php7 fixes
[Pman.Builder] / Generator / JSON.php
1 <?php
2
3 require_once 'Services/JSON.php';
4
5
6 class Pman_Builder_Generator_JSON extends Services_JSON 
7 {
8      var $indent = 0;
9
10     var $crlf = "\n";
11     var $tab = "\t";
12  
13     function __construct($use = 0) {
14          if (is_array($use)) {
15             foreach($use as $k=>$v) {
16                 $this->$k = $v;
17             }
18         } else {
19             $this->use = $use;
20             
21         }
22         $this->indent = 0;
23         
24     }
25     
26     function _encode($var) 
27     {
28          
29         switch (gettype($var)) {
30             case 'boolean':
31                 return $var ? 'true' : 'false';
32
33             case 'NULL':
34                 return 'null';
35
36             case 'integer':
37                 return (int) $var;
38
39             case 'double':
40             case 'float':
41                 return (float) $var;
42
43             case 'string':
44                 // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
45                 $ascii = '';
46                 $strlen_var = strlen($var);
47
48                /*
49                 * Iterate over every character in the string,
50                 * escaping with a slash or encoding to UTF-8 where necessary
51                 */
52                 for ($c = 0; $c < $strlen_var; ++$c) {
53
54                     $ord_var_c = ord($var[$c]);
55
56                     switch (true) {
57                         case $ord_var_c == 0x08:
58                             $ascii .= '\b';
59                             break;
60                         case $ord_var_c == 0x09:
61                             $ascii .= '\t';
62                             break;
63                         case $ord_var_c == 0x0A:
64                             $ascii .= '\n';
65                             break;
66                         case $ord_var_c == 0x0C:
67                             $ascii .= '\f';
68                             break;
69                         case $ord_var_c == 0x0D:
70                             $ascii .= '\r';
71                             break;
72
73                         case $ord_var_c == 0x22:
74                         case $ord_var_c == 0x2F:
75                         case $ord_var_c == 0x5C:
76                             // double quote, slash, slosh
77                             $ascii .= '\\'.$var[$c];
78                             break;
79
80                         case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
81                             // characters U-00000000 - U-0000007F (same as ASCII)
82                             $ascii .= $var[$c];
83                             break;
84
85                         case (($ord_var_c & 0xE0) == 0xC0):
86                             // characters U-00000080 - U-000007FF, mask 110XXXXX
87                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
88                             if ($c+1 >= $strlen_var) {
89                                 $c += 1;
90                                 $ascii .= '?';
91                                 break;
92                             }
93                             
94                             $char = pack('C*', $ord_var_c, ord($var[$c + 1]));
95                             $c += 1;
96                             $utf16 = $this->utf82utf16($char);
97                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
98                             break;
99
100                         case (($ord_var_c & 0xF0) == 0xE0):
101                             if ($c+2 >= $strlen_var) {
102                                 $c += 2;
103                                 $ascii .= '?';
104                                 break;
105                             }
106                             // characters U-00000800 - U-0000FFFF, mask 1110XXXX
107                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
108                             $char = pack('C*', $ord_var_c,
109                                          @ord($var[$c + 1]),
110                                          @ord($var[$c + 2]));
111                             $c += 2;
112                             $utf16 = $this->utf82utf16($char);
113                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
114                             break;
115
116                         case (($ord_var_c & 0xF8) == 0xF0):
117                             if ($c+3 >= $strlen_var) {
118                                 $c += 3;
119                                 $ascii .= '?';
120                                 break;
121                             }
122                             // characters U-00010000 - U-001FFFFF, mask 11110XXX
123                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
124                             $char = pack('C*', $ord_var_c,
125                                          ord($var[$c + 1]),
126                                          ord($var[$c + 2]),
127                                          ord($var[$c + 3]));
128                             $c += 3;
129                             $utf16 = $this->utf82utf16($char);
130                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
131                             break;
132
133                         case (($ord_var_c & 0xFC) == 0xF8):
134                             // characters U-00200000 - U-03FFFFFF, mask 111110XX
135                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
136                             if ($c+4 >= $strlen_var) {
137                                 $c += 4;
138                                 $ascii .= '?';
139                                 break;
140                             }
141                             $char = pack('C*', $ord_var_c,
142                                          ord($var[$c + 1]),
143                                          ord($var[$c + 2]),
144                                          ord($var[$c + 3]),
145                                          ord($var[$c + 4]));
146                             $c += 4;
147                             $utf16 = $this->utf82utf16($char);
148                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
149                             break;
150
151                         case (($ord_var_c & 0xFE) == 0xFC):
152                         if ($c+5 >= $strlen_var) {
153                                 $c += 5;
154                                 $ascii .= '?';
155                                 break;
156                             }
157                             // characters U-04000000 - U-7FFFFFFF, mask 1111110X
158                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
159                             $char = pack('C*', $ord_var_c,
160                                          ord($var[$c + 1]),
161                                          ord($var[$c + 2]),
162                                          ord($var[$c + 3]),
163                                          ord($var[$c + 4]),
164                                          ord($var[$c + 5]));
165                             $c += 5;
166                             $utf16 = $this->utf82utf16($char);
167                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
168                             break;
169                     }
170                 }
171
172                 return (strpos($ascii, "'") > -1) ? '"'.$ascii.'"' : "'".$ascii."'";
173
174             case 'array':
175                /*
176                 * As per JSON spec if any array key is not an integer
177                 * we must treat the the whole array as an object. We
178                 * also try to catch a sparsely populated associative
179                 * array with numeric keys here because some JS engines
180                 * will create an array with empty indexes up to
181                 * max_index which can cause memory issues and because
182                 * the keys, which may be relevant, will be remapped
183                 * otherwise.
184                 *
185                 * As per the ECMA and JSON specification an object may
186                 * have any string as a property. Unfortunately due to
187                 * a hole in the ECMA specification if the key is a
188                 * ECMA reserved word or starts with a digit the
189                 * parameter is only accessible using ECMAScript's
190                 * bracket notation.
191                 */
192
193                 // treat as a JSON object
194                 if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
195                     $var = (object) $var;
196                     // drop throug to object.!
197                 } else {
198                         
199
200                     // treat it like a regular array
201                     $elements = array_map(array($this, '_encode'), $var);
202
203                     foreach($elements as $element) {
204                         if(Services_JSON::isError($element)) {
205                             return $element;
206                         }
207                     }
208
209                     return '[' . join(',', $elements) . ']';
210                 }
211                 // fall through for associative arrays..
212                 
213             case 'object':
214                 $vars = get_object_vars($var);
215                 $this->indent++;
216                 $properties = array_map(array($this, 'name_value'),
217                                         array_keys($vars),
218                                         array_values($vars));
219                 $this->indent--;
220                 foreach($properties as $property) {
221                     if(Services_JSON::isError($property)) {
222                         return $property;
223                     }
224                 }
225                 
226                 $ind = str_repeat($this->tab, $this->indent);
227                 $indx = $ind. $this->tab;
228                 return "{" . $this->crlf . $indx .  join(",". $this->crlf . $indx, $properties) . $this->crlf .$ind."}";
229
230             default:
231                 return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
232                     ? 'null'
233                     : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
234         }
235     }
236     
237     function name_value($name, $value)
238     {
239         $encoded_value = $this->_encode($value);
240
241         if(Services_JSON::isError($encoded_value)) {
242             return $encoded_value;
243         }
244         $lv = strval($name);
245         // do not escape keyvalues if they are just text, and not keywords...
246         if (preg_match('/^[a-z_]+$/i', $lv)) {
247             if (!in_array($lv, $GLOBALS['Pman_Builder_Generator_JSON']['keywords'])) {
248                 return $lv .' : ' . $encoded_value;
249             }
250             
251         }
252         
253         return $this->_encode(strval($name)) . ' : ' . $encoded_value;
254     }
255
256 }
257
258
259 $GLOBALS['Pman_Builder_Generator_JSON']['keywords'] = array(
260     'break',
261     'continue',
262     'do',
263     'for',
264     'import',
265     'new',
266     'this',
267     'void',
268     'case',
269     'default',
270     'else',
271     'function',
272     'in',
273     'return',
274     'typeof',
275     'while',
276     'comment',
277     'delete',
278     'export',
279     'if',
280     'label',
281     'switch',
282     'var',
283     'with',
284     'abstract',
285     'implements',
286     'protected',
287     'boolean',
288     'instanceOf',
289     'public',
290     'byte',
291     'int',
292     'short',
293     'char',
294     'interface',
295     'static',
296     'double',
297     'long',
298     'synchronized',
299     'false',
300     'native',
301     'throws',
302     'final',
303     'null',
304     'transient',
305     'float',
306     'package',
307     'true',
308     'goto',
309     'private',
310     'catch',
311     'enum',
312     'throw',
313     'class',
314     'extends',
315     'try',
316     'const',
317     'finally',
318     'debugger',
319     'super',
320     'alert',
321     'eval',
322     'Link',
323     'outerHeight',
324     'scrollTo',
325     'Anchor',
326     'FileUpload',
327     'location',
328     'outerWidth',
329     'Select',
330     'Area',
331     'find',
332     'Location',
333     'Packages',
334     'self',
335     'arguments',
336     'focus',
337     'locationbar',
338     'pageXoffset',
339     'setInterval',
340     'Array',
341     'Form',
342     'Math',
343     'pageYoffset',
344     'setTimeout',
345     'assign',
346     'Frame',
347     'menubar',
348     'parent',
349     'status',
350     'blur',
351     'frames',
352     'MimeType',
353     'parseFloat',
354     'statusbar',
355     'Boolean',
356     'Function',
357     'moveBy',
358     'parseInt',
359     'stop',
360     'Button',
361     'getClass',
362     'moveTo',
363     'Password',
364     'String',
365     'callee',
366     'Hidden',
367     // 'name', // why???
368     'personalbar',
369     'Submit',
370     'caller',
371     'history',
372     'NaN',
373     'Plugin',
374     'sun',
375     'captureEvents',
376     'History',
377     'navigate',
378     'print',
379     'taint',
380     'Checkbox',
381     'home',
382     'navigator',
383     'prompt',
384     'Text',
385     'clearInterval',
386     'Image',
387     'Navigator',
388     'prototype',
389     'Textarea',
390     'clearTimeout',
391     'Infinity',
392     'netscape',
393     'Radio',
394     'toolbar',
395     'close',
396     'innerHeight',
397     'Number',
398     'ref',
399     'top',
400     'closed',
401     'innerWidth',
402     'Object',
403     'RegExp',
404     'toString',
405     'confirm',
406     'isFinite',
407     'onBlur',
408     'releaseEvents',
409     'unescape',
410     'constructor',
411     'isNan',
412     'onError',
413     'Reset',
414     'untaint',
415     'Date',
416     'java',
417     'onFocus',
418     'resizeBy',
419     'unwatch',
420     'defaultStatus',
421     'JavaArray',
422     'onLoad',
423     'resizeTo',
424     'valueOf',
425     'document',
426     'JavaClass',
427     'onUnload',
428     'routeEvent',
429     'watch',
430     'Document',
431     'JavaObject',
432     'open',
433     'scroll',
434     'window',
435     'Element',
436     'JavaPackage',
437     'opener',
438     'scrollbars',
439     'Window',
440     'escape',
441     'length',
442     'Option',
443     'scrollBy'
444 );