includes/json2.php
changeset 1227 bdac73ed481e
parent 1111 8fae8fb3cbb1
equal deleted inserted replaced
1226:de56132c008d 1227:bdac73ed481e
    27  * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
    27  * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
    28  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    28  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    29  */
    29  */
    30 class Zend_Json_Encoder
    30 class Zend_Json_Encoder
    31 {
    31 {
    32     /**
    32 		/**
    33      * Whether or not to check for possible cycling
    33  		* Whether or not to check for possible cycling
    34      *
    34  		*
    35      * @var boolean
    35  		* @var boolean
    36      */
    36  		*/
    37     protected $_cycleCheck;
    37 		protected $_cycleCheck;
    38 
    38 
    39     /**
    39 		/**
    40      * Array of visited objects; used to prevent cycling.
    40  		* Array of visited objects; used to prevent cycling.
    41      *
    41  		*
    42      * @var array
    42  		* @var array
    43      */
    43  		*/
    44     protected $_visited = array();
    44 		protected $_visited = array();
    45 
    45 
    46     /**
    46 		/**
    47      * Constructor
    47  		* Constructor
    48      *
    48  		*
    49      * @param boolean $cycleCheck Whether or not to check for recursion when encoding
    49  		* @param boolean $cycleCheck Whether or not to check for recursion when encoding
    50      * @return void
    50  		* @return void
    51      */
    51  		*/
    52     protected function __construct($cycleCheck = false)
    52 		protected function __construct($cycleCheck = false)
    53     {
    53 		{
    54         $this->_cycleCheck = $cycleCheck;
    54 				$this->_cycleCheck = $cycleCheck;
    55     }
    55 		}
    56 
    56 
    57     /**
    57 		/**
    58      * Use the JSON encoding scheme for the value specified
    58  		* Use the JSON encoding scheme for the value specified
    59      *
    59  		*
    60      * @param mixed $value The value to be encoded
    60  		* @param mixed $value The value to be encoded
    61      * @param boolean $cycleCheck Whether or not to check for possible object recursion when encoding
    61  		* @param boolean $cycleCheck Whether or not to check for possible object recursion when encoding
    62      * @return string  The encoded value
    62  		* @return string  The encoded value
    63      */
    63  		*/
    64     public static function encode($value, $cycleCheck = false)
    64 		public static function encode($value, $cycleCheck = false)
    65     {
    65 		{
    66         $encoder = new Zend_Json_Encoder(($cycleCheck) ? true : false);
    66 				$encoder = new Zend_Json_Encoder(($cycleCheck) ? true : false);
    67 
    67 
    68         return $encoder->_encodeValue($value);
    68 				return $encoder->_encodeValue($value);
    69     }
    69 		}
    70 
    70 
    71     /**
    71 		/**
    72      * Recursive driver which determines the type of value to be encoded
    72  		* Recursive driver which determines the type of value to be encoded
    73      * and then dispatches to the appropriate method. $values are either
    73  		* and then dispatches to the appropriate method. $values are either
    74      *    - objects (returns from {@link _encodeObject()})
    74  		*    - objects (returns from {@link _encodeObject()})
    75      *    - arrays (returns from {@link _encodeArray()})
    75  		*    - arrays (returns from {@link _encodeArray()})
    76      *    - basic datums (e.g. numbers or strings) (returns from {@link _encodeDatum()})
    76  		*    - basic datums (e.g. numbers or strings) (returns from {@link _encodeDatum()})
    77      *
    77  		*
    78      * @param $value mixed The value to be encoded
    78  		* @param $value mixed The value to be encoded
    79      * @return string Encoded value
    79  		* @return string Encoded value
    80      */
    80  		*/
    81     protected function _encodeValue(&$value)
    81 		protected function _encodeValue(&$value)
    82     {
    82 		{
    83         if (is_object($value)) {
    83 				if (is_object($value)) {
    84             return $this->_encodeObject($value);
    84 						return $this->_encodeObject($value);
    85         } else if (is_array($value)) {
    85 				} else if (is_array($value)) {
    86             return $this->_encodeArray($value);
    86 						return $this->_encodeArray($value);
    87         }
    87 				}
    88 
    88 
    89         return $this->_encodeDatum($value);
    89 				return $this->_encodeDatum($value);
    90     }
    90 		}
    91 
    91 
    92 
    92 
    93 
    93 
    94     /**
    94 		/**
    95      * Encode an object to JSON by encoding each of the public properties
    95  		* Encode an object to JSON by encoding each of the public properties
    96      *
    96  		*
    97      * A special property is added to the JSON object called '__className'
    97  		* A special property is added to the JSON object called '__className'
    98      * that contains the name of the class of $value. This is used to decode
    98  		* that contains the name of the class of $value. This is used to decode
    99      * the object on the client into a specific class.
    99  		* the object on the client into a specific class.
   100      *
   100  		*
   101      * @param $value object
   101  		* @param $value object
   102      * @return string
   102  		* @return string
   103      * @throws Zend_Json_Exception If recursive checks are enabled and the object has been serialized previously
   103  		* @throws Zend_Json_Exception If recursive checks are enabled and the object has been serialized previously
   104      */
   104  		*/
   105     protected function _encodeObject(&$value)
   105 		protected function _encodeObject(&$value)
   106     {
   106 		{
   107         if ($this->_cycleCheck) {
   107 				if ($this->_cycleCheck) {
   108             if ($this->_wasVisited($value)) {
   108 						if ($this->_wasVisited($value)) {
   109                 throw new Zend_Json_Exception(
   109 								throw new Zend_Json_Exception(
   110                     'Cycles not supported in JSON encoding, cycle introduced by '
   110 										'Cycles not supported in JSON encoding, cycle introduced by '
   111                     . 'class "' . get_class($value) . '"'
   111 										. 'class "' . get_class($value) . '"'
   112                 );
   112 								);
   113             }
   113 						}
   114 
   114 
   115             $this->_visited[] = $value;
   115 						$this->_visited[] = $value;
   116         }
   116 				}
   117 
   117 
   118         $props = '';
   118 				$props = '';
   119         foreach (get_object_vars($value) as $name => $propValue) {
   119 				foreach (get_object_vars($value) as $name => $propValue) {
   120             if (isset($propValue)) {
   120 						if (isset($propValue)) {
   121                 $props .= ','
   121 								$props .= ','
   122                         . $this->_encodeValue($name)
   122 												. $this->_encodeValue($name)
   123                         . ':'
   123 												. ':'
   124                         . $this->_encodeValue($propValue);
   124 												. $this->_encodeValue($propValue);
   125             }
   125 						}
   126         }
   126 				}
   127 
   127 
   128         return '{"__className":"' . get_class($value) . '"'
   128 				return '{"__className":"' . get_class($value) . '"'
   129                 . $props . '}';
   129 								. $props . '}';
   130     }
   130 		}
   131 
   131 
   132 
   132 
   133     /**
   133 		/**
   134      * Determine if an object has been serialized already
   134  		* Determine if an object has been serialized already
   135      *
   135  		*
   136      * @param mixed $value
   136  		* @param mixed $value
   137      * @return boolean
   137  		* @return boolean
   138      */
   138  		*/
   139     protected function _wasVisited(&$value)
   139 		protected function _wasVisited(&$value)
   140     {
   140 		{
   141         if (in_array($value, $this->_visited, true)) {
   141 				if (in_array($value, $this->_visited, true)) {
   142             return true;
   142 						return true;
   143         }
   143 				}
   144 
   144 
   145         return false;
   145 				return false;
   146     }
   146 		}
   147 
   147 
   148 
   148 
   149     /**
   149 		/**
   150      * JSON encode an array value
   150  		* JSON encode an array value
   151      *
   151  		*
   152      * Recursively encodes each value of an array and returns a JSON encoded
   152  		* Recursively encodes each value of an array and returns a JSON encoded
   153      * array string.
   153  		* array string.
   154      *
   154  		*
   155      * Arrays are defined as integer-indexed arrays starting at index 0, where
   155  		* Arrays are defined as integer-indexed arrays starting at index 0, where
   156      * the last index is (count($array) -1); any deviation from that is
   156  		* the last index is (count($array) -1); any deviation from that is
   157      * considered an associative array, and will be encoded as such.
   157  		* considered an associative array, and will be encoded as such.
   158      *
   158  		*
   159      * @param $array array
   159  		* @param $array array
   160      * @return string
   160  		* @return string
   161      */
   161  		*/
   162     protected function _encodeArray(&$array)
   162 		protected function _encodeArray(&$array)
   163     {
   163 		{
   164         $tmpArray = array();
   164 				$tmpArray = array();
   165 
   165 
   166         // Check for associative array
   166 				// Check for associative array
   167         if (!empty($array) && (array_keys($array) !== range(0, count($array) - 1))) {
   167 				if (!empty($array) && (array_keys($array) !== range(0, count($array) - 1))) {
   168             // Associative array
   168 						// Associative array
   169             $result = '{';
   169 						$result = '{';
   170             foreach ($array as $key => $value) {
   170 						foreach ($array as $key => $value) {
   171                 $key = (string) $key;
   171 								$key = (string) $key;
   172                 $tmpArray[] = $this->_encodeString($key)
   172 								$tmpArray[] = $this->_encodeString($key)
   173                             . ':'
   173 														. ':'
   174                             . $this->_encodeValue($value);
   174 														. $this->_encodeValue($value);
   175             }
   175 						}
   176             $result .= implode(',', $tmpArray);
   176 						$result .= implode(',', $tmpArray);
   177             $result .= '}';
   177 						$result .= '}';
   178         } else {
   178 				} else {
   179             // Indexed array
   179 						// Indexed array
   180             $result = '[';
   180 						$result = '[';
   181             $length = count($array);
   181 						$length = count($array);
   182             for ($i = 0; $i < $length; $i++) {
   182 						for ($i = 0; $i < $length; $i++) {
   183                 $tmpArray[] = $this->_encodeValue($array[$i]);
   183 								$tmpArray[] = $this->_encodeValue($array[$i]);
   184             }
   184 						}
   185             $result .= implode(',', $tmpArray);
   185 						$result .= implode(',', $tmpArray);
   186             $result .= ']';
   186 						$result .= ']';
   187         }
   187 				}
   188 
   188 
   189         return $result;
   189 				return $result;
   190     }
   190 		}
   191 
   191 
   192 
   192 
   193     /**
   193 		/**
   194      * JSON encode a basic data type (string, number, boolean, null)
   194  		* JSON encode a basic data type (string, number, boolean, null)
   195      *
   195  		*
   196      * If value type is not a string, number, boolean, or null, the string
   196  		* If value type is not a string, number, boolean, or null, the string
   197      * 'null' is returned.
   197  		* 'null' is returned.
   198      *
   198  		*
   199      * @param $value mixed
   199  		* @param $value mixed
   200      * @return string
   200  		* @return string
   201      */
   201  		*/
   202     protected function _encodeDatum(&$value)
   202 		protected function _encodeDatum(&$value)
   203     {
   203 		{
   204         $result = 'null';
   204 				$result = 'null';
   205 
   205 
   206         if (is_int($value) || is_float($value)) {
   206 				if (is_int($value) || is_float($value)) {
   207             $result = (string)$value;
   207 						$result = (string)$value;
   208         } elseif (is_string($value)) {
   208 				} elseif (is_string($value)) {
   209             $result = $this->_encodeString($value);
   209 						$result = $this->_encodeString($value);
   210         } elseif (is_bool($value)) {
   210 				} elseif (is_bool($value)) {
   211             $result = $value ? 'true' : 'false';
   211 						$result = $value ? 'true' : 'false';
   212         }
   212 				}
   213 
   213 
   214         return $result;
   214 				return $result;
   215     }
   215 		}
   216 
   216 
   217 
   217 
   218     /**
   218 		/**
   219      * JSON encode a string value by escaping characters as necessary
   219  		* JSON encode a string value by escaping characters as necessary
   220      *
   220  		*
   221      * @param $value string
   221  		* @param $value string
   222      * @return string
   222  		* @return string
   223      */
   223  		*/
   224     protected function _encodeString(&$string)
   224 		protected function _encodeString(&$string)
   225     {
   225 		{
   226         // Escape these characters with a backslash:
   226 				// Escape these characters with a backslash:
   227         // " \ / \n \r \t \b \f
   227 				// " \ / \n \r \t \b \f
   228         $search  = array('\\', "\n", "\t", "\r", "\b", "\f", '"');
   228 				$search  = array('\\', "\n", "\t", "\r", "\b", "\f", '"');
   229         $replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"');
   229 				$replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"');
   230         $string  = str_replace($search, $replace, $string);
   230 				$string  = str_replace($search, $replace, $string);
   231 
   231 
   232         // Escape certain ASCII characters:
   232 				// Escape certain ASCII characters:
   233         // 0x08 => \b
   233 				// 0x08 => \b
   234         // 0x0c => \f
   234 				// 0x0c => \f
   235         $string = str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $string);
   235 				$string = str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $string);
   236 
   236 
   237         return '"' . $string . '"';
   237 				return '"' . $string . '"';
   238     }
   238 		}
   239 
   239 
   240 
   240 
   241     /**
   241 		/**
   242      * Encode the constants associated with the ReflectionClass
   242  		* Encode the constants associated with the ReflectionClass
   243      * parameter. The encoding format is based on the class2 format
   243  		* parameter. The encoding format is based on the class2 format
   244      *
   244  		*
   245      * @param $cls ReflectionClass
   245  		* @param $cls ReflectionClass
   246      * @return string Encoded constant block in class2 format
   246  		* @return string Encoded constant block in class2 format
   247      */
   247  		*/
   248     private static function _encodeConstants(ReflectionClass $cls)
   248 		private static function _encodeConstants(ReflectionClass $cls)
   249     {
   249 		{
   250         $result    = "constants : {";
   250 				$result    = "constants : {";
   251         $constants = $cls->getConstants();
   251 				$constants = $cls->getConstants();
   252 
   252 
   253         $tmpArray = array();
   253 				$tmpArray = array();
   254         if (!empty($constants)) {
   254 				if (!empty($constants)) {
   255             foreach ($constants as $key => $value) {
   255 						foreach ($constants as $key => $value) {
   256                 $tmpArray[] = "$key: " . self::encode($value);
   256 								$tmpArray[] = "$key: " . self::encode($value);
   257             }
   257 						}
   258 
   258 
   259             $result .= implode(', ', $tmpArray);
   259 						$result .= implode(', ', $tmpArray);
   260         }
   260 				}
   261 
   261 
   262         return $result . "}";
   262 				return $result . "}";
   263     }
   263 		}
   264 
   264 
   265 
   265 
   266     /**
   266 		/**
   267      * Encode the public methods of the ReflectionClass in the
   267  		* Encode the public methods of the ReflectionClass in the
   268      * class2 format
   268  		* class2 format
   269      *
   269  		*
   270      * @param $cls ReflectionClass
   270  		* @param $cls ReflectionClass
   271      * @return string Encoded method fragment
   271  		* @return string Encoded method fragment
   272      *
   272  		*
   273      */
   273  		*/
   274     private static function _encodeMethods(ReflectionClass $cls)
   274 		private static function _encodeMethods(ReflectionClass $cls)
   275     {
   275 		{
   276         $methods = $cls->getMethods();
   276 				$methods = $cls->getMethods();
   277         $result = 'methods:{';
   277 				$result = 'methods:{';
   278 
   278 
   279         $started = false;
   279 				$started = false;
   280         foreach ($methods as $method) {
   280 				foreach ($methods as $method) {
   281             if (! $method->isPublic() || !$method->isUserDefined()) {
   281 						if (! $method->isPublic() || !$method->isUserDefined()) {
   282                 continue;
   282 								continue;
   283             }
   283 						}
   284 
   284 
   285             if ($started) {
   285 						if ($started) {
   286                 $result .= ',';
   286 								$result .= ',';
   287             }
   287 						}
   288             $started = true;
   288 						$started = true;
   289 
   289 
   290             $result .= '' . $method->getName(). ':function(';
   290 						$result .= '' . $method->getName(). ':function(';
   291 
   291 
   292             if ('__construct' != $method->getName()) {
   292 						if ('__construct' != $method->getName()) {
   293                 $parameters  = $method->getParameters();
   293 								$parameters  = $method->getParameters();
   294                 $paramCount  = count($parameters);
   294 								$paramCount  = count($parameters);
   295                 $argsStarted = false;
   295 								$argsStarted = false;
   296 
   296 
   297                 $argNames = "var argNames=[";
   297 								$argNames = "var argNames=[";
   298                 foreach ($parameters as $param) {
   298 								foreach ($parameters as $param) {
   299                     if ($argsStarted) {
   299 										if ($argsStarted) {
   300                         $result .= ',';
   300 												$result .= ',';
   301                     }
   301 										}
   302 
   302 
   303                     $result .= $param->getName();
   303 										$result .= $param->getName();
   304 
   304 
   305                     if ($argsStarted) {
   305 										if ($argsStarted) {
   306                         $argNames .= ',';
   306 												$argNames .= ',';
   307                     }
   307 										}
   308 
   308 
   309                     $argNames .= '"' . $param->getName() . '"';
   309 										$argNames .= '"' . $param->getName() . '"';
   310 
   310 
   311                     $argsStarted = true;
   311 										$argsStarted = true;
   312                 }
   312 								}
   313                 $argNames .= "];";
   313 								$argNames .= "];";
   314 
   314 
   315                 $result .= "){"
   315 								$result .= "){"
   316                          . $argNames
   316  												. $argNames
   317                          . 'var result = ZAjaxEngine.invokeRemoteMethod('
   317  												. 'var result = ZAjaxEngine.invokeRemoteMethod('
   318                          . "this, '" . $method->getName()
   318  												. "this, '" . $method->getName()
   319                          . "',argNames,arguments);"
   319  												. "',argNames,arguments);"
   320                          . 'return(result);}';
   320  												. 'return(result);}';
   321             } else {
   321 						} else {
   322                 $result .= "){}";
   322 								$result .= "){}";
   323             }
   323 						}
   324         }
   324 				}
   325 
   325 
   326         return $result . "}";
   326 				return $result . "}";
   327     }
   327 		}
   328 
   328 
   329 
   329 
   330     /**
   330 		/**
   331      * Encode the public properties of the ReflectionClass in the class2
   331  		* Encode the public properties of the ReflectionClass in the class2
   332      * format.
   332  		* format.
   333      *
   333  		*
   334      * @param $cls ReflectionClass
   334  		* @param $cls ReflectionClass
   335      * @return string Encode properties list
   335  		* @return string Encode properties list
   336      *
   336  		*
   337      */
   337  		*/
   338     private static function _encodeVariables(ReflectionClass $cls)
   338 		private static function _encodeVariables(ReflectionClass $cls)
   339     {
   339 		{
   340         $properties = $cls->getProperties();
   340 				$properties = $cls->getProperties();
   341         $propValues = get_class_vars($cls->getName());
   341 				$propValues = get_class_vars($cls->getName());
   342         $result = "variables:{";
   342 				$result = "variables:{";
   343         $cnt = 0;
   343 				$cnt = 0;
   344 
   344 
   345         $tmpArray = array();
   345 				$tmpArray = array();
   346         foreach ($properties as $prop) {
   346 				foreach ($properties as $prop) {
   347             if (! $prop->isPublic()) {
   347 						if (! $prop->isPublic()) {
   348                 continue;
   348 								continue;
   349             }
   349 						}
   350 
   350 
   351             $tmpArray[] = $prop->getName()
   351 						$tmpArray[] = $prop->getName()
   352                         . ':'
   352 												. ':'
   353                         . self::encode($propValues[$prop->getName()]);
   353 												. self::encode($propValues[$prop->getName()]);
   354         }
   354 				}
   355         $result .= implode(',', $tmpArray);
   355 				$result .= implode(',', $tmpArray);
   356 
   356 
   357         return $result . "}";
   357 				return $result . "}";
   358     }
   358 		}
   359 
   359 
   360     /**
   360 		/**
   361      * Encodes the given $className into the class2 model of encoding PHP
   361  		* Encodes the given $className into the class2 model of encoding PHP
   362      * classes into JavaScript class2 classes.
   362  		* classes into JavaScript class2 classes.
   363      * NOTE: Currently only public methods and variables are proxied onto
   363  		* NOTE: Currently only public methods and variables are proxied onto
   364      * the client machine
   364  		* the client machine
   365      *
   365  		*
   366      * @param $className string The name of the class, the class must be
   366  		* @param $className string The name of the class, the class must be
   367      * instantiable using a null constructor
   367  		* instantiable using a null constructor
   368      * @param $package string Optional package name appended to JavaScript
   368  		* @param $package string Optional package name appended to JavaScript
   369      * proxy class name
   369  		* proxy class name
   370      * @return string The class2 (JavaScript) encoding of the class
   370  		* @return string The class2 (JavaScript) encoding of the class
   371      * @throws Zend_Json_Exception
   371  		* @throws Zend_Json_Exception
   372      */
   372  		*/
   373     public static function encodeClass($className, $package = '')
   373 		public static function encodeClass($className, $package = '')
   374     {
   374 		{
   375         $cls = new ReflectionClass($className);
   375 				$cls = new ReflectionClass($className);
   376         if (! $cls->isInstantiable()) {
   376 				if (! $cls->isInstantiable()) {
   377             throw new Zend_Json_Exception("$className must be instantiable");
   377 						throw new Zend_Json_Exception("$className must be instantiable");
   378         }
   378 				}
   379 
   379 
   380         return "Class.create('$package$className',{"
   380 				return "Class.create('$package$className',{"
   381                 . self::_encodeConstants($cls)    .","
   381 								. self::_encodeConstants($cls)    .","
   382                 . self::_encodeMethods($cls)      .","
   382 								. self::_encodeMethods($cls)      .","
   383                 . self::_encodeVariables($cls)    .'});';
   383 								. self::_encodeVariables($cls)    .'});';
   384     }
   384 		}
   385 
   385 
   386 
   386 
   387     /**
   387 		/**
   388      * Encode several classes at once
   388  		* Encode several classes at once
   389      *
   389  		*
   390      * Returns JSON encoded classes, using {@link encodeClass()}.
   390  		* Returns JSON encoded classes, using {@link encodeClass()}.
   391      *
   391  		*
   392      * @param array $classNames
   392  		* @param array $classNames
   393      * @param string $package
   393  		* @param string $package
   394      * @return string
   394  		* @return string
   395      */
   395  		*/
   396     public static function encodeClasses(array $classNames, $package = '')
   396 		public static function encodeClasses(array $classNames, $package = '')
   397     {
   397 		{
   398         $result = '';
   398 				$result = '';
   399         foreach ($classNames as $className) {
   399 				foreach ($classNames as $className) {
   400             $result .= self::encodeClass($className, $package);
   400 						$result .= self::encodeClass($className, $package);
   401         }
   401 				}
   402 
   402 
   403         return $result;
   403 				return $result;
   404     }
   404 		}
   405 
   405 
   406 }
   406 }
   407 
   407 
   408 /**
   408 /**
   409  * Decode JSON encoded string to PHP variable constructs
   409  * Decode JSON encoded string to PHP variable constructs
   413  * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
   413  * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
   414  * @license    http://framework.zend.com/license/new-bsd     New BSD License
   414  * @license    http://framework.zend.com/license/new-bsd     New BSD License
   415  */
   415  */
   416 class Zend_Json_Decoder
   416 class Zend_Json_Decoder
   417 {
   417 {
   418     /**
   418 		/**
   419      * Parse tokens used to decode the JSON object. These are not
   419  		* Parse tokens used to decode the JSON object. These are not
   420      * for public consumption, they are just used internally to the
   420  		* for public consumption, they are just used internally to the
   421      * class.
   421  		* class.
   422      */
   422  		*/
   423     const EOF          = 0;
   423 		const EOF          = 0;
   424     const DATUM        = 1;
   424 		const DATUM        = 1;
   425     const LBRACE       = 2;
   425 		const LBRACE       = 2;
   426     const LBRACKET     = 3;
   426 		const LBRACKET     = 3;
   427     const RBRACE       = 4;
   427 		const RBRACE       = 4;
   428     const RBRACKET     = 5;
   428 		const RBRACKET     = 5;
   429     const COMMA        = 6;
   429 		const COMMA        = 6;
   430     const COLON        = 7;
   430 		const COLON        = 7;
   431 
   431 
   432     /**
   432 		/**
   433      * Use to maintain a "pointer" to the source being decoded
   433  		* Use to maintain a "pointer" to the source being decoded
   434      *
   434  		*
   435      * @var string
   435  		* @var string
   436      */
   436  		*/
   437     protected $_source;
   437 		protected $_source;
   438 
   438 
   439     /**
   439 		/**
   440      * Caches the source length
   440  		* Caches the source length
   441      *
   441  		*
   442      * @var int
   442  		* @var int
   443      */
   443  		*/
   444     protected $_sourceLength;
   444 		protected $_sourceLength;
   445 
   445 
   446     /**
   446 		/**
   447      * The offset within the souce being decoded
   447  		* The offset within the souce being decoded
   448      *
   448  		*
   449      * @var int
   449  		* @var int
   450      *
   450  		*
   451      */
   451  		*/
   452     protected $_offset;
   452 		protected $_offset;
   453 
   453 
   454     /**
   454 		/**
   455      * The current token being considered in the parser cycle
   455  		* The current token being considered in the parser cycle
   456      *
   456  		*
   457      * @var int
   457  		* @var int
   458      */
   458  		*/
   459     protected $_token;
   459 		protected $_token;
   460 
   460 
   461     /**
   461 		/**
   462      * Flag indicating how objects should be decoded
   462  		* Flag indicating how objects should be decoded
   463      *
   463  		*
   464      * @var int
   464  		* @var int
   465      * @access protected
   465  		* @access protected
   466      */
   466  		*/
   467     protected $_decodeType;
   467 		protected $_decodeType;
   468 
   468 
   469     /**
   469 		/**
   470      * Constructor
   470  		* Constructor
   471      *
   471  		*
   472      * @param string $source String source to decode
   472  		* @param string $source String source to decode
   473      * @param int $decodeType How objects should be decoded -- see
   473  		* @param int $decodeType How objects should be decoded -- see
   474      * {@link Zend_Json::TYPE_ARRAY} and {@link Zend_Json::TYPE_OBJECT} for
   474  		* {@link Zend_Json::TYPE_ARRAY} and {@link Zend_Json::TYPE_OBJECT} for
   475      * valid values
   475  		* valid values
   476      * @return void
   476  		* @return void
   477      */
   477  		*/
   478     protected function __construct($source, $decodeType)
   478 		protected function __construct($source, $decodeType)
   479     {
   479 		{
   480         
   480 				
   481         // eliminate comments
   481 				// eliminate comments
   482         $source = preg_replace(array(
   482 				$source = preg_replace(array(
   483 
   483 
   484                   // eliminate single line comments in '// ...' form
   484 									// eliminate single line comments in '// ...' form
   485                   '#^\s*//(.+)$#m',
   485 									'#^\s*//(.+)$#m',
   486     
   486 		
   487                   // eliminate multi-line comments in '/* ... */' form, at start of string
   487 									// eliminate multi-line comments in '/* ... */' form, at start of string
   488                   '#^\s*/\*(.+)\*/#Us',
   488 									'#^\s*/\*(.+)\*/#Us',
   489     
   489 		
   490                   // eliminate multi-line comments in '/* ... */' form, at end of string
   490 									// eliminate multi-line comments in '/* ... */' form, at end of string
   491                   '#/\*(.+)\*/\s*$#Us'
   491 									'#/\*(.+)\*/\s*$#Us'
   492     
   492 		
   493               ), '', $source);
   493 							), '', $source);
   494         
   494 				
   495         // Set defaults
   495 				// Set defaults
   496         $this->_source       = $source;
   496 				$this->_source       = $source;
   497         $this->_sourceLength = strlen($source);
   497 				$this->_sourceLength = strlen($source);
   498         $this->_token        = self::EOF;
   498 				$this->_token        = self::EOF;
   499         $this->_offset       = 0;
   499 				$this->_offset       = 0;
   500 
   500 
   501         // Normalize and set $decodeType
   501 				// Normalize and set $decodeType
   502         if (!in_array($decodeType, array(Zend_Json::TYPE_ARRAY, Zend_Json::TYPE_OBJECT)))
   502 				if (!in_array($decodeType, array(Zend_Json::TYPE_ARRAY, Zend_Json::TYPE_OBJECT)))
   503         {
   503 				{
   504             $decodeType = Zend_Json::TYPE_ARRAY;
   504 						$decodeType = Zend_Json::TYPE_ARRAY;
   505         }
   505 				}
   506         $this->_decodeType   = $decodeType;
   506 				$this->_decodeType   = $decodeType;
   507 
   507 
   508         // Set pointer at first token
   508 				// Set pointer at first token
   509         $this->_getNextToken();
   509 				$this->_getNextToken();
   510     }
   510 		}
   511 
   511 
   512     /**
   512 		/**
   513      * Decode a JSON source string
   513  		* Decode a JSON source string
   514      *
   514  		*
   515      * Decodes a JSON encoded string. The value returned will be one of the
   515  		* Decodes a JSON encoded string. The value returned will be one of the
   516      * following:
   516  		* following:
   517      *        - integer
   517  		*        - integer
   518      *        - float
   518  		*        - float
   519      *        - boolean
   519  		*        - boolean
   520      *        - null
   520  		*        - null
   521      *      - StdClass
   521  		*      - StdClass
   522      *      - array
   522  		*      - array
   523      *         - array of one or more of the above types
   523  		*         - array of one or more of the above types
   524      *
   524  		*
   525      * By default, decoded objects will be returned as associative arrays; to
   525  		* By default, decoded objects will be returned as associative arrays; to
   526      * return a StdClass object instead, pass {@link Zend_Json::TYPE_OBJECT} to
   526  		* return a StdClass object instead, pass {@link Zend_Json::TYPE_OBJECT} to
   527      * the $objectDecodeType parameter.
   527  		* the $objectDecodeType parameter.
   528      *
   528  		*
   529      * Throws a Zend_Json_Exception if the source string is null.
   529  		* Throws a Zend_Json_Exception if the source string is null.
   530      *
   530  		*
   531      * @static
   531  		* @static
   532      * @access public
   532  		* @access public
   533      * @param string $source String to be decoded
   533  		* @param string $source String to be decoded
   534      * @param int $objectDecodeType How objects should be decoded; should be
   534  		* @param int $objectDecodeType How objects should be decoded; should be
   535      * either or {@link Zend_Json::TYPE_ARRAY} or
   535  		* either or {@link Zend_Json::TYPE_ARRAY} or
   536      * {@link Zend_Json::TYPE_OBJECT}; defaults to TYPE_ARRAY
   536  		* {@link Zend_Json::TYPE_OBJECT}; defaults to TYPE_ARRAY
   537      * @return mixed
   537  		* @return mixed
   538      * @throws Zend_Json_Exception
   538  		* @throws Zend_Json_Exception
   539      */
   539  		*/
   540     public static function decode($source = null, $objectDecodeType = Zend_Json::TYPE_ARRAY)
   540 		public static function decode($source = null, $objectDecodeType = Zend_Json::TYPE_ARRAY)
   541     {
   541 		{
   542         if (null === $source) {
   542 				if (null === $source) {
   543             throw new Zend_Json_Exception('Must specify JSON encoded source for decoding');
   543 						throw new Zend_Json_Exception('Must specify JSON encoded source for decoding');
   544         } elseif (!is_string($source)) {
   544 				} elseif (!is_string($source)) {
   545             throw new Zend_Json_Exception('Can only decode JSON encoded strings');
   545 						throw new Zend_Json_Exception('Can only decode JSON encoded strings');
   546         }
   546 				}
   547 
   547 
   548         $decoder = new self($source, $objectDecodeType);
   548 				$decoder = new self($source, $objectDecodeType);
   549 
   549 
   550         return $decoder->_decodeValue();
   550 				return $decoder->_decodeValue();
   551     }
   551 		}
   552 
   552 
   553 
   553 
   554     /**
   554 		/**
   555      * Recursive driving rountine for supported toplevel tops
   555  		* Recursive driving rountine for supported toplevel tops
   556      *
   556  		*
   557      * @return mixed
   557  		* @return mixed
   558      */
   558  		*/
   559     protected function _decodeValue()
   559 		protected function _decodeValue()
   560     {
   560 		{
   561         switch ($this->_token) {
   561 				switch ($this->_token) {
   562             case self::DATUM:
   562 						case self::DATUM:
   563                 $result  = $this->_tokenValue;
   563 								$result  = $this->_tokenValue;
   564                 $this->_getNextToken();
   564 								$this->_getNextToken();
   565                 return($result);
   565 								return($result);
   566                 break;
   566 								break;
   567             case self::LBRACE:
   567 						case self::LBRACE:
   568                 return($this->_decodeObject());
   568 								return($this->_decodeObject());
   569                 break;
   569 								break;
   570             case self::LBRACKET:
   570 						case self::LBRACKET:
   571                 return($this->_decodeArray());
   571 								return($this->_decodeArray());
   572                 break;
   572 								break;
   573             default:
   573 						default:
   574                 return null;
   574 								return null;
   575                 break;
   575 								break;
   576         }
   576 				}
   577     }
   577 		}
   578 
   578 
   579     /**
   579 		/**
   580      * Decodes an object of the form:
   580  		* Decodes an object of the form:
   581      *  { "attribute: value, "attribute2" : value,...}
   581  		*  { "attribute: value, "attribute2" : value,...}
   582      *
   582  		*
   583      * If ZJsonEnoder or ZJAjax was used to encode the original object
   583  		* If ZJsonEnoder or ZJAjax was used to encode the original object
   584      * then a special attribute called __className which specifies a class
   584  		* then a special attribute called __className which specifies a class
   585      * name that should wrap the data contained within the encoded source.
   585  		* name that should wrap the data contained within the encoded source.
   586      *
   586  		*
   587      * Decodes to either an array or StdClass object, based on the value of
   587  		* Decodes to either an array or StdClass object, based on the value of
   588      * {@link $_decodeType}. If invalid $_decodeType present, returns as an
   588  		* {@link $_decodeType}. If invalid $_decodeType present, returns as an
   589      * array.
   589  		* array.
   590      *
   590  		*
   591      * @return array|StdClass
   591  		* @return array|StdClass
   592      */
   592  		*/
   593     protected function _decodeObject()
   593 		protected function _decodeObject()
   594     {
   594 		{
   595         $members = array();
   595 				$members = array();
   596         $tok = $this->_getNextToken();
   596 				$tok = $this->_getNextToken();
   597 
   597 
   598         while ($tok && $tok != self::RBRACE) {
   598 				while ($tok && $tok != self::RBRACE) {
   599             if ($tok != self::DATUM || ! is_string($this->_tokenValue)) {
   599 						if ($tok != self::DATUM || ! is_string($this->_tokenValue)) {
   600                 throw new Zend_Json_Exception('Missing key in object encoding: ' . $this->_source);
   600 								throw new Zend_Json_Exception('Missing key in object encoding: ' . $this->_source);
   601             }
   601 						}
   602 
   602 
   603             $key = $this->_tokenValue;
   603 						$key = $this->_tokenValue;
   604             $tok = $this->_getNextToken();
   604 						$tok = $this->_getNextToken();
   605 
   605 
   606             if ($tok != self::COLON) {
   606 						if ($tok != self::COLON) {
   607                 throw new Zend_Json_Exception('Missing ":" in object encoding: ' . $this->_source);
   607 								throw new Zend_Json_Exception('Missing ":" in object encoding: ' . $this->_source);
   608             }
   608 						}
   609 
   609 
   610             $tok = $this->_getNextToken();
   610 						$tok = $this->_getNextToken();
   611             $members[$key] = $this->_decodeValue();
   611 						$members[$key] = $this->_decodeValue();
   612             $tok = $this->_token;
   612 						$tok = $this->_token;
   613 
   613 
   614             if ($tok == self::RBRACE) {
   614 						if ($tok == self::RBRACE) {
   615                 break;
   615 								break;
   616             }
   616 						}
   617 
   617 
   618             if ($tok != self::COMMA) {
   618 						if ($tok != self::COMMA) {
   619                 throw new Zend_Json_Exception('Missing "," in object encoding: ' . $this->_source);
   619 								throw new Zend_Json_Exception('Missing "," in object encoding: ' . $this->_source);
   620             }
   620 						}
   621 
   621 
   622             $tok = $this->_getNextToken();
   622 						$tok = $this->_getNextToken();
   623         }
   623 				}
   624 
   624 
   625         switch ($this->_decodeType) {
   625 				switch ($this->_decodeType) {
   626             case Zend_Json::TYPE_OBJECT:
   626 						case Zend_Json::TYPE_OBJECT:
   627                 // Create new StdClass and populate with $members
   627 								// Create new StdClass and populate with $members
   628                 $result = new StdClass();
   628 								$result = new StdClass();
   629                 foreach ($members as $key => $value) {
   629 								foreach ($members as $key => $value) {
   630                     $result->$key = $value;
   630 										$result->$key = $value;
   631                 }
   631 								}
   632                 break;
   632 								break;
   633             case Zend_Json::TYPE_ARRAY:
   633 						case Zend_Json::TYPE_ARRAY:
   634             default:
   634 						default:
   635                 $result = $members;
   635 								$result = $members;
   636                 break;
   636 								break;
   637         }
   637 				}
   638 
   638 
   639         $this->_getNextToken();
   639 				$this->_getNextToken();
   640         return $result;
   640 				return $result;
   641     }
   641 		}
   642 
   642 
   643     /**
   643 		/**
   644      * Decodes a JSON array format:
   644  		* Decodes a JSON array format:
   645      *    [element, element2,...,elementN]
   645  		*    [element, element2,...,elementN]
   646      *
   646  		*
   647      * @return array
   647  		* @return array
   648      */
   648  		*/
   649     protected function _decodeArray()
   649 		protected function _decodeArray()
   650     {
   650 		{
   651         $result = array();
   651 				$result = array();
   652         $starttok = $tok = $this->_getNextToken(); // Move past the '['
   652 				$starttok = $tok = $this->_getNextToken(); // Move past the '['
   653         $index  = 0;
   653 				$index  = 0;
   654 
   654 
   655         while ($tok && $tok != self::RBRACKET) {
   655 				while ($tok && $tok != self::RBRACKET) {
   656             $result[$index++] = $this->_decodeValue();
   656 						$result[$index++] = $this->_decodeValue();
   657 
   657 
   658             $tok = $this->_token;
   658 						$tok = $this->_token;
   659 
   659 
   660             if ($tok == self::RBRACKET || !$tok) {
   660 						if ($tok == self::RBRACKET || !$tok) {
   661                 break;
   661 								break;
   662             }
   662 						}
   663 
   663 
   664             if ($tok != self::COMMA) {
   664 						if ($tok != self::COMMA) {
   665                 throw new Zend_Json_Exception('Missing "," in array encoding: ' . $this->_source);
   665 								throw new Zend_Json_Exception('Missing "," in array encoding: ' . $this->_source);
   666             }
   666 						}
   667 
   667 
   668             $tok = $this->_getNextToken();
   668 						$tok = $this->_getNextToken();
   669         }
   669 				}
   670 
   670 
   671         $this->_getNextToken();
   671 				$this->_getNextToken();
   672         return($result);
   672 				return($result);
   673     }
   673 		}
   674 
   674 
   675 
   675 
   676     /**
   676 		/**
   677      * Removes whitepsace characters from the source input
   677  		* Removes whitepsace characters from the source input
   678      */
   678  		*/
   679     protected function _eatWhitespace()
   679 		protected function _eatWhitespace()
   680     {
   680 		{
   681         if (preg_match(
   681 				if (preg_match(
   682                 '/([\t\b\f\n\r ])*/s',
   682 								'/([\t\b\f\n\r ])*/s',
   683                 $this->_source,
   683 								$this->_source,
   684                 $matches,
   684 								$matches,
   685                 PREG_OFFSET_CAPTURE,
   685 								PREG_OFFSET_CAPTURE,
   686                 $this->_offset)
   686 								$this->_offset)
   687             && $matches[0][1] == $this->_offset)
   687 						&& $matches[0][1] == $this->_offset)
   688         {
   688 				{
   689             $this->_offset += strlen($matches[0][0]);
   689 						$this->_offset += strlen($matches[0][0]);
   690         }
   690 				}
   691     }
   691 		}
   692 
   692 
   693 
   693 
   694     /**
   694 		/**
   695      * Retrieves the next token from the source stream
   695  		* Retrieves the next token from the source stream
   696      *
   696  		*
   697      * @return int Token constant value specified in class definition
   697  		* @return int Token constant value specified in class definition
   698      */
   698  		*/
   699     protected function _getNextToken()
   699 		protected function _getNextToken()
   700     {
   700 		{
   701         $this->_token      = self::EOF;
   701 				$this->_token      = self::EOF;
   702         $this->_tokenValue = null;
   702 				$this->_tokenValue = null;
   703         $this->_eatWhitespace();
   703 				$this->_eatWhitespace();
   704         
   704 				
   705         if ($this->_offset >= $this->_sourceLength) {
   705 				if ($this->_offset >= $this->_sourceLength) {
   706             return(self::EOF);
   706 						return(self::EOF);
   707         }
   707 				}
   708 
   708 
   709         $str        = $this->_source;
   709 				$str        = $this->_source;
   710         $str_length = $this->_sourceLength;
   710 				$str_length = $this->_sourceLength;
   711         $i          = $this->_offset;
   711 				$i          = $this->_offset;
   712         $start      = $i;
   712 				$start      = $i;
   713         
   713 				
   714         switch ($str{$i}) {
   714 				switch ($str{$i}) {
   715             case '{':
   715 						case '{':
   716                $this->_token = self::LBRACE;
   716  							$this->_token = self::LBRACE;
   717                break;
   717  							break;
   718             case '}':
   718 						case '}':
   719                 $this->_token = self::RBRACE;
   719 								$this->_token = self::RBRACE;
   720                 break;
   720 								break;
   721             case '[':
   721 						case '[':
   722                 $this->_token = self::LBRACKET;
   722 								$this->_token = self::LBRACKET;
   723                 break;
   723 								break;
   724             case ']':
   724 						case ']':
   725                 $this->_token = self::RBRACKET;
   725 								$this->_token = self::RBRACKET;
   726                 break;
   726 								break;
   727             case ',':
   727 						case ',':
   728                 $this->_token = self::COMMA;
   728 								$this->_token = self::COMMA;
   729                 break;
   729 								break;
   730             case ':':
   730 						case ':':
   731                 $this->_token = self::COLON;
   731 								$this->_token = self::COLON;
   732                 break;
   732 								break;
   733             case  '"':
   733 						case  '"':
   734                 $result = '';
   734 								$result = '';
   735                 do {
   735 								do {
   736                     $i++;
   736 										$i++;
   737                     if ($i >= $str_length) {
   737 										if ($i >= $str_length) {
   738                         break;
   738 												break;
   739                     }
   739 										}
   740 
   740 
   741                     $chr = $str{$i};
   741 										$chr = $str{$i};
   742                     if ($chr == '\\') {
   742 										if ($chr == '\\') {
   743                         $i++;
   743 												$i++;
   744                         if ($i >= $str_length) {
   744 												if ($i >= $str_length) {
   745                             break;
   745 														break;
   746                         }
   746 												}
   747                         $chr = $str{$i};
   747 												$chr = $str{$i};
   748                         switch ($chr) {
   748 												switch ($chr) {
   749                             case '"' :
   749 														case '"' :
   750                                 $result .= '"';
   750 																$result .= '"';
   751                                 break;
   751 																break;
   752                             case '\\':
   752 														case '\\':
   753                                 $result .= '\\';
   753 																$result .= '\\';
   754                                 break;
   754 																break;
   755                             case '/' :
   755 														case '/' :
   756                                 $result .= '/';
   756 																$result .= '/';
   757                                 break;
   757 																break;
   758                             case 'b' :
   758 														case 'b' :
   759                                 $result .= chr(8);
   759 																$result .= chr(8);
   760                                 break;
   760 																break;
   761                             case 'f' :
   761 														case 'f' :
   762                                 $result .= chr(12);
   762 																$result .= chr(12);
   763                                 break;
   763 																break;
   764                             case 'n' :
   764 														case 'n' :
   765                                 $result .= chr(10);
   765 																$result .= chr(10);
   766                                 break;
   766 																break;
   767                             case 'r' :
   767 														case 'r' :
   768                                 $result .= chr(13);
   768 																$result .= chr(13);
   769                                 break;
   769 																break;
   770                             case 't' :
   770 														case 't' :
   771                                 $result .= chr(9);
   771 																$result .= chr(9);
   772                                 break;
   772 																break;
   773                             case '\'' :
   773 														case '\'' :
   774                                 $result .= '\'';
   774 																$result .= '\'';
   775                                 break;
   775 																break;
   776                             case 'u':
   776 														case 'u':
   777                               $result .= self::decode_unicode_byte(substr($str, $i + 1, 4));
   777 															$result .= self::decode_unicode_byte(substr($str, $i + 1, 4));
   778                               $i += 4;
   778 															$i += 4;
   779                               break;
   779 															break;
   780                             default:
   780 														default:
   781                                 throw new Zend_Json_Exception("Illegal escape "
   781 																throw new Zend_Json_Exception("Illegal escape "
   782                                     .  "sequence '" . $chr . "'");
   782 																		.  "sequence '" . $chr . "'");
   783                             }
   783 														}
   784                     } elseif ($chr == '"') {
   784 										} elseif ($chr == '"') {
   785                         break;
   785 												break;
   786                     } else {
   786 										} else {
   787                         $result .= $chr;
   787 												$result .= $chr;
   788                     }
   788 										}
   789                 } while ($i < $str_length);
   789 								} while ($i < $str_length);
   790 
   790 
   791                 $this->_token = self::DATUM;
   791 								$this->_token = self::DATUM;
   792                 //$this->_tokenValue = substr($str, $start + 1, $i - $start - 1);
   792 								//$this->_tokenValue = substr($str, $start + 1, $i - $start - 1);
   793                 $this->_tokenValue = $result;
   793 								$this->_tokenValue = $result;
   794                 break;
   794 								break;
   795             case  "'":
   795 						case  "'":
   796                 $result = '';
   796 								$result = '';
   797                 do {
   797 								do {
   798                     $i++;
   798 										$i++;
   799                     if ($i >= $str_length) {
   799 										if ($i >= $str_length) {
   800                         break;
   800 												break;
   801                     }
   801 										}
   802 
   802 
   803                     $chr = $str{$i};
   803 										$chr = $str{$i};
   804                     if ($chr == '\\') {
   804 										if ($chr == '\\') {
   805                         $i++;
   805 												$i++;
   806                         if ($i >= $str_length) {
   806 												if ($i >= $str_length) {
   807                             break;
   807 														break;
   808                         }
   808 												}
   809                         $chr = $str{$i};
   809 												$chr = $str{$i};
   810                         switch ($chr) {
   810 												switch ($chr) {
   811                             case "'" :
   811 														case "'" :
   812                                 $result .= "'";
   812 																$result .= "'";
   813                                 break;
   813 																break;
   814                             case '\\':
   814 														case '\\':
   815                                 $result .= '\\';
   815 																$result .= '\\';
   816                                 break;
   816 																break;
   817                             case '/' :
   817 														case '/' :
   818                                 $result .= '/';
   818 																$result .= '/';
   819                                 break;
   819 																break;
   820                             case 'b' :
   820 														case 'b' :
   821                                 $result .= chr(8);
   821 																$result .= chr(8);
   822                                 break;
   822 																break;
   823                             case 'f' :
   823 														case 'f' :
   824                                 $result .= chr(12);
   824 																$result .= chr(12);
   825                                 break;
   825 																break;
   826                             case 'n' :
   826 														case 'n' :
   827                                 $result .= chr(10);
   827 																$result .= chr(10);
   828                                 break;
   828 																break;
   829                             case 'r' :
   829 														case 'r' :
   830                                 $result .= chr(13);
   830 																$result .= chr(13);
   831                                 break;
   831 																break;
   832                             case 't' :
   832 														case 't' :
   833                                 $result .= chr(9);
   833 																$result .= chr(9);
   834                                 break;
   834 																break;
   835                             case '"' :
   835 														case '"' :
   836                                 $result .= '"';
   836 																$result .= '"';
   837                                 break;
   837 																break;
   838                             default:
   838 														default:
   839                                 throw new Zend_Json_Exception("Illegal escape "
   839 																throw new Zend_Json_Exception("Illegal escape "
   840                                     .  "sequence '" . $chr . "'");
   840 																		.  "sequence '" . $chr . "'");
   841                             }
   841 														}
   842                     } elseif ($chr == "'") {
   842 										} elseif ($chr == "'") {
   843                         break;
   843 												break;
   844                     } else {
   844 										} else {
   845                         $result .= $chr;
   845 												$result .= $chr;
   846                     }
   846 										}
   847                 } while ($i < $str_length);
   847 								} while ($i < $str_length);
   848 
   848 
   849                 $this->_token = self::DATUM;
   849 								$this->_token = self::DATUM;
   850                 //$this->_tokenValue = substr($str, $start + 1, $i - $start - 1);
   850 								//$this->_tokenValue = substr($str, $start + 1, $i - $start - 1);
   851                 $this->_tokenValue = $result;
   851 								$this->_tokenValue = $result;
   852                 break;
   852 								break;
   853             case 't':
   853 						case 't':
   854                 if (($i+ 3) < $str_length && substr($str, $start, 4) == "true") {
   854 								if (($i+ 3) < $str_length && substr($str, $start, 4) == "true") {
   855                     $this->_token = self::DATUM;
   855 										$this->_token = self::DATUM;
   856                 }
   856 								}
   857                 $this->_tokenValue = true;
   857 								$this->_tokenValue = true;
   858                 $i += 3;
   858 								$i += 3;
   859                 break;
   859 								break;
   860             case 'f':
   860 						case 'f':
   861                 if (($i+ 4) < $str_length && substr($str, $start, 5) == "false") {
   861 								if (($i+ 4) < $str_length && substr($str, $start, 5) == "false") {
   862                     $this->_token = self::DATUM;
   862 										$this->_token = self::DATUM;
   863                 }
   863 								}
   864                 $this->_tokenValue = false;
   864 								$this->_tokenValue = false;
   865                 $i += 4;
   865 								$i += 4;
   866                 break;
   866 								break;
   867             case 'n':
   867 						case 'n':
   868                 if (($i+ 3) < $str_length && substr($str, $start, 4) == "null") {
   868 								if (($i+ 3) < $str_length && substr($str, $start, 4) == "null") {
   869                     $this->_token = self::DATUM;
   869 										$this->_token = self::DATUM;
   870                 }
   870 								}
   871                 $this->_tokenValue = NULL;
   871 								$this->_tokenValue = NULL;
   872                 $i += 3;
   872 								$i += 3;
   873                 break;
   873 								break;
   874               case ' ':
   874 							case ' ':
   875                 break;
   875 								break;
   876         }
   876 				}
   877 
   877 
   878         if ($this->_token != self::EOF) {
   878 				if ($this->_token != self::EOF) {
   879             $this->_offset = $i + 1; // Consume the last token character
   879 						$this->_offset = $i + 1; // Consume the last token character
   880             return($this->_token);
   880 						return($this->_token);
   881         }
   881 				}
   882 
   882 
   883         $chr = $str{$i};
   883 				$chr = $str{$i};
   884         if ($chr == '-' || $chr == '.' || ($chr >= '0' && $chr <= '9')) {
   884 				if ($chr == '-' || $chr == '.' || ($chr >= '0' && $chr <= '9')) {
   885             if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s',
   885 						if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s',
   886                 $str, $matches, PREG_OFFSET_CAPTURE, $start) && $matches[0][1] == $start) {
   886 								$str, $matches, PREG_OFFSET_CAPTURE, $start) && $matches[0][1] == $start) {
   887 
   887 
   888                 $datum = $matches[0][0];
   888 								$datum = $matches[0][0];
   889 
   889 
   890                 if (is_numeric($datum)) {
   890 								if (is_numeric($datum)) {
   891                     if (preg_match('/^0\d+$/', $datum)) {
   891 										if (preg_match('/^0\d+$/', $datum)) {
   892                         throw new Zend_Json_Exception("Octal notation not supported by JSON (value: $datum)");
   892 												throw new Zend_Json_Exception("Octal notation not supported by JSON (value: $datum)");
   893                     } else {
   893 										} else {
   894                         $val  = intval($datum);
   894 												$val  = intval($datum);
   895                         $fVal = floatval($datum);
   895 												$fVal = floatval($datum);
   896                         $this->_tokenValue = ($val == $fVal ? $val : $fVal);
   896 												$this->_tokenValue = ($val == $fVal ? $val : $fVal);
   897                     }
   897 										}
   898                 } else {
   898 								} else {
   899                     throw new Zend_Json_Exception("Illegal number format: $datum");
   899 										throw new Zend_Json_Exception("Illegal number format: $datum");
   900                 }
   900 								}
   901 
   901 
   902                 $this->_token = self::DATUM;
   902 								$this->_token = self::DATUM;
   903                 $this->_offset = $start + strlen($datum);
   903 								$this->_offset = $start + strlen($datum);
   904             }
   904 						}
   905         } else {
   905 				} else {
   906             throw new Zend_Json_Exception("Illegal Token at pos $i: $chr\nContext:\n--------------------------------------------------" . substr($str, $i) . "\n--------------------------------------------------");
   906 						throw new Zend_Json_Exception("Illegal Token at pos $i: $chr\nContext:\n--------------------------------------------------" . substr($str, $i) . "\n--------------------------------------------------");
   907         }
   907 				}
   908 
   908 
   909         return($this->_token);
   909 				return($this->_token);
   910     }
   910 		}
   911     
   911 		
   912     /**
   912 		/**
   913      * Handle a Unicode byte; local to Enano.
   913  		* Handle a Unicode byte; local to Enano.
   914      * @param string 4 character byte sequence
   914  		* @param string 4 character byte sequence
   915      * @return string
   915  		* @return string
   916      */
   916  		*/
   917     
   917 		
   918     protected function decode_unicode_byte($byte)
   918 		protected function decode_unicode_byte($byte)
   919     {
   919 		{
   920       if ( strlen($byte) != 4 )
   920 			if ( strlen($byte) != 4 )
   921         throw new Zend_Json_Exception("Invalid Unicode sequence \\u$byte");
   921 				throw new Zend_Json_Exception("Invalid Unicode sequence \\u$byte");
   922         
   922 				
   923       $value = hexdec($byte);
   923 			$value = hexdec($byte);
   924 
   924 
   925       if ($value < 0x0080)
   925 			if ($value < 0x0080)
   926       {
   926 			{
   927         // 1 byte: 0xxxxxxx
   927 				// 1 byte: 0xxxxxxx
   928         $character = chr($value);
   928 				$character = chr($value);
   929       }
   929 			}
   930       else if ($value < 0x0800)
   930 			else if ($value < 0x0800)
   931       {
   931 			{
   932         // 2 bytes: 110xxxxx 10xxxxxx
   932 				// 2 bytes: 110xxxxx 10xxxxxx
   933         $character =
   933 				$character =
   934             chr((($value & 0x07c0) >> 6) | 0xc0)
   934 						chr((($value & 0x07c0) >> 6) | 0xc0)
   935           . chr(($value & 0x3f) | 0x80);
   935 					. chr(($value & 0x3f) | 0x80);
   936       }
   936 			}
   937       else
   937 			else
   938       {
   938 			{
   939         // 3 bytes: 1110xxxx 10xxxxxx 10xxxxxx
   939 				// 3 bytes: 1110xxxx 10xxxxxx 10xxxxxx
   940         $character =
   940 				$character =
   941             chr((($value & 0xf000) >> 12) | 0xe0)
   941 						chr((($value & 0xf000) >> 12) | 0xe0)
   942           . chr((($value & 0x0fc0) >> 6) | 0x80)
   942 					. chr((($value & 0x0fc0) >> 6) | 0x80)
   943           . chr(($value & 0x3f) | 0x80);
   943 					. chr(($value & 0x3f) | 0x80);
   944       }
   944 			}
   945       
   945 			
   946       return $character;
   946 			return $character;
   947     }
   947 		}
   948 }
   948 }
   949 
   949 
   950 /**
   950 /**
   951  * Zend Framework
   951  * Zend Framework
   952  *
   952  *
   993  * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
   993  * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
   994  * @license    http://framework.zend.com/license/new-bsd     New BSD License
   994  * @license    http://framework.zend.com/license/new-bsd     New BSD License
   995  */
   995  */
   996 class Zend_Json
   996 class Zend_Json
   997 {
   997 {
   998     /**
   998 		/**
   999      * How objects should be encoded -- arrays or as StdClass. TYPE_ARRAY is 1
   999  		* How objects should be encoded -- arrays or as StdClass. TYPE_ARRAY is 1
  1000      * so that it is a boolean true value, allowing it to be used with
  1000  		* so that it is a boolean true value, allowing it to be used with
  1001      * ext/json's functions.
  1001  		* ext/json's functions.
  1002      */
  1002  		*/
  1003     const TYPE_ARRAY  = 1;
  1003 		const TYPE_ARRAY  = 1;
  1004     const TYPE_OBJECT = 0;
  1004 		const TYPE_OBJECT = 0;
  1005 
  1005 
  1006     /**
  1006 		/**
  1007      * @var bool
  1007  		* @var bool
  1008      */
  1008  		*/
  1009     public static $useBuiltinEncoderDecoder = true;
  1009 		public static $useBuiltinEncoderDecoder = true;
  1010 
  1010 
  1011     /**
  1011 		/**
  1012      * Decodes the given $encodedValue string which is
  1012  		* Decodes the given $encodedValue string which is
  1013      * encoded in the JSON format
  1013  		* encoded in the JSON format
  1014      *
  1014  		*
  1015      * Uses ext/json's json_decode if available.
  1015  		* Uses ext/json's json_decode if available.
  1016      *
  1016  		*
  1017      * @param string $encodedValue Encoded in JSON format
  1017  		* @param string $encodedValue Encoded in JSON format
  1018      * @param int $objectDecodeType Optional; flag indicating how to decode
  1018  		* @param int $objectDecodeType Optional; flag indicating how to decode
  1019      * objects. See {@link ZJsonDecoder::decode()} for details.
  1019  		* objects. See {@link ZJsonDecoder::decode()} for details.
  1020      * @return mixed
  1020  		* @return mixed
  1021      */
  1021  		*/
  1022     public static function decode($encodedValue, $objectDecodeType = Zend_Json::TYPE_ARRAY)
  1022 		public static function decode($encodedValue, $objectDecodeType = Zend_Json::TYPE_ARRAY)
  1023     {
  1023 		{
  1024         if (function_exists('json_decode') && self::$useBuiltinEncoderDecoder !== true) {
  1024 				if (function_exists('json_decode') && self::$useBuiltinEncoderDecoder !== true) {
  1025             return json_decode($encodedValue, $objectDecodeType);
  1025 						return json_decode($encodedValue, $objectDecodeType);
  1026         }
  1026 				}
  1027 
  1027 
  1028         return Zend_Json_Decoder::decode($encodedValue, $objectDecodeType);
  1028 				return Zend_Json_Decoder::decode($encodedValue, $objectDecodeType);
  1029     }
  1029 		}
  1030 
  1030 
  1031 
  1031 
  1032     /**
  1032 		/**
  1033      * Encode the mixed $valueToEncode into the JSON format
  1033  		* Encode the mixed $valueToEncode into the JSON format
  1034      *
  1034  		*
  1035      * Encodes using ext/json's json_encode() if available.
  1035  		* Encodes using ext/json's json_encode() if available.
  1036      *
  1036  		*
  1037      * NOTE: Object should not contain cycles; the JSON format
  1037  		* NOTE: Object should not contain cycles; the JSON format
  1038      * does not allow object reference.
  1038  		* does not allow object reference.
  1039      *
  1039  		*
  1040      * NOTE: Only public variables will be encoded
  1040  		* NOTE: Only public variables will be encoded
  1041      *
  1041  		*
  1042      * @param mixed $valueToEncode
  1042  		* @param mixed $valueToEncode
  1043      * @param boolean $cycleCheck Optional; whether or not to check for object recursion; off by default
  1043  		* @param boolean $cycleCheck Optional; whether or not to check for object recursion; off by default
  1044      * @return string JSON encoded object
  1044  		* @return string JSON encoded object
  1045      */
  1045  		*/
  1046     public static function encode($valueToEncode, $cycleCheck = false)
  1046 		public static function encode($valueToEncode, $cycleCheck = false)
  1047     {
  1047 		{
  1048         if (function_exists('json_encode') && self::$useBuiltinEncoderDecoder !== true) {
  1048 				if (function_exists('json_encode') && self::$useBuiltinEncoderDecoder !== true) {
  1049             return json_encode($valueToEncode);
  1049 						return json_encode($valueToEncode);
  1050         }
  1050 				}
  1051 
  1051 
  1052         return Zend_Json_Encoder::encode($valueToEncode, $cycleCheck);
  1052 				return Zend_Json_Encoder::encode($valueToEncode, $cycleCheck);
  1053     }
  1053 		}
  1054 }
  1054 }
  1055 
  1055 
  1056 ?>
  1056 ?>