Annotation of embedaddon/php/ext/json/JSON_parser.c, revision 1.1.1.2

1.1       misho       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: 
1.1.1.2 ! misho     294: static void json_create_zval(zval **z, smart_str *buf, int type, int options)
1.1       misho     295: {
                    296:     ALLOC_INIT_ZVAL(*z);
                    297: 
                    298:     if (type == IS_LONG)
                    299:     {
1.1.1.2 ! misho     300:                zend_bool bigint = 0;
        !           301: 
1.1       misho     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] == '-'))) {
1.1.1.2 ! misho     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++;
1.1       misho     324:                                }
1.1.1.2 ! misho     325:                                goto use_string;
1.1       misho     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:     {
1.1.1.2 ! misho     340: use_string:
1.1       misho     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
1.1.1.2 ! misho     439: parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int options TSRMLS_DC)
1.1       misho     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;
1.1.1.2 ! misho     445:     int assoc = options & PHP_JSON_OBJECT_AS_ARRAY;
1.1       misho     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: 
1.1.1.2 ! misho     550:                     json_create_zval(&mval, &buf, type, options);
1.1       misho     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: 
1.1.1.2 ! misho     578:                     json_create_zval(&mval, &buf, type, options);
1.1       misho     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);
1.1.1.2 ! misho     690:                     json_create_zval(&mval, &buf, type, options);
1.1       misho     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:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>