root/ext/json/JSON_parser.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. push
  2. pop
  3. new_JSON_parser
  4. free_JSON_parser
  5. dehexchar
  6. json_create_zval
  7. utf16_to_utf8
  8. attach_zval
  9. parse_JSON_ex

   1 /* JSON_parser.c */
   2 
   3 /* 2005-12-30 */
   4 
   5 /*
   6 Copyright (c) 2005 JSON.org
   7 
   8 Permission is hereby granted, free of charge, to any person obtaining a copy
   9 of this software and associated documentation files (the "Software"), to deal
  10 in the Software without restriction, including without limitation the rights
  11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12 copies of the Software, and to permit persons to whom the Software is
  13 furnished to do so, subject to the following conditions:
  14 
  15 The above copyright notice and this permission notice shall be included in all
  16 copies or substantial portions of the Software.
  17 
  18 The Software shall be used for Good, not Evil.
  19 
  20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  26 SOFTWARE.
  27 */
  28 
  29 #include <stdio.h>
  30 #include "JSON_parser.h"
  31 
  32 /* Windows defines IN for documentation */
  33 #undef IN
  34 
  35 #define true  1
  36 #define false 0
  37 #define __   -1     /* the universal error code */
  38 
  39 /*
  40     Characters are mapped into these 31 character classes. This allows for
  41     a significant reduction in the size of the state transition table.
  42 */
  43 
  44 enum classes {
  45     C_SPACE,  /* space */
  46     C_WHITE,  /* other whitespace */
  47     C_LCURB,  /* {  */
  48     C_RCURB,  /* } */
  49     C_LSQRB,  /* [ */
  50     C_RSQRB,  /* ] */
  51     C_COLON,  /* : */
  52     C_COMMA,  /* , */
  53     C_QUOTE,  /* " */
  54     C_BACKS,  /* \ */
  55     C_SLASH,  /* / */
  56     C_PLUS,   /* + */
  57     C_MINUS,  /* - */
  58     C_POINT,  /* . */
  59     C_ZERO ,  /* 0 */
  60     C_DIGIT,  /* 123456789 */
  61     C_LOW_A,  /* a */
  62     C_LOW_B,  /* b */
  63     C_LOW_C,  /* c */
  64     C_LOW_D,  /* d */
  65     C_LOW_E,  /* e */
  66     C_LOW_F,  /* f */
  67     C_LOW_L,  /* l */
  68     C_LOW_N,  /* n */
  69     C_LOW_R,  /* r */
  70     C_LOW_S,  /* s */
  71     C_LOW_T,  /* t */
  72     C_LOW_U,  /* u */
  73     C_ABCDF,  /* ABCDF */
  74     C_E,      /* E */
  75     C_ETC,    /* everything else */
  76     NR_CLASSES
  77 };
  78 
  79 static const int ascii_class[128] = {
  80 /*
  81     This array maps the 128 ASCII characters into character classes.
  82     The remaining Unicode characters should be mapped to C_ETC.
  83     Non-whitespace control characters are errors.
  84 */
  85     __,      __,      __,      __,      __,      __,      __,      __,
  86     __,      C_WHITE, C_WHITE, __,      __,      C_WHITE, __,      __,
  87     __,      __,      __,      __,      __,      __,      __,      __,
  88     __,      __,      __,      __,      __,      __,      __,      __,
  89 
  90     C_SPACE, C_ETC,   C_QUOTE, C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
  91     C_ETC,   C_ETC,   C_ETC,   C_PLUS,  C_COMMA, C_MINUS, C_POINT, C_SLASH,
  92     C_ZERO,  C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT,
  93     C_DIGIT, C_DIGIT, C_COLON, C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
  94 
  95     C_ETC,   C_ABCDF, C_ABCDF, C_ABCDF, C_ABCDF, C_E,     C_ABCDF, C_ETC,
  96     C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
  97     C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
  98     C_ETC,   C_ETC,   C_ETC,   C_LSQRB, C_BACKS, C_RSQRB, C_ETC,   C_ETC,
  99 
 100     C_ETC,   C_LOW_A, C_LOW_B, C_LOW_C, C_LOW_D, C_LOW_E, C_LOW_F, C_ETC,
 101     C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_LOW_L, C_ETC,   C_LOW_N, C_ETC,
 102     C_ETC,   C_ETC,   C_LOW_R, C_LOW_S, C_LOW_T, C_LOW_U, C_ETC,   C_ETC,
 103     C_ETC,   C_ETC,   C_ETC,   C_LCURB, C_ETC,   C_RCURB, C_ETC,   C_ETC
 104 };
 105 
 106 
 107 /*
 108     The state codes.
 109 */
 110 enum states {
 111     GO,  /* start    */
 112     OK,  /* ok       */
 113     OB,  /* object   */
 114     KE,  /* key      */
 115     CO,  /* colon    */
 116     VA,  /* value    */
 117     AR,  /* array    */
 118     ST,  /* string   */
 119     ES,  /* escape   */
 120     U1,  /* u1       */
 121     U2,  /* u2       */
 122     U3,  /* u3       */
 123     U4,  /* u4       */
 124     MI,  /* minus    */
 125     ZE,  /* zero     */
 126     IN,  /* integer  */
 127     FR,  /* fraction */
 128     E1,  /* e        */
 129     E2,  /* ex       */
 130     E3,  /* exp      */
 131     T1,  /* tr       */
 132     T2,  /* tru      */
 133     T3,  /* true     */
 134     F1,  /* fa       */
 135     F2,  /* fal      */
 136     F3,  /* fals     */
 137     F4,  /* false    */
 138     N1,  /* nu       */
 139     N2,  /* nul      */
 140     N3,  /* null     */
 141     NR_STATES
 142 };
 143 
 144 
 145 static const int state_transition_table[NR_STATES][NR_CLASSES] = {
 146 /*
 147     The state transition table takes the current state and the current symbol,
 148     and returns either a new state or an action. An action is represented as a
 149     negative number. A JSON text is accepted if at the end of the text the
 150     state is OK and if the mode is MODE_DONE.
 151 
 152                  white                                      1-9                                   ABCDF  etc
 153              space |  {  }  [  ]  :  ,  "  \  /  +  -  .  0  |  a  b  c  d  e  f  l  n  r  s  t  u  |  E  |*/
 154 /*start  GO*/ {GO,GO,-6,__,-5,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
 155 /*ok     OK*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
 156 /*object OB*/ {OB,OB,__,-9,__,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
 157 /*key    KE*/ {KE,KE,__,__,__,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
 158 /*colon  CO*/ {CO,CO,__,__,__,__,-2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
 159 /*value  VA*/ {VA,VA,-6,__,-5,__,__,__,ST,__,__,__,MI,__,ZE,IN,__,__,__,__,__,F1,__,N1,__,__,T1,__,__,__,__},
 160 /*array  AR*/ {AR,AR,-6,__,-5,-7,__,__,ST,__,__,__,MI,__,ZE,IN,__,__,__,__,__,F1,__,N1,__,__,T1,__,__,__,__},
 161 /*string ST*/ {ST,__,ST,ST,ST,ST,ST,ST,-4,ES,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST},
 162 /*escape ES*/ {__,__,__,__,__,__,__,__,ST,ST,ST,__,__,__,__,__,__,ST,__,__,__,ST,__,ST,ST,__,ST,U1,__,__,__},
 163 /*u1     U1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U2,U2,U2,U2,U2,U2,U2,U2,__,__,__,__,__,__,U2,U2,__},
 164 /*u2     U2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U3,U3,U3,U3,U3,U3,U3,U3,__,__,__,__,__,__,U3,U3,__},
 165 /*u3     U3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U4,U4,U4,U4,U4,U4,U4,U4,__,__,__,__,__,__,U4,U4,__},
 166 /*u4     U4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,ST,ST,ST,ST,ST,ST,ST,ST,__,__,__,__,__,__,ST,ST,__},
 167 /*minus  MI*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,ZE,IN,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
 168 /*zero   ZE*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,FR,__,__,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
 169 /*int    IN*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,FR,IN,IN,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
 170 /*frac   FR*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,FR,FR,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
 171 /*e      E1*/ {__,__,__,__,__,__,__,__,__,__,__,E2,E2,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
 172 /*ex     E2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
 173 /*exp    E3*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
 174 /*tr     T1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T2,__,__,__,__,__,__},
 175 /*tru    T2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T3,__,__,__},
 176 /*true   T3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__},
 177 /*fa     F1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F2,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
 178 /*fal    F2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F3,__,__,__,__,__,__,__,__},
 179 /*fals   F3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F4,__,__,__,__,__},
 180 /*false  F4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__},
 181 /*nu     N1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N2,__,__,__},
 182 /*nul    N2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N3,__,__,__,__,__,__,__,__},
 183 /*null   N3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__},
 184 };
 185 
 186 
 187 /*
 188     These modes can be pushed on the stack.
 189 */
 190 enum modes {
 191     MODE_ARRAY, 
 192     MODE_DONE,  
 193     MODE_KEY,   
 194     MODE_OBJECT,
 195 };
 196 
 197 
 198 /*
 199     Push a mode onto the stack. Return false if there is overflow.
 200 */
 201 static int
 202 push(JSON_parser jp, int mode)
 203 {
 204     jp->top += 1;
 205     if (jp->top >= jp->depth) {
 206                 jp->error_code = PHP_JSON_ERROR_DEPTH;
 207         return false;
 208     }
 209     jp->stack[jp->top] = mode;
 210     return true;
 211 }
 212 
 213 
 214 /*
 215     Pop the stack, assuring that the current mode matches the expectation.
 216     Return false if there is underflow or if the modes mismatch.
 217 */
 218 static int
 219 pop(JSON_parser jp, int mode)
 220 {
 221     if (jp->top < 0 || jp->stack[jp->top] != mode) {
 222                 jp->error_code = PHP_JSON_ERROR_STATE_MISMATCH;
 223         return false;
 224     }
 225     jp->top -= 1;
 226     return true;
 227 }
 228 
 229 /*
 230     new_JSON_checker starts the checking process by constructing a JSON_checker
 231     object. It takes a depth parameter that restricts the level of maximum
 232     nesting.
 233 
 234     To continue the process, call JSON_checker_char for each character in the
 235     JSON text, and then call JSON_checker_done to obtain the final result.
 236     These functions are fully reentrant.
 237 
 238     The JSON_checker object will be deleted by JSON_checker_done.
 239     JSON_checker_char will delete the JSON_checker object if it sees an error.
 240 */
 241 JSON_parser
 242 new_JSON_parser(int depth)
 243 {
 244     JSON_parser jp = (JSON_parser)emalloc(sizeof(struct JSON_parser_struct));
 245     jp->state = GO;
 246     jp->depth = depth;
 247     jp->top = -1;
 248         jp->error_code = PHP_JSON_ERROR_NONE;
 249     jp->stack = (int*)ecalloc(depth, sizeof(int));
 250     if (depth > JSON_PARSER_DEFAULT_DEPTH) {
 251         jp->the_zstack = (zval **)safe_emalloc(depth, sizeof(zval), 0);
 252     } else {
 253         jp->the_zstack = &jp->the_static_zstack[0];
 254     }
 255     push(jp, MODE_DONE);
 256     return jp;
 257 }
 258 
 259 /*
 260     Delete the JSON_parser object.
 261 */
 262 int
 263 free_JSON_parser(JSON_parser jp)
 264 {
 265     efree((void*)jp->stack);
 266     if (jp->the_zstack != &jp->the_static_zstack[0]) {
 267         efree(jp->the_zstack);
 268     }
 269     efree((void*)jp);
 270     return false;
 271 }
 272 
 273 static int dehexchar(char c)
 274 {
 275     if (c >= '0' && c <= '9')
 276     {
 277         return c - '0';
 278     }
 279     else if (c >= 'A' && c <= 'F')
 280     {
 281         return c - ('A' - 10);
 282     }
 283     else if (c >= 'a' && c <= 'f')
 284     {
 285         return c - ('a' - 10);
 286     }
 287     else
 288     {
 289         return -1;
 290     }
 291 }
 292 
 293 
 294 static void json_create_zval(zval **z, smart_str *buf, int type, int options)
 295 {
 296     ALLOC_INIT_ZVAL(*z);
 297 
 298     if (type == IS_LONG)
 299     {
 300                 zend_bool bigint = 0;
 301 
 302                 if (buf->c[0] == '-') {
 303                         buf->len--;
 304                 }
 305 
 306                 if (buf->len >= MAX_LENGTH_OF_LONG - 1) {
 307                         if (buf->len == MAX_LENGTH_OF_LONG - 1) {
 308                                 int cmp = strcmp(buf->c + (buf->c[0] == '-'), long_min_digits);
 309 
 310                                 if (!(cmp < 0 || (cmp == 0 && buf->c[0] == '-'))) {
 311                                         bigint = 1;
 312                                 }
 313                         } else {
 314                                 bigint = 1;
 315                         }
 316                 }
 317 
 318                 if (bigint) {
 319                         /* value too large to represent as a long */
 320                         if (options & PHP_JSON_BIGINT_AS_STRING) {
 321                                 if (buf->c[0] == '-') {
 322                                         /* Restore last char consumed above */
 323                                         buf->len++;
 324                                 }
 325                                 goto use_string;
 326                         } else {
 327                                 goto use_double;
 328                         }
 329                 }
 330 
 331                 ZVAL_LONG(*z, strtol(buf->c, NULL, 10));
 332     }
 333     else if (type == IS_DOUBLE)
 334     {
 335 use_double:
 336         ZVAL_DOUBLE(*z, zend_strtod(buf->c, NULL));
 337     }
 338     else if (type == IS_STRING)
 339     {
 340 use_string:
 341         ZVAL_STRINGL(*z, buf->c, buf->len, 1);
 342     }
 343     else if (type == IS_BOOL)
 344     {
 345         ZVAL_BOOL(*z, (*(buf->c) == 't'));
 346     }
 347     else /* type == IS_NULL) || type unknown */
 348     {
 349         ZVAL_NULL(*z);
 350     }
 351 }
 352 
 353 
 354 static void utf16_to_utf8(smart_str *buf, unsigned short utf16)
 355 {
 356     if (utf16 < 0x80)
 357     {
 358         smart_str_appendc(buf, (unsigned char) utf16);
 359     }
 360     else if (utf16 < 0x800)
 361     {
 362         smart_str_appendc(buf, 0xc0 | (utf16 >> 6));
 363         smart_str_appendc(buf, 0x80 | (utf16 & 0x3f));
 364     }
 365     else if ((utf16 & 0xfc00) == 0xdc00
 366                 && buf->len >= 3
 367                 && ((unsigned char) buf->c[buf->len - 3]) == 0xed
 368                 && ((unsigned char) buf->c[buf->len - 2] & 0xf0) == 0xa0
 369                 && ((unsigned char) buf->c[buf->len - 1] & 0xc0) == 0x80)
 370     {
 371         /* found surrogate pair */
 372         unsigned long utf32;
 373 
 374         utf32 = (((buf->c[buf->len - 2] & 0xf) << 16)
 375                     | ((buf->c[buf->len - 1] & 0x3f) << 10)
 376                     | (utf16 & 0x3ff)) + 0x10000;
 377         buf->len -= 3;
 378 
 379         smart_str_appendc(buf, (unsigned char) (0xf0 | (utf32 >> 18)));
 380         smart_str_appendc(buf, 0x80 | ((utf32 >> 12) & 0x3f));
 381         smart_str_appendc(buf, 0x80 | ((utf32 >> 6) & 0x3f));
 382         smart_str_appendc(buf, 0x80 | (utf32 & 0x3f));
 383     }
 384     else
 385     {
 386         smart_str_appendc(buf, 0xe0 | (utf16 >> 12));
 387         smart_str_appendc(buf, 0x80 | ((utf16 >> 6) & 0x3f));
 388         smart_str_appendc(buf, 0x80 | (utf16 & 0x3f));
 389     }
 390 }
 391 
 392 static void attach_zval(JSON_parser jp, int up, int cur, smart_str *key, int assoc TSRMLS_DC)
 393 {
 394     zval *root = jp->the_zstack[up];
 395     zval *child =  jp->the_zstack[cur];
 396     int up_mode = jp->stack[up];
 397 
 398     if (up_mode == MODE_ARRAY)
 399     {
 400         add_next_index_zval(root, child);
 401     }
 402     else if (up_mode == MODE_OBJECT)
 403     {
 404         if (!assoc)
 405         {
 406             add_property_zval_ex(root, (key->len ? key->c : "_empty_"), (key->len ? (key->len + 1) : sizeof("_empty_")), child TSRMLS_CC);
 407             Z_DELREF_P(child);
 408         }
 409         else
 410         {
 411             add_assoc_zval_ex(root, (key->len ? key->c : ""), (key->len ? (key->len + 1) : sizeof("")), child);
 412         }
 413         key->len = 0;
 414     }
 415 }
 416 
 417 
 418 #define FREE_BUFFERS() smart_str_free(&buf); smart_str_free(&key);
 419 #define SWAP_BUFFERS(from, to) do { \
 420         char *t1 = from.c; \
 421         int t2 = from.a; \
 422         from.c = to.c; \
 423         from.a = to.a; \
 424         to.c = t1; \
 425         to.a = t2; \
 426         to.len = from.len; \
 427         from.len = 0; \
 428         } while(0);
 429 #define JSON_RESET_TYPE() type = -1;
 430 
 431 /*
 432     The JSON_parser takes a UTF-16 encoded string and determines if it is a
 433     syntactically correct JSON text. Along the way, it creates a PHP variable.
 434 
 435     It is implemented as a Pushdown Automaton; that means it is a finite state
 436     machine with a stack.
 437 */
 438 int
 439 parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int options TSRMLS_DC)
 440 {
 441     int next_char;  /* the next character */
 442     int next_class;  /* the next character class */
 443     int next_state;  /* the next state */
 444     int the_index;
 445     int assoc = options & PHP_JSON_OBJECT_AS_ARRAY;
 446 
 447     smart_str buf = {0};
 448     smart_str key = {0};
 449 
 450     unsigned short utf16 = 0;
 451     int type;
 452 
 453         JSON_RESET_TYPE();
 454 
 455     for (the_index = 0; the_index < length; the_index += 1) {
 456         next_char = utf16_json[the_index];
 457                 if (next_char >= 128) {
 458                         next_class = C_ETC;
 459                 } else {
 460                         next_class = ascii_class[next_char];
 461                         if (next_class <= __) {
 462                                 jp->error_code = PHP_JSON_ERROR_CTRL_CHAR;
 463                                 FREE_BUFFERS();
 464                                 return false;
 465                         }
 466                 }
 467 /*
 468     Get the next state from the transition table.
 469 */
 470         next_state = state_transition_table[jp->state][next_class];
 471         if (next_state >= 0) {
 472 /*
 473     Change the state and iterate
 474 */
 475                         if (type == IS_STRING) {
 476                     if (next_state == ST && jp->state != U4) {
 477                         if (jp->state != ES) {
 478                             utf16_to_utf8(&buf, next_char);
 479                         } else {
 480                             switch (next_char) {
 481                                 case 'b':
 482                                     smart_str_appendc(&buf, '\b');
 483                                     break;
 484                                 case 't':
 485                                     smart_str_appendc(&buf, '\t');
 486                                     break;
 487                                 case 'n':
 488                                     smart_str_appendc(&buf, '\n');
 489                                     break;
 490                                 case 'f':
 491                                     smart_str_appendc(&buf, '\f');
 492                                     break;
 493                                 case 'r':
 494                                     smart_str_appendc(&buf, '\r');
 495                                     break;
 496                                 default:
 497                                     utf16_to_utf8(&buf, next_char);
 498                                     break;
 499                             }
 500                         }
 501                     } else if (next_state == U2) {
 502                         utf16 = dehexchar(next_char) << 12;
 503                     } else if (next_state == U3) {
 504                         utf16 += dehexchar(next_char) << 8;
 505                     } else if (next_state == U4) {
 506                         utf16 += dehexchar(next_char) << 4;
 507                     } else if (next_state == ST && jp->state == U4) {
 508                         utf16 += dehexchar(next_char);
 509                         utf16_to_utf8(&buf, utf16);
 510                     }
 511                 } else if (type < IS_LONG && (next_class == C_DIGIT || next_class == C_ZERO)) {
 512                     type = IS_LONG;
 513                     smart_str_appendc(&buf, next_char);
 514                 } else if (type == IS_LONG && next_state == E1) {
 515                     type = IS_DOUBLE;
 516                     smart_str_appendc(&buf, next_char);
 517                 } else if (type < IS_DOUBLE && next_class == C_POINT) {
 518                     type = IS_DOUBLE;
 519                     smart_str_appendc(&buf, next_char);
 520                 } else if (type < IS_STRING && next_class == C_QUOTE) {
 521                     type = IS_STRING;
 522                 } else if (type < IS_BOOL && ((jp->state == T3 && next_state == OK) || (jp->state == F4 && next_state == OK))) {
 523                     type = IS_BOOL;
 524                 } else if (type < IS_NULL && jp->state == N3 && next_state == OK) {
 525                     type = IS_NULL;
 526                 } else if (type != IS_STRING && next_class > C_WHITE) {
 527                     utf16_to_utf8(&buf, next_char);
 528                 }
 529                 jp->state = next_state;
 530                 } else {
 531 /*
 532     Perform one of the predefined actions.
 533 */
 534             switch (next_state) {
 535 /* empty } */
 536             case -9:
 537                 if (!pop(jp, MODE_KEY)) {
 538                     FREE_BUFFERS();
 539                     return false;
 540                 }
 541                 jp->state = OK;
 542                 break;
 543 /* } */
 544             case -8:
 545                 if (type != -1 && jp->stack[jp->top] == MODE_OBJECT)
 546                 {
 547                     zval *mval;
 548                     smart_str_0(&buf);
 549 
 550                     json_create_zval(&mval, &buf, type, options);
 551 
 552                     if (!assoc) {
 553                         add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
 554                         Z_DELREF_P(mval);
 555                     } else {
 556                         add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
 557                     }
 558                     key.len = 0;
 559                     buf.len = 0;
 560                     JSON_RESET_TYPE();
 561                 }
 562 
 563 
 564                 if (!pop(jp, MODE_OBJECT)) {
 565                     FREE_BUFFERS();
 566                     return false;
 567                 }
 568                 jp->state = OK;
 569                 break;
 570 /* ] */
 571             case -7:
 572             {
 573                 if (type != -1 && jp->stack[jp->top] == MODE_ARRAY)
 574                 {
 575                     zval *mval;
 576                     smart_str_0(&buf);
 577 
 578                     json_create_zval(&mval, &buf, type, options);
 579                     add_next_index_zval(jp->the_zstack[jp->top], mval);
 580                     buf.len = 0;
 581                     JSON_RESET_TYPE();
 582                 }
 583 
 584                 if (!pop(jp, MODE_ARRAY)) {
 585                     FREE_BUFFERS();
 586                     return false;
 587                 }
 588                 jp->state = OK;
 589             }
 590                         break;
 591 /* { */
 592             case -6:
 593                 if (!push(jp, MODE_KEY)) {
 594                     FREE_BUFFERS();
 595                     return false;
 596                 }
 597 
 598                 jp->state = OB;
 599                 if (jp->top > 0) {
 600                     zval *obj;
 601 
 602                     if (jp->top == 1) {
 603                         obj = z;
 604                         } else {
 605                         ALLOC_INIT_ZVAL(obj);
 606                     }
 607 
 608                     if (!assoc) {
 609                         object_init(obj);
 610                     } else {
 611                         array_init(obj);
 612                     }
 613 
 614                     jp->the_zstack[jp->top] = obj;
 615 
 616                     if (jp->top > 1) {
 617                         attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
 618                     }
 619 
 620                     JSON_RESET_TYPE();
 621                 }
 622 
 623                 break;
 624 /* [ */
 625             case -5:
 626                 if (!push(jp, MODE_ARRAY)) {
 627                     FREE_BUFFERS();
 628                     return false;
 629                 }
 630                 jp->state = AR;
 631 
 632                 if (jp->top > 0) {
 633                     zval *arr;
 634 
 635                     if (jp->top == 1) {
 636                         arr = z;
 637                     } else {
 638                         ALLOC_INIT_ZVAL(arr);
 639                     }
 640 
 641                     array_init(arr);
 642                     jp->the_zstack[jp->top] = arr;
 643 
 644                     if (jp->top > 1) {
 645                         attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
 646                     }
 647 
 648                     JSON_RESET_TYPE();
 649                 }
 650 
 651                 break;
 652 
 653 /* " */
 654             case -4:
 655                 switch (jp->stack[jp->top]) {
 656                 case MODE_KEY:
 657                     jp->state = CO;
 658                     smart_str_0(&buf);
 659                     SWAP_BUFFERS(buf, key);
 660                     JSON_RESET_TYPE();
 661                     break;
 662                 case MODE_ARRAY:
 663                 case MODE_OBJECT:
 664                     jp->state = OK;
 665                     break;
 666                                 case MODE_DONE:
 667                                         if (type == IS_STRING) {
 668                                                 smart_str_0(&buf);
 669                                                 ZVAL_STRINGL(z, buf.c, buf.len, 1);
 670                                                 jp->state = OK;
 671                                                 break;
 672                                         }
 673                                         /* fall through if not IS_STRING */
 674                 default:
 675                     FREE_BUFFERS();
 676                     jp->error_code = PHP_JSON_ERROR_SYNTAX;
 677                     return false;
 678                 }
 679                 break;
 680 /* , */
 681             case -3:
 682             {
 683                 zval *mval;
 684 
 685                 if (type != -1 &&
 686                     (jp->stack[jp->top] == MODE_OBJECT ||
 687                      jp->stack[jp->top] == MODE_ARRAY))
 688                 {
 689                     smart_str_0(&buf);
 690                     json_create_zval(&mval, &buf, type, options);
 691                 }
 692 
 693                 switch (jp->stack[jp->top]) {
 694                     case MODE_OBJECT:
 695                         if (pop(jp, MODE_OBJECT) && push(jp, MODE_KEY)) {
 696                             if (type != -1) {
 697                                 if (!assoc) {
 698                                     add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
 699                                     Z_DELREF_P(mval);
 700                                 } else {
 701                                     add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
 702                                 }
 703                                 key.len = 0;
 704                             }
 705                             jp->state = KE;
 706                         }
 707                         break;
 708                     case MODE_ARRAY:
 709                         if (type != -1) {
 710                             add_next_index_zval(jp->the_zstack[jp->top], mval);
 711                         }
 712                         jp->state = VA;
 713                         break;
 714                     default:
 715                         FREE_BUFFERS();
 716                         jp->error_code = PHP_JSON_ERROR_SYNTAX;
 717                         return false;
 718                 }
 719                 buf.len = 0;
 720                 JSON_RESET_TYPE();
 721             }
 722             break;
 723 /* : */
 724             case -2:
 725                 if (pop(jp, MODE_KEY) && push(jp, MODE_OBJECT)) {
 726                     jp->state = VA;
 727                     break;
 728                 }
 729 /*
 730     syntax error
 731 */
 732             default:
 733                 {
 734                                         jp->error_code = PHP_JSON_ERROR_SYNTAX;
 735                     FREE_BUFFERS();
 736                     return false;
 737                 }
 738             }
 739         }
 740     }
 741 
 742     FREE_BUFFERS();
 743         if (jp->state == OK && pop(jp, MODE_DONE)) {
 744                 return true;
 745         }
 746 
 747         jp->error_code = PHP_JSON_ERROR_SYNTAX;
 748         return false;
 749 }
 750 
 751 
 752 /*
 753  * Local variables:
 754  * tab-width: 4
 755  * c-basic-offset: 4
 756  * End:
 757  * vim600: noet sw=4 ts=4
 758  * vim<600: noet sw=4 ts=4
 759  */

/* [<][>][^][v][top][bottom][index][help] */