[ Index ] |
WordPress Cross Reference |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * $Id: JSON.php 40 2007-06-18 11:43:15Z spocke $ 4 * 5 * @package MCManager.utils 6 * @author Moxiecode 7 * @copyright Copyright © 2007, Moxiecode Systems AB, All rights reserved. 8 */ 9 10 define('JSON_BOOL', 1); 11 define('JSON_INT', 2); 12 define('JSON_STR', 3); 13 define('JSON_FLOAT', 4); 14 define('JSON_NULL', 5); 15 define('JSON_START_OBJ', 6); 16 define('JSON_END_OBJ', 7); 17 define('JSON_START_ARRAY', 8); 18 define('JSON_END_ARRAY', 9); 19 define('JSON_KEY', 10); 20 define('JSON_SKIP', 11); 21 22 define('JSON_IN_ARRAY', 30); 23 define('JSON_IN_OBJECT', 40); 24 define('JSON_IN_BETWEEN', 50); 25 26 class Moxiecode_JSONReader { 27 var $_data, $_len, $_pos; 28 var $_value, $_token; 29 var $_location, $_lastLocations; 30 var $_needProp; 31 32 function Moxiecode_JSONReader($data) { 33 $this->_data = $data; 34 $this->_len = strlen($data); 35 $this->_pos = -1; 36 $this->_location = JSON_IN_BETWEEN; 37 $this->_lastLocations = array(); 38 $this->_needProp = false; 39 } 40 41 function getToken() { 42 return $this->_token; 43 } 44 45 function getLocation() { 46 return $this->_location; 47 } 48 49 function getTokenName() { 50 switch ($this->_token) { 51 case JSON_BOOL: 52 return 'JSON_BOOL'; 53 54 case JSON_INT: 55 return 'JSON_INT'; 56 57 case JSON_STR: 58 return 'JSON_STR'; 59 60 case JSON_FLOAT: 61 return 'JSON_FLOAT'; 62 63 case JSON_NULL: 64 return 'JSON_NULL'; 65 66 case JSON_START_OBJ: 67 return 'JSON_START_OBJ'; 68 69 case JSON_END_OBJ: 70 return 'JSON_END_OBJ'; 71 72 case JSON_START_ARRAY: 73 return 'JSON_START_ARRAY'; 74 75 case JSON_END_ARRAY: 76 return 'JSON_END_ARRAY'; 77 78 case JSON_KEY: 79 return 'JSON_KEY'; 80 } 81 82 return 'UNKNOWN'; 83 } 84 85 function getValue() { 86 return $this->_value; 87 } 88 89 function readToken() { 90 $chr = $this->read(); 91 92 if ($chr != null) { 93 switch ($chr) { 94 case '[': 95 $this->_lastLocation[] = $this->_location; 96 $this->_location = JSON_IN_ARRAY; 97 $this->_token = JSON_START_ARRAY; 98 $this->_value = null; 99 $this->readAway(); 100 return true; 101 102 case ']': 103 $this->_location = array_pop($this->_lastLocation); 104 $this->_token = JSON_END_ARRAY; 105 $this->_value = null; 106 $this->readAway(); 107 108 if ($this->_location == JSON_IN_OBJECT) 109 $this->_needProp = true; 110 111 return true; 112 113 case '{': 114 $this->_lastLocation[] = $this->_location; 115 $this->_location = JSON_IN_OBJECT; 116 $this->_needProp = true; 117 $this->_token = JSON_START_OBJ; 118 $this->_value = null; 119 $this->readAway(); 120 return true; 121 122 case '}': 123 $this->_location = array_pop($this->_lastLocation); 124 $this->_token = JSON_END_OBJ; 125 $this->_value = null; 126 $this->readAway(); 127 128 if ($this->_location == JSON_IN_OBJECT) 129 $this->_needProp = true; 130 131 return true; 132 133 // String 134 case '"': 135 case '\'': 136 return $this->_readString($chr); 137 138 // Null 139 case 'n': 140 return $this->_readNull(); 141 142 // Bool 143 case 't': 144 case 'f': 145 return $this->_readBool($chr); 146 147 default: 148 // Is number 149 if (is_numeric($chr) || $chr == '-' || $chr == '.') 150 return $this->_readNumber($chr); 151 152 return true; 153 } 154 } 155 156 return false; 157 } 158 159 function _readBool($chr) { 160 $this->_token = JSON_BOOL; 161 $this->_value = $chr == 't'; 162 163 if ($chr == 't') 164 $this->skip(3); // rue 165 else 166 $this->skip(4); // alse 167 168 $this->readAway(); 169 170 if ($this->_location == JSON_IN_OBJECT && !$this->_needProp) 171 $this->_needProp = true; 172 173 return true; 174 } 175 176 function _readNull() { 177 $this->_token = JSON_NULL; 178 $this->_value = null; 179 180 $this->skip(3); // ull 181 $this->readAway(); 182 183 if ($this->_location == JSON_IN_OBJECT && !$this->_needProp) 184 $this->_needProp = true; 185 186 return true; 187 } 188 189 function _readString($quote) { 190 $output = ""; 191 $this->_token = JSON_STR; 192 $endString = false; 193 194 while (($chr = $this->peek()) != -1) { 195 switch ($chr) { 196 case '\\': 197 // Read away slash 198 $this->read(); 199 200 // Read escape code 201 $chr = $this->read(); 202 switch ($chr) { 203 case 't': 204 $output .= "\t"; 205 break; 206 207 case 'b': 208 $output .= "\b"; 209 break; 210 211 case 'f': 212 $output .= "\f"; 213 break; 214 215 case 'r': 216 $output .= "\r"; 217 break; 218 219 case 'n': 220 $output .= "\n"; 221 break; 222 223 case 'u': 224 $output .= $this->_int2utf8(hexdec($this->read(4))); 225 break; 226 227 default: 228 $output .= $chr; 229 break; 230 } 231 232 break; 233 234 case '\'': 235 case '"': 236 if ($chr == $quote) 237 $endString = true; 238 239 $chr = $this->read(); 240 if ($chr != -1 && $chr != $quote) 241 $output .= $chr; 242 243 break; 244 245 default: 246 $output .= $this->read(); 247 } 248 249 // String terminated 250 if ($endString) 251 break; 252 } 253 254 $this->readAway(); 255 $this->_value = $output; 256 257 // Needed a property 258 if ($this->_needProp) { 259 $this->_token = JSON_KEY; 260 $this->_needProp = false; 261 return true; 262 } 263 264 if ($this->_location == JSON_IN_OBJECT && !$this->_needProp) 265 $this->_needProp = true; 266 267 return true; 268 } 269 270 function _int2utf8($int) { 271 $int = intval($int); 272 273 switch ($int) { 274 case 0: 275 return chr(0); 276 277 case ($int & 0x7F): 278 return chr($int); 279 280 case ($int & 0x7FF): 281 return chr(0xC0 | (($int >> 6) & 0x1F)) . chr(0x80 | ($int & 0x3F)); 282 283 case ($int & 0xFFFF): 284 return chr(0xE0 | (($int >> 12) & 0x0F)) . chr(0x80 | (($int >> 6) & 0x3F)) . chr (0x80 | ($int & 0x3F)); 285 286 case ($int & 0x1FFFFF): 287 return chr(0xF0 | ($int >> 18)) . chr(0x80 | (($int >> 12) & 0x3F)) . chr(0x80 | (($int >> 6) & 0x3F)) . chr(0x80 | ($int & 0x3F)); 288 } 289 } 290 291 function _readNumber($start) { 292 $value = ""; 293 $isFloat = false; 294 295 $this->_token = JSON_INT; 296 $value .= $start; 297 298 while (($chr = $this->peek()) != -1) { 299 if (is_numeric($chr) || $chr == '-' || $chr == '.') { 300 if ($chr == '.') 301 $isFloat = true; 302 303 $value .= $this->read(); 304 } else 305 break; 306 } 307 308 $this->readAway(); 309 310 if ($isFloat) { 311 $this->_token = JSON_FLOAT; 312 $this->_value = floatval($value); 313 } else 314 $this->_value = intval($value); 315 316 if ($this->_location == JSON_IN_OBJECT && !$this->_needProp) 317 $this->_needProp = true; 318 319 return true; 320 } 321 322 function readAway() { 323 while (($chr = $this->peek()) != null) { 324 if ($chr != ':' && $chr != ',' && $chr != ' ') 325 return; 326 327 $this->read(); 328 } 329 } 330 331 function read($len = 1) { 332 if ($this->_pos < $this->_len) { 333 if ($len > 1) { 334 $str = substr($this->_data, $this->_pos + 1, $len); 335 $this->_pos += $len; 336 337 return $str; 338 } else 339 return $this->_data[++$this->_pos]; 340 } 341 342 return null; 343 } 344 345 function skip($len) { 346 $this->_pos += $len; 347 } 348 349 function peek() { 350 if ($this->_pos < $this->_len) 351 return $this->_data[$this->_pos + 1]; 352 353 return null; 354 } 355 } 356 357 /** 358 * This class handles JSON stuff. 359 * 360 * @package MCManager.utils 361 */ 362 class Moxiecode_JSON { 363 function Moxiecode_JSON() { 364 } 365 366 function decode($input) { 367 $reader = new Moxiecode_JSONReader($input); 368 369 return $this->readValue($reader); 370 } 371 372 function readValue(&$reader) { 373 $this->data = array(); 374 $this->parents = array(); 375 $this->cur =& $this->data; 376 $key = null; 377 $loc = JSON_IN_ARRAY; 378 379 while ($reader->readToken()) { 380 switch ($reader->getToken()) { 381 case JSON_STR: 382 case JSON_INT: 383 case JSON_BOOL: 384 case JSON_FLOAT: 385 case JSON_NULL: 386 switch ($reader->getLocation()) { 387 case JSON_IN_OBJECT: 388 $this->cur[$key] = $reader->getValue(); 389 break; 390 391 case JSON_IN_ARRAY: 392 $this->cur[] = $reader->getValue(); 393 break; 394 395 default: 396 return $reader->getValue(); 397 } 398 break; 399 400 case JSON_KEY: 401 $key = $reader->getValue(); 402 break; 403 404 case JSON_START_OBJ: 405 case JSON_START_ARRAY: 406 if ($loc == JSON_IN_OBJECT) 407 $this->addArray($key); 408 else 409 $this->addArray(null); 410 411 $cur =& $obj; 412 413 $loc = $reader->getLocation(); 414 break; 415 416 case JSON_END_OBJ: 417 case JSON_END_ARRAY: 418 $loc = $reader->getLocation(); 419 420 if (count($this->parents) > 0) { 421 $this->cur =& $this->parents[count($this->parents) - 1]; 422 array_pop($this->parents); 423 } 424 break; 425 } 426 } 427 428 return $this->data[0]; 429 } 430 431 // This method was needed since PHP is crapy and doesn't have pointers/references 432 function addArray($key) { 433 $this->parents[] =& $this->cur; 434 $ar = array(); 435 436 if ($key) 437 $this->cur[$key] =& $ar; 438 else 439 $this->cur[] =& $ar; 440 441 $this->cur =& $ar; 442 } 443 444 function getDelim($index, &$reader) { 445 switch ($reader->getLocation()) { 446 case JSON_IN_ARRAY: 447 case JSON_IN_OBJECT: 448 if ($index > 0) 449 return ","; 450 break; 451 } 452 453 return ""; 454 } 455 456 function encode($input) { 457 switch (gettype($input)) { 458 case 'boolean': 459 return $input ? 'true' : 'false'; 460 461 case 'integer': 462 return (int) $input; 463 464 case 'float': 465 case 'double': 466 return (float) $input; 467 468 case 'NULL': 469 return 'null'; 470 471 case 'string': 472 return $this->encodeString($input); 473 474 case 'array': 475 return $this->_encodeArray($input); 476 477 case 'object': 478 return $this->_encodeArray(get_object_vars($input)); 479 } 480 481 return ''; 482 } 483 484 function encodeString($input) { 485 // Needs to be escaped 486 if (preg_match('/[^a-zA-Z0-9]/', $input)) { 487 $output = ''; 488 489 for ($i=0; $i<strlen($input); $i++) { 490 switch ($input[$i]) { 491 case "\b": 492 $output .= "\\b"; 493 break; 494 495 case "\t": 496 $output .= "\\t"; 497 break; 498 499 case "\f": 500 $output .= "\\f"; 501 break; 502 503 case "\r": 504 $output .= "\\r"; 505 break; 506 507 case "\n": 508 $output .= "\\n"; 509 break; 510 511 case '\\': 512 $output .= "\\\\"; 513 break; 514 515 case '\'': 516 $output .= "\\'"; 517 break; 518 519 case '"': 520 $output .= '\"'; 521 break; 522 523 default: 524 $byte = ord($input[$i]); 525 526 if (($byte & 0xE0) == 0xC0) { 527 $char = pack('C*', $byte, ord($input[$i + 1])); 528 $i += 1; 529 $output .= sprintf('\u%04s', bin2hex($this->_utf82utf16($char))); 530 } if (($byte & 0xF0) == 0xE0) { 531 $char = pack('C*', $byte, ord($input[$i + 1]), ord($input[$i + 2])); 532 $i += 2; 533 $output .= sprintf('\u%04s', bin2hex($this->_utf82utf16($char))); 534 } if (($byte & 0xF8) == 0xF0) { 535 $char = pack('C*', $byte, ord($input[$i + 1]), ord($input[$i + 2]), ord($input[$i + 3])); 536 $i += 3; 537 $output .= sprintf('\u%04s', bin2hex($this->_utf82utf16($char))); 538 } if (($byte & 0xFC) == 0xF8) { 539 $char = pack('C*', $byte, ord($input[$i + 1]), ord($input[$i + 2]), ord($input[$i + 3]), ord($input[$i + 4])); 540 $i += 4; 541 $output .= sprintf('\u%04s', bin2hex($this->_utf82utf16($char))); 542 } if (($byte & 0xFE) == 0xFC) { 543 $char = pack('C*', $byte, ord($input[$i + 1]), ord($input[$i + 2]), ord($input[$i + 3]), ord($input[$i + 4]), ord($input[$i + 5])); 544 $i += 5; 545 $output .= sprintf('\u%04s', bin2hex($this->_utf82utf16($char))); 546 } else if ($byte < 128) 547 $output .= $input[$i]; 548 } 549 } 550 551 return '"' . $output . '"'; 552 } 553 554 return '"' . $input . '"'; 555 } 556 557 function _utf82utf16($utf8) { 558 if (function_exists('mb_convert_encoding')) 559 return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); 560 561 switch (strlen($utf8)) { 562 case 1: 563 return $utf8; 564 565 case 2: 566 return chr(0x07 & (ord($utf8[0]) >> 2)) . chr((0xC0 & (ord($utf8[0]) << 6)) | (0x3F & ord($utf8[1]))); 567 568 case 3: 569 return chr((0xF0 & (ord($utf8[0]) << 4)) | (0x0F & (ord($utf8[1]) >> 2))) . chr((0xC0 & (ord($utf8[1]) << 6)) | (0x7F & ord($utf8[2]))); 570 } 571 572 return ''; 573 } 574 575 function _encodeArray($input) { 576 $output = ''; 577 $isIndexed = true; 578 579 $keys = array_keys($input); 580 for ($i=0; $i<count($keys); $i++) { 581 if (!is_int($keys[$i])) { 582 $output .= $this->encodeString($keys[$i]) . ':' . $this->encode($input[$keys[$i]]); 583 $isIndexed = false; 584 } else 585 $output .= $this->encode($input[$keys[$i]]); 586 587 if ($i != count($keys) - 1) 588 $output .= ','; 589 } 590 591 return $isIndexed ? '[' . $output . ']' : '{' . $output . '}'; 592 } 593 } 594 595 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 25 01:41:18 2014 | WordPress honlapkĂ©szĂtĂ©s: online1.hu |