[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Zend Framework 4 * 5 * LICENSE 6 * 7 * This source file is subject to the new BSD license that is bundled 8 * with this package in the file LICENSE.txt. 9 * It is also available through the world-wide-web at this URL: 10 * http://framework.zend.com/license/new-bsd 11 * If you did not receive a copy of the license and are unable to 12 * obtain it through the world-wide-web, please send an email 13 * to [email protected] so we can send you a copy immediately. 14 * 15 * @category Zend 16 * @package Zend_Json 17 * @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com) 18 * @license http://framework.zend.com/license/new-bsd New BSD License 19 */ 20 21 /** 22 * Zend_Json 23 */ 24 require_once 'include/Zend/Json.php'; 25 26 /** 27 * Zend_Json_Exception 28 */ 29 require_once 'include/Zend/Json/Exception.php'; 30 31 32 /** 33 * Decode JSON encoded string to PHP variable constructs 34 * 35 * @category Zend 36 * @package Zend_Json 37 * @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com) 38 * @license http://framework.zend.com/license/new-bsd New BSD License 39 */ 40 class Zend_Json_Decoder 41 { 42 /** 43 * Parse tokens used to decode the JSON object. These are not 44 * for public consumption, they are just used internally to the 45 * class. 46 */ 47 const EOF = 0; 48 const DATUM = 1; 49 const LBRACE = 2; 50 const LBRACKET = 3; 51 const RBRACE = 4; 52 const RBRACKET = 5; 53 const COMMA = 6; 54 const COLON = 7; 55 56 /** 57 * Use to maintain a "pointer" to the source being decoded 58 * 59 * @var string 60 */ 61 protected $_source; 62 63 /** 64 * Caches the source length 65 * 66 * @var int 67 */ 68 protected $_sourceLength; 69 70 /** 71 * The offset within the souce being decoded 72 * 73 * @var int 74 * 75 */ 76 protected $_offset; 77 78 /** 79 * The current token being considered in the parser cycle 80 * 81 * @var int 82 */ 83 protected $_token; 84 85 /** 86 * Flag indicating how objects should be decoded 87 * 88 * @var int 89 * @access protected 90 */ 91 protected $_decodeType; 92 93 /** 94 * Constructor 95 * 96 * @param string $source String source to decode 97 * @param int $decodeType How objects should be decoded -- see 98 * {@link Zend_Json::TYPE_ARRAY} and {@link Zend_Json::TYPE_OBJECT} for 99 * valid values 100 * @return void 101 */ 102 protected function __construct($source, $decodeType) 103 { 104 // Set defaults 105 $this->_source = $source; 106 $this->_sourceLength = strlen($source); 107 $this->_token = self::EOF; 108 $this->_offset = 0; 109 110 // Normalize and set $decodeType 111 if (!in_array($decodeType, array(Zend_Json::TYPE_ARRAY, Zend_Json::TYPE_OBJECT))) 112 { 113 $decodeType = Zend_Json::TYPE_ARRAY; 114 } 115 $this->_decodeType = $decodeType; 116 117 // Set pointer at first token 118 $this->_getNextToken(); 119 } 120 121 /** 122 * Decode a JSON source string 123 * 124 * Decodes a JSON encoded string. The value returned will be one of the 125 * following: 126 * - integer 127 * - float 128 * - boolean 129 * - null 130 * - StdClass 131 * - array 132 * - array of one or more of the above types 133 * 134 * By default, decoded objects will be returned as associative arrays; to 135 * return a StdClass object instead, pass {@link Zend_Json::TYPE_OBJECT} to 136 * the $objectDecodeType parameter. 137 * 138 * Throws a Zend_Json_Exception if the source string is null. 139 * 140 * @static 141 * @access public 142 * @param string $source String to be decoded 143 * @param int $objectDecodeType How objects should be decoded; should be 144 * either or {@link Zend_Json::TYPE_ARRAY} or 145 * {@link Zend_Json::TYPE_OBJECT}; defaults to TYPE_ARRAY 146 * @return mixed 147 * @throws Zend_Json_Exception 148 */ 149 public static function decode($source = null, $objectDecodeType = Zend_Json::TYPE_ARRAY) 150 { 151 if (null === $source) { 152 throw new Zend_Json_Exception('Must specify JSON encoded source for decoding'); 153 } elseif (!is_string($source)) { 154 throw new Zend_Json_Exception('Can only decode JSON encoded strings'); 155 } 156 157 $decoder = new self($source, $objectDecodeType); 158 159 return $decoder->_decodeValue(); 160 } 161 162 163 /** 164 * Recursive driving rountine for supported toplevel tops 165 * 166 * @return mixed 167 */ 168 protected function _decodeValue() 169 { 170 switch ($this->_token) { 171 case self::DATUM: 172 $result = $this->_tokenValue; 173 $this->_getNextToken(); 174 return($result); 175 break; 176 case self::LBRACE: 177 return($this->_decodeObject()); 178 break; 179 case self::LBRACKET: 180 return($this->_decodeArray()); 181 break; 182 default: 183 return null; 184 break; 185 } 186 } 187 188 /** 189 * Decodes an object of the form: 190 * { "attribute: value, "attribute2" : value,...} 191 * 192 * If ZJsonEnoder or ZJAjax was used to encode the original object 193 * then a special attribute called __className which specifies a class 194 * name that should wrap the data contained within the encoded source. 195 * 196 * Decodes to either an array or StdClass object, based on the value of 197 * {@link $_decodeType}. If invalid $_decodeType present, returns as an 198 * array. 199 * 200 * @return array|StdClass 201 */ 202 protected function _decodeObject() 203 { 204 $members = array(); 205 $tok = $this->_getNextToken(); 206 207 while ($tok && $tok != self::RBRACE) { 208 if ($tok != self::DATUM || ! is_string($this->_tokenValue)) { 209 throw new Zend_Json_Exception('Missing key in object encoding: ' . $this->_source); 210 } 211 212 $key = $this->_tokenValue; 213 $tok = $this->_getNextToken(); 214 215 if ($tok != self::COLON) { 216 throw new Zend_Json_Exception('Missing ":" in object encoding: ' . $this->_source); 217 } 218 219 $tok = $this->_getNextToken(); 220 $members[$key] = $this->_decodeValue(); 221 $tok = $this->_token; 222 223 if ($tok == self::RBRACE) { 224 break; 225 } 226 227 if ($tok != self::COMMA) { 228 throw new Zend_Json_Exception('Missing "," in object encoding: ' . $this->_source); 229 } 230 231 $tok = $this->_getNextToken(); 232 } 233 234 switch ($this->_decodeType) { 235 case Zend_Json::TYPE_OBJECT: 236 // Create new StdClass and populate with $members 237 $result = new StdClass(); 238 foreach ($members as $key => $value) { 239 $result->$key = $value; 240 } 241 break; 242 case Zend_Json::TYPE_ARRAY: 243 default: 244 $result = $members; 245 break; 246 } 247 248 $this->_getNextToken(); 249 return $result; 250 } 251 252 /** 253 * Decodes a JSON array format: 254 * [element, element2,...,elementN] 255 * 256 * @return array 257 */ 258 protected function _decodeArray() 259 { 260 $result = array(); 261 $starttok = $tok = $this->_getNextToken(); // Move past the '[' 262 $index = 0; 263 264 while ($tok && $tok != self::RBRACKET) { 265 $result[$index++] = $this->_decodeValue(); 266 267 $tok = $this->_token; 268 269 if ($tok == self::RBRACKET || !$tok) { 270 break; 271 } 272 273 if ($tok != self::COMMA) { 274 throw new Zend_Json_Exception('Missing "," in array encoding: ' . $this->_source); 275 } 276 277 $tok = $this->_getNextToken(); 278 } 279 280 $this->_getNextToken(); 281 return($result); 282 } 283 284 285 /** 286 * Removes whitepsace characters from the source input 287 */ 288 protected function _eatWhitespace() 289 { 290 if (preg_match( 291 '/([\t\b\f\n\r ])*/s', 292 $this->_source, 293 $matches, 294 PREG_OFFSET_CAPTURE, 295 $this->_offset) 296 && $matches[0][1] == $this->_offset) 297 { 298 $this->_offset += strlen($matches[0][0]); 299 } 300 } 301 302 303 /** 304 * Retrieves the next token from the source stream 305 * 306 * @return int Token constant value specified in class definition 307 */ 308 protected function _getNextToken() 309 { 310 $this->_token = self::EOF; 311 $this->_tokenValue = null; 312 $this->_eatWhitespace(); 313 314 if ($this->_offset >= $this->_sourceLength) { 315 return(self::EOF); 316 } 317 318 $str = $this->_source; 319 $str_length = $this->_sourceLength; 320 $i = $this->_offset; 321 $start = $i; 322 323 switch ($str{$i}) { 324 case '{': 325 $this->_token = self::LBRACE; 326 break; 327 case '}': 328 $this->_token = self::RBRACE; 329 break; 330 case '[': 331 $this->_token = self::LBRACKET; 332 break; 333 case ']': 334 $this->_token = self::RBRACKET; 335 break; 336 case ',': 337 $this->_token = self::COMMA; 338 break; 339 case ':': 340 $this->_token = self::COLON; 341 break; 342 case '"': 343 $result = ''; 344 do { 345 $i++; 346 if ($i >= $str_length) { 347 break; 348 } 349 350 $chr = $str{$i}; 351 if ($chr == '\\') { 352 $i++; 353 if ($i >= $str_length) { 354 break; 355 } 356 $chr = $str{$i}; 357 switch ($chr) { 358 case '"' : 359 $result .= '"'; 360 break; 361 case '\\': 362 $result .= '\\'; 363 break; 364 case '/' : 365 $result .= '/'; 366 break; 367 case 'b' : 368 $result .= chr(8); 369 break; 370 case 'f' : 371 $result .= chr(12); 372 break; 373 case 'n' : 374 $result .= chr(10); 375 break; 376 case 'r' : 377 $result .= chr(13); 378 break; 379 case 't' : 380 $result .= chr(9); 381 break; 382 case '\'' : 383 $result .= '\''; 384 break; 385 default: 386 throw new Zend_Json_Exception("Illegal escape " 387 . "sequence '" . $chr . "'"); 388 } 389 } elseif ($chr == '"') { 390 break; 391 } else { 392 $result .= $chr; 393 } 394 } while ($i < $str_length); 395 396 $this->_token = self::DATUM; 397 //$this->_tokenValue = substr($str, $start + 1, $i - $start - 1); 398 $this->_tokenValue = $result; 399 break; 400 case 't': 401 if (($i+ 3) < $str_length && substr($str, $start, 4) == "true") { 402 $this->_token = self::DATUM; 403 } 404 $this->_tokenValue = true; 405 $i += 3; 406 break; 407 case 'f': 408 if (($i+ 4) < $str_length && substr($str, $start, 5) == "false") { 409 $this->_token = self::DATUM; 410 } 411 $this->_tokenValue = false; 412 $i += 4; 413 break; 414 case 'n': 415 if (($i+ 3) < $str_length && substr($str, $start, 4) == "null") { 416 $this->_token = self::DATUM; 417 } 418 $this->_tokenValue = NULL; 419 $i += 3; 420 break; 421 } 422 423 if ($this->_token != self::EOF) { 424 $this->_offset = $i + 1; // Consume the last token character 425 return($this->_token); 426 } 427 428 $chr = $str{$i}; 429 if ($chr == '-' || $chr == '.' || ($chr >= '0' && $chr <= '9')) { 430 if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s', 431 $str, $matches, PREG_OFFSET_CAPTURE, $start) && $matches[0][1] == $start) { 432 433 $datum = $matches[0][0]; 434 435 if (is_numeric($datum)) { 436 if (preg_match('/^0\d+$/', $datum)) { 437 throw new Zend_Json_Exception("Octal notation not supported by JSON (value: $datum)"); 438 } else { 439 $val = intval($datum); 440 $fVal = floatval($datum); 441 $this->_tokenValue = ($val == $fVal ? $val : $fVal); 442 } 443 } else { 444 throw new Zend_Json_Exception("Illegal number format: $datum"); 445 } 446 447 $this->_token = self::DATUM; 448 $this->_offset = $start + strlen($datum); 449 } 450 } else { 451 throw new Zend_Json_Exception('Illegal Token'); 452 } 453 454 return($this->_token); 455 } 456 } 457
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |