OSDN Git Service

v1.1.1
[nucleus-jp/nucleus-plugins.git] / trunk / NP_OpenId / sharedlibs / Jsphon / Encoder.php
1 <?php
2 //
3 // +--------------------------------------------------------------------+
4 // | PHP version 4 and 5                                                |
5 // +--------------------------------------------------------------------+
6 // | Copyright (c) 2006 Hawk                                            |
7 // +--------------------------------------------------------------------+
8 // | This source file is subject to version 3.00 of the PHP License,    |
9 // | that is available at http://www.php.net/license/3_0.txt.           |
10 // | If you did not receive a copy of the PHP license and are unable to |
11 // | obtain it through the world-wide-web, please send a note to        |
12 // | license@php.net so we can mail you a copy immediately.             |
13 // +--------------------------------------------------------------------+
14 // | Authors: Hawk <scholar@hawklab.jp>                                 |
15 // +--------------------------------------------------------------------+
16 //
17 //
18
19 /**
20  * Converts to JSON format.
21  * 
22  * example:
23  * <code>
24  * //create a new instance of Jsphon_Encoder
25  * $json =& new Jsphon_Encoder();
26  * 
27  * //convert a complex value to JSON notation, and send it to the browser
28  * $value = array('foo', 'bar', array('hoge' => array(1,2)));
29  * $output = $json->encode($value);
30  * 
31  * print_r($output);
32  * //prints: ["foo","bar",{"hoge":[1,2]}]
33  * </code>
34  * 
35  * @author Hawk
36  */
37 class Jsphon_Encoder
38 {
39     var $_mbstring;
40     
41     var $_escapeNonASCII;
42     
43     var $_escapeOverUCS2;
44     
45     var $_transTable;
46     
47     var $_utf8UCS2reg;
48     
49     var $_utf8overUCS2reg;
50     
51     /**
52      * constructs a new Jsphon_Encoder instance.
53      * 
54      * @param bool $escapeNonASCII  If true, encode() converts non-ASCII characters 
55      *                              to Unicode escape sequence (\uXXXX).
56      * @param bool $escapeOverUCS2  If true, encode() converts all the non-ASCII characters 
57      *                              that is encodable in UTF-16 to Unicode escape sequence.
58      *                              This parameter affects the encoder's behavior 
59      *                              only if $escapeNonASCII is set to true and 
60      *                              the multibyte string extension is available.
61      * 
62      */
63     function Jsphon_Encoder($escapeNonASCII=true, $escapeOverUCS2=false)
64     {
65         $this->_escapeNonASCII = $escapeNonASCII;
66         $this->_escapeOverUCS2 = $escapeOverUCS2;
67         $this->_mbstring = extension_loaded('mbstring');
68
69         $this->_transTable = array(
70             "\x08" => '\b',
71             "\x09" => '\t',
72             "\x0A" => '\n',
73             "\x0C" => '\f',
74             "\x0D" => '\r',
75             "\x22" => '\"',
76             "\x2F" => '\/',
77             "\x5C" => '\\\\'
78         );
79         
80         $utf8ucs2 = '[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}';
81         $utf16sur = '[\xF0-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2}';
82         $this->_utf8UCS2reg = "/{$utf8ucs2}/";
83         $this->_utf8overUCS2reg = "/{$utf8ucs2}|{$utf16sur}/";
84     }
85     
86     /**
87      * encodes an arbitrary variables into JSON format.
88      * 
89      * If $_escapeNonASCII is set to true, 
90      * encode() removes all non-ASCII characters to make sure that 
91      * returning value dosen't contain any non-ASCII characters.
92      * 
93      * @param mixed $value
94      * @return string
95      */
96     function encode($value)
97     {
98         $json = $this->_encode($value);
99         if($this->_escapeNonASCII) {
100             $json = preg_replace('/[\x80-\xFF]/', '', $json);
101         }
102         return $json;
103     }
104     
105     function _encode($value)
106     {
107         if($value === null) {
108             return 'null';
109             
110         } elseif(is_bool($value)) {
111             return $value ? 'true' : 'false';
112             
113         } elseif(is_int($value)) {
114             return (int)$value;
115             
116         } elseif(is_float($value)) {
117             return (float)$value;
118             
119         } elseif(is_string($value)) {
120             return '"'. $this->_encodeString($value) .'"';
121
122         } elseif(is_array($value)) {
123             if(($len = count($value)) > 0 &&
124                array_keys($value) !== range(0, $len - 1)) {
125                 return $this->_encodeObject($value);
126             } else {
127                 return '['. join(',', array_map(array(&$this, '_encode'), $value)) .']';
128             }
129
130         } elseif(is_object($value)) {
131             return $this->_encodeObject($value);
132             
133         }
134         
135         return 'null';
136     }
137     
138     function _encodeObject($arr)
139     {
140         $result = array();
141         foreach($arr as $name => $value) {
142             $result[] = $this->_encode((string)$name) .':'. $this->_encode($value);
143         }
144         return '{'. join(',', $result) ."}";
145     }
146     
147     function _encodeString($str)
148     {
149         $str = strtr($str, $this->_transTable);
150         
151         if(!$this->_escapeNonASCII) {
152             return $str;
153         }
154         
155         if(!$this->_mbstring) {
156             return $this->_escapeNonASCIIWithoutMbstring($str);
157         }
158         
159         if($this->_escapeOverUCS2) {
160             return $this->_escapeNonASCIIOverUCS2($str);
161         } else {
162             return $this->_escapeNonASCII($str);
163         }
164     }
165     
166     function _escapeNonASCII($str) 
167     {
168         $transTable = array();
169
170         if(!preg_match_all($this->_utf8UCS2reg, $str, $matches)) {
171             return $str;
172         }
173         
174         foreach($matches[0] as $utf8char) {
175             if(isset($transTable[$utf8char])) {
176                 continue;
177             }
178             $transTable[$utf8char] = $this->_formatSeq(
179                 mb_convert_encoding($utf8char, 'UTF-16', 'UTF-8'));
180         }
181         return strtr($str, $transTable);
182     }
183
184     function _escapeNonASCIIOverUCS2($str) 
185     {
186         $transTable = array();
187
188         if(!preg_match_all($this->_utf8overUCS2reg, $str, $matches)) {
189             return $str;
190         }
191         
192         foreach($matches[0] as $utf8char) {
193             if(isset($transTable[$utf8char])) {
194                 continue;
195             }
196             $utf16char = mb_convert_encoding($utf8char, 'UTF-16', 'UTF-8');
197             
198             if(($l = strlen($utf16char)) == 2) {
199                 $transTable[$utf8char] = $this->_formatSeq($utf16char);
200             } elseif($l == 4) {
201                 $transTable[$utf8char] = 
202                     $this->_formatSeq(substr($utf16char, 0, 2)) . $this->_formatSeq(substr($utf16char, 2));
203             }
204             
205         }
206         return strtr($str, $transTable);
207     }
208
209     function _escapeNonASCIIWithoutMbstring($str) 
210     {
211         $transTable = array();
212
213         if(!preg_match_all($this->_utf8UCS2reg, $str, $matches)) {
214             return $str;
215         }
216         
217         foreach($matches[0] as $utf8char) {
218             if(isset($transTable[$utf8char])) {
219                 continue;
220             }
221             
222             switch(strlen($utf8char)) {
223             case 2:
224                 $code = (
225                  ((ord($utf8char{0}) & 0x1F) << 6) |
226                   (ord($utf8char{1}) & 0x3F)
227                 );
228                 break;
229
230             case 3:
231                 $code = (
232                  ((ord($utf8char{0}) & 0x0F) << 12) |
233                  ((ord($utf8char{1}) & 0x3F) << 6 ) |
234                   (ord($utf8char{2}) & 0x3F)
235                 );
236                 break;
237             default:
238             }
239             $transTable[$utf8char] = '\u'. substr('0000'. dechex($code), -4);
240         }
241         return strtr($str, $transTable);
242     }
243
244     function _formatSeq($u16)
245     {
246         return '\u'. substr('0000'. bin2hex($u16), -4);
247     }
248 }
249
250 ?>