source: sandbox/2.3-MailArchiver/expressoMail1_2/spell_checker/cpaint/json.php @ 6779

Revision 6779, 13.2 KB checked in by rafaelraymundo, 12 years ago (diff)

Ticket #2946 - Liberado Expresso(branch 2.3) integrado ao MailArchiver?.

Line 
1<?php
2/**
3* The content of this file is (c) 2003-2005 digital media center GmbH
4* All rights reserved
5*
6* a JSON parser / generator.
7* implemented as 100% compatible port of the original JSON parser
8* by Douglas Crockford on http://www.JSON.org.
9*
10* @package      JSON
11* @access       public
12* @copyright    Copyright (c) 2005-2006 Dominique Stender - http://sf.net/projects/cpaint
13* @license      http://www.crockford.com/JSON/license.html
14* @author       Dominique Stender <dstender@st-webdevelopment.de>
15* @version      $Id$
16*/
17
18 
19 
20  /**
21  * a JSON parser / generator
22  *
23  * @access public
24  * @author Dominique Stender <dst@dmc.de>
25  * @version 1.0.1
26  */
27  class JSON {
28    /**
29    * line counter
30    *
31    * @access   private
32    * @var      integer    $at
33    */
34    var $at = 0;
35   
36    /**
37    *
38    * @access   private
39    * @var      string    $ch
40    */
41    var $ch = ' ';
42   
43    /**
44    * JSON representation
45    *
46    * @access   private
47    * @var      string    $text
48    */
49    var $text = '';
50   
51    /**
52    * takes an arbitrary PHP data structure and generates a valid JSON representation from it
53    *
54    * @param    mixed    $arg    an arbitrary PHP data structure
55    * @access   public
56    * @return   string
57    * @version  1.0.1   fixed tests whether $s has content by using strlen(). this enables the user to use 0 as very first character
58    */
59    function stringify($arg) {
60      $returnValue  = '';
61      $c            = '';
62      $i            = '';
63      $l            = '';
64      $s            = '';
65      $v            = '';
66      $numeric      = true;
67
68      switch (gettype($arg)) {
69
70        case 'array':
71          // do a test whether all array keys are numeric
72          foreach ($arg as $i => $v) {
73            if (!is_numeric($i)) {
74              $numeric = false;
75              break;
76            }
77          }
78         
79          if ($numeric) {
80           
81            foreach ($arg as $i => $v) {
82              if (strlen($s) > 0) {
83                $s .= ',';
84              }
85                         
86              $s .= $this->stringify($arg[$i]);
87            } // end: foreach
88                     
89            $returnValue = '[' . $s . ']';
90         
91          } else {
92            // associative array
93            foreach ($arg as $i => $v) {
94              if (strlen($s) > 0) {
95                $s .= ',';
96              }
97              $s .= $this->stringify($i) . ':' . $this->stringify($arg[$i]);
98            }
99            // return as object
100            $returnValue = '{' . $s . '}';
101          }
102          break;
103         
104        case 'object':
105         
106          foreach (get_object_vars($arg) as $i => $v) {
107            $v = $this->stringify($v);
108                           
109            if (strlen($s) > 0) {
110              $s .= ',';
111            }
112                           
113            $s .= $this->stringify($i) . ':' . $v;
114          }
115                   
116          $returnValue = '{' . $s . '}';
117          break;
118           
119        case 'integer':
120        case 'double':
121          $returnValue = is_numeric($arg) ? (string) $arg : 'null';
122          break;
123           
124        case 'string':
125          $l = strlen($arg);
126          $s = '"';
127               
128          for ($i = 0; $i < $l; $i++) {
129            $c = $arg{$i};
130                   
131            if (ord($c) >= ord(' ')) {
132                       
133              if ($c == '\\'
134                || $c == '"') {
135                           
136                $s .= '\\';
137              }
138              $s .= $c;
139                   
140            } else {
141                       
142              switch ($c) {
143                           
144                case '\b':
145                  $s .= '\\b';
146                  break;
147                           
148                case '\f':
149                  $s .= '\\f';
150                  break;
151                           
152                case '\n':
153                  $s .= '\\n';
154                  break;
155                           
156                case '\r':
157                  $s .= '\\r';
158                  break;
159                           
160                case '\t':
161                  $s .= '\\t';
162                  break;
163                           
164                default:
165                  $s .= '\u00' . sprintf('%02x', ord($c));
166              }
167            }
168          }
169          $returnValue = $s . '"';
170          break;
171         
172        case 'boolean':
173          $returnValue = (string) $arg;
174          break;
175         
176        default:
177          $returnValue = 'null';
178      }
179     
180      return $returnValue;
181    }
182   
183   
184    /**
185    * parses the given string into a PHP data structure
186    *
187    * @param    string    $text    JSON data representation
188    * @access   public
189    * @return   mixed
190    */
191    function parse($text) {
192      $this->at  = 0;
193      $this->ch  = ' ';
194      $this->text  = $text;
195     
196      return $this->val();
197    }
198   
199    /**
200    * triggers a PHP_ERROR
201    *
202    * @access   private
203    * @param    string    $m    error message
204    * @return   void
205    */
206    function error($m) {
207      trigger_error($m . ' at offset ' . $this->at . ': ' . $this->text, E_USER_ERROR);
208    }
209
210    /**
211    * returns the next character of a JSON string
212    *
213    * @access  private
214    * @return  string
215    */
216    function next() {
217      $this->ch = $this->text{$this->at};
218      $this->at++;
219      return $this->ch;
220    }
221
222    /**
223    * handles whitespace and comments
224    *
225    * @access  private
226    * @return  void
227    */
228    function white() {
229   
230      while ($this->ch != ''
231        && ord($this->ch) <= ord(' ')) {
232
233        $this->next();
234      }
235    }
236
237    /**
238    * handles strings
239    *
240    * @access  private
241    * @return  void
242    */
243    function str() {
244      $i = '';
245      $s = '';
246      $t = '';
247      $u = '';
248
249      if ($this->ch == '"') {
250
251        while ($this->next() !== null) {
252                   
253          if ($this->ch == '"') {
254            $this->next();
255            return $s;
256                   
257          } elseif ($this->ch == '\\') {
258                       
259            switch ($this->next()) {
260              case 'b':
261                $s .= '\b';
262                break;
263                         
264              case 'f':
265                $s .= '\f';
266                break;
267                         
268              case 'n':
269                $s .= '\n';
270                break;
271                         
272              case 'r':
273                $s .= '\r';
274                break;
275                         
276              case 't':
277                $s .= '\t';
278                break;
279                         
280              case 'u':
281                $u = 0;
282                             
283                for ($i = 0; $i < 4; $i += 1) {
284                  $t = (integer) sprintf('%01c', hexdec($this->next()));
285                                 
286                  if (!is_numeric($t)) {
287                    break 2;
288                  }
289                  $u = $u * 16 + $t;
290                }
291                             
292                $s .= chr($u);
293                break;
294                         
295              default:
296                $s .= $this->ch;
297            }
298          } else {
299            $s .= $this->ch;
300          }
301        }
302      }
303     
304      $this->error('Bad string');
305    }
306
307    /**
308    * handless arrays
309    *
310    * @access  private
311    * @return  void
312    */
313    function arr() {
314      $a = array();
315
316      if ($this->ch == '[') {
317        $this->next();
318        $this->white();
319               
320        if ($this->ch == ']') {
321          $this->next();
322          return $a;
323        }
324               
325        while ($this->ch) {
326          array_push($a, $this->val());
327          $this->white();
328                   
329          if ($this->ch == ']') {
330            $this->next();
331            return $a;
332                   
333          } elseif ($this->ch != ',') {
334            break;
335          }
336                   
337          $this->next();
338          $this->white();
339        }
340           
341        $this->error('Bad array');
342      }
343    }
344   
345    /**
346    * handles objects
347    *
348    * @access  public
349    * @return  void
350    */
351    function obj() {
352      $k = '';
353      $o = new stdClass();
354
355      if ($this->ch == '{') {
356        $this->next();
357        $this->white();
358               
359        if ($this->ch == '}') {
360          $this->next();
361          return $o;
362        }
363               
364        while ($this->ch) {
365          $k = $this->str();
366          $this->white();
367                   
368          if ($this->ch != ':') {
369            break;
370          }
371                   
372          $this->next();
373          $o->$k = $this->val();
374          $this->white();
375                   
376          if ($this->ch == '}') {
377            $this->next();
378            return $o;
379                   
380          } elseif ($this->ch != ',') {
381            break;
382          }
383                   
384          $this->next();
385          $this->white();
386        }
387      }
388     
389      $this->error('Bad object');
390    }
391
392    /**
393    * handles objects
394    *
395    * @access  public
396    * @return  void
397    */
398    function assoc() {
399      $k = '';
400      $a = array();
401
402      if ($this->ch == '<') {
403        $this->next();
404        $this->white();
405               
406        if ($this->ch == '>') {
407          $this->next();
408          return $a;
409        }
410               
411        while ($this->ch) {
412          $k = $this->str();
413          $this->white();
414                   
415          if ($this->ch != ':') {
416            break;
417          }
418                   
419          $this->next();
420          $a[$k] = $this->val();
421          $this->white();
422                   
423          if ($this->ch == '>') {
424            $this->next();
425            return $a;
426                   
427          } elseif ($this->ch != ',') {
428            break;
429          }
430                   
431          $this->next();
432          $this->white();
433        }
434      }
435     
436      $this->error('Bad associative array');
437    }
438
439    /**
440    * handles numbers
441    *
442    * @access  private
443    * @return  void
444    */
445    function num() {
446      $n = '';
447      $v = '';
448           
449      if ($this->ch == '-') {
450        $n = '-';
451        $this->next();
452      }
453           
454      while ($this->ch >= '0'
455        && $this->ch <= '9') {
456       
457        $n .= $this->ch;
458        $this->next();
459      }
460           
461      if ($this->ch == '.') {
462        $n .= '.';
463               
464        while ($this->next()
465          && $this->ch >= '0'
466          && $this->ch <= '9') {
467         
468            $n .= $this->ch;
469          }
470        }
471           
472      if ($this->ch == 'e'
473        || $this->ch == 'E') {
474               
475        $n .= 'e';
476        $this->next();
477               
478        if ($this->ch == '-'
479          || $this->ch == '+') {
480         
481          $n .= $this->ch;
482          $this->next();
483        }
484
485        while ($this->ch >= '0'
486          && $this->ch <= '9') {
487
488          $n .= $this->ch;
489          $this->next();
490        }
491      }
492           
493      $v += $n;
494     
495      if (!is_numeric($v)) {
496        $this->error('Bad number');
497     
498      } else {
499        return $v;
500      } // end: if
501    }
502
503    /**
504    * handles words
505    *
506    * @access  private
507    * @return  mixed
508    */
509    function word() {
510      switch ($this->ch) {
511             
512        case 't':
513                   
514          if ($this->next() == 'r'
515            && $this->next() == 'u'
516            && $this->next() == 'e') {
517                       
518            $this->next();
519            return true;
520          }
521          break;
522               
523        case 'f':
524          if ($this->next() == 'a'
525            && $this->next() == 'l'
526            && $this->next() == 's'
527            && $this->next() == 'e') {
528                       
529            $this->next();
530            return false;
531          }
532          break;
533               
534        case 'n':
535          if ($this->next() == 'u'
536            && $this->next() == 'l'
537            && $this->next() == 'l') {
538                       
539            $this->next();
540            return null;
541          }
542          break;
543      }
544           
545      $this->error('Syntax error');
546    }
547
548    /**
549    * generic value handler
550    *
551    * @access  private
552    * @return  mixed
553    */
554    function val() {
555      $this->white();
556           
557      switch ($this->ch) {
558               
559        case '{':
560          return $this->obj();
561               
562        case '[':
563          return $this->arr();
564               
565        case '<':
566          return $this->assoc();
567               
568        case '"':
569          return $this->str();
570               
571        case '-':
572          return $this->num();
573               
574        default:
575          return ($this->ch >= '0' && $this->ch <= '9') ? $this->num() : $this->word();
576      }
577    }
578  }
579 
580?>
Note: See TracBrowser for help on using the repository browser.