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

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: 
        !           294: static void json_create_zval(zval **z, smart_str *buf, int type)
        !           295: {
        !           296:     ALLOC_INIT_ZVAL(*z);
        !           297: 
        !           298:     if (type == IS_LONG)
        !           299:     {
        !           300:                if (buf->c[0] == '-') {
        !           301:                        buf->len--;
        !           302:                }
        !           303: 
        !           304:                if (buf->len >= MAX_LENGTH_OF_LONG - 1) {
        !           305:                        if (buf->len == MAX_LENGTH_OF_LONG - 1) {
        !           306:                                int cmp = strcmp(buf->c + (buf->c[0] == '-'), long_min_digits);
        !           307: 
        !           308:                                if (!(cmp < 0 || (cmp == 0 && buf->c[0] == '-'))) {
        !           309:                                        goto use_double;
        !           310:                                }
        !           311:                        } else {
        !           312:                                goto use_double;
        !           313:                        }
        !           314:                }
        !           315: 
        !           316:                ZVAL_LONG(*z, strtol(buf->c, NULL, 10));
        !           317:     }
        !           318:     else if (type == IS_DOUBLE)
        !           319:     {
        !           320: use_double:
        !           321:         ZVAL_DOUBLE(*z, zend_strtod(buf->c, NULL));
        !           322:     }
        !           323:     else if (type == IS_STRING)
        !           324:     {
        !           325:         ZVAL_STRINGL(*z, buf->c, buf->len, 1);
        !           326:     }
        !           327:     else if (type == IS_BOOL)
        !           328:     {
        !           329:         ZVAL_BOOL(*z, (*(buf->c) == 't'));
        !           330:     }
        !           331:     else /* type == IS_NULL) || type unknown */
        !           332:     {
        !           333:         ZVAL_NULL(*z);
        !           334:     }
        !           335: }
        !           336: 
        !           337: 
        !           338: static void utf16_to_utf8(smart_str *buf, unsigned short utf16)
        !           339: {
        !           340:     if (utf16 < 0x80)
        !           341:     {
        !           342:         smart_str_appendc(buf, (unsigned char) utf16);
        !           343:     }
        !           344:     else if (utf16 < 0x800)
        !           345:     {
        !           346:         smart_str_appendc(buf, 0xc0 | (utf16 >> 6));
        !           347:         smart_str_appendc(buf, 0x80 | (utf16 & 0x3f));
        !           348:     }
        !           349:     else if ((utf16 & 0xfc00) == 0xdc00
        !           350:                 && buf->len >= 3
        !           351:                 && ((unsigned char) buf->c[buf->len - 3]) == 0xed
        !           352:                 && ((unsigned char) buf->c[buf->len - 2] & 0xf0) == 0xa0
        !           353:                 && ((unsigned char) buf->c[buf->len - 1] & 0xc0) == 0x80)
        !           354:     {
        !           355:         /* found surrogate pair */
        !           356:         unsigned long utf32;
        !           357: 
        !           358:         utf32 = (((buf->c[buf->len - 2] & 0xf) << 16)
        !           359:                     | ((buf->c[buf->len - 1] & 0x3f) << 10)
        !           360:                     | (utf16 & 0x3ff)) + 0x10000;
        !           361:         buf->len -= 3;
        !           362: 
        !           363:         smart_str_appendc(buf, (unsigned char) (0xf0 | (utf32 >> 18)));
        !           364:         smart_str_appendc(buf, 0x80 | ((utf32 >> 12) & 0x3f));
        !           365:         smart_str_appendc(buf, 0x80 | ((utf32 >> 6) & 0x3f));
        !           366:         smart_str_appendc(buf, 0x80 | (utf32 & 0x3f));
        !           367:     }
        !           368:     else
        !           369:     {
        !           370:         smart_str_appendc(buf, 0xe0 | (utf16 >> 12));
        !           371:         smart_str_appendc(buf, 0x80 | ((utf16 >> 6) & 0x3f));
        !           372:         smart_str_appendc(buf, 0x80 | (utf16 & 0x3f));
        !           373:     }
        !           374: }
        !           375: 
        !           376: static void attach_zval(JSON_parser jp, int up, int cur, smart_str *key, int assoc TSRMLS_DC)
        !           377: {
        !           378:     zval *root = jp->the_zstack[up];
        !           379:     zval *child =  jp->the_zstack[cur];
        !           380:     int up_mode = jp->stack[up];
        !           381: 
        !           382:     if (up_mode == MODE_ARRAY)
        !           383:     {
        !           384:         add_next_index_zval(root, child);
        !           385:     }
        !           386:     else if (up_mode == MODE_OBJECT)
        !           387:     {
        !           388:         if (!assoc)
        !           389:         {
        !           390:             add_property_zval_ex(root, (key->len ? key->c : "_empty_"), (key->len ? (key->len + 1) : sizeof("_empty_")), child TSRMLS_CC);
        !           391:             Z_DELREF_P(child);
        !           392:         }
        !           393:         else
        !           394:         {
        !           395:             add_assoc_zval_ex(root, (key->len ? key->c : ""), (key->len ? (key->len + 1) : sizeof("")), child);
        !           396:         }
        !           397:         key->len = 0;
        !           398:     }
        !           399: }
        !           400: 
        !           401: 
        !           402: #define FREE_BUFFERS() smart_str_free(&buf); smart_str_free(&key);
        !           403: #define SWAP_BUFFERS(from, to) do { \
        !           404:         char *t1 = from.c; \
        !           405:         int t2 = from.a; \
        !           406:         from.c = to.c; \
        !           407:         from.a = to.a; \
        !           408:         to.c = t1; \
        !           409:         to.a = t2; \
        !           410:         to.len = from.len; \
        !           411:         from.len = 0; \
        !           412:         } while(0);
        !           413: #define JSON_RESET_TYPE() type = -1;
        !           414: 
        !           415: /*
        !           416:     The JSON_parser takes a UTF-16 encoded string and determines if it is a
        !           417:     syntactically correct JSON text. Along the way, it creates a PHP variable.
        !           418: 
        !           419:     It is implemented as a Pushdown Automaton; that means it is a finite state
        !           420:     machine with a stack.
        !           421: */
        !           422: int
        !           423: parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int assoc TSRMLS_DC)
        !           424: {
        !           425:     int next_char;  /* the next character */
        !           426:     int next_class;  /* the next character class */
        !           427:     int next_state;  /* the next state */
        !           428:     int the_index;
        !           429: 
        !           430:     smart_str buf = {0};
        !           431:     smart_str key = {0};
        !           432: 
        !           433:     unsigned short utf16 = 0;
        !           434:     int type;
        !           435: 
        !           436:        JSON_RESET_TYPE();
        !           437: 
        !           438:     for (the_index = 0; the_index < length; the_index += 1) {
        !           439:         next_char = utf16_json[the_index];
        !           440:                if (next_char >= 128) {
        !           441:                        next_class = C_ETC;
        !           442:                } else {
        !           443:                        next_class = ascii_class[next_char];
        !           444:                        if (next_class <= __) {
        !           445:                                jp->error_code = PHP_JSON_ERROR_CTRL_CHAR;
        !           446:                                FREE_BUFFERS();
        !           447:                                return false;
        !           448:                        }
        !           449:                }
        !           450: /*
        !           451:     Get the next state from the transition table.
        !           452: */
        !           453:         next_state = state_transition_table[jp->state][next_class];
        !           454:         if (next_state >= 0) {
        !           455: /*
        !           456:     Change the state and iterate
        !           457: */
        !           458:                        if (type == IS_STRING) {
        !           459:                    if (next_state == ST && jp->state != U4) {
        !           460:                        if (jp->state != ES) {
        !           461:                            utf16_to_utf8(&buf, next_char);
        !           462:                        } else {
        !           463:                            switch (next_char) {
        !           464:                                case 'b':
        !           465:                                    smart_str_appendc(&buf, '\b');
        !           466:                                    break;
        !           467:                                case 't':
        !           468:                                    smart_str_appendc(&buf, '\t');
        !           469:                                    break;
        !           470:                                case 'n':
        !           471:                                    smart_str_appendc(&buf, '\n');
        !           472:                                    break;
        !           473:                                case 'f':
        !           474:                                    smart_str_appendc(&buf, '\f');
        !           475:                                    break;
        !           476:                                case 'r':
        !           477:                                    smart_str_appendc(&buf, '\r');
        !           478:                                    break;
        !           479:                                default:
        !           480:                                    utf16_to_utf8(&buf, next_char);
        !           481:                                    break;
        !           482:                            }
        !           483:                        }
        !           484:                    } else if (next_state == U2) {
        !           485:                        utf16 = dehexchar(next_char) << 12;
        !           486:                    } else if (next_state == U3) {
        !           487:                        utf16 += dehexchar(next_char) << 8;
        !           488:                    } else if (next_state == U4) {
        !           489:                        utf16 += dehexchar(next_char) << 4;
        !           490:                    } else if (next_state == ST && jp->state == U4) {
        !           491:                        utf16 += dehexchar(next_char);
        !           492:                        utf16_to_utf8(&buf, utf16);
        !           493:                    }
        !           494:                } else if (type < IS_LONG && (next_class == C_DIGIT || next_class == C_ZERO)) {
        !           495:                    type = IS_LONG;
        !           496:                    smart_str_appendc(&buf, next_char);
        !           497:                } else if (type == IS_LONG && next_state == E1) {
        !           498:                    type = IS_DOUBLE;
        !           499:                    smart_str_appendc(&buf, next_char);
        !           500:                } else if (type < IS_DOUBLE && next_class == C_POINT) {
        !           501:                    type = IS_DOUBLE;
        !           502:                    smart_str_appendc(&buf, next_char);
        !           503:                } else if (type < IS_STRING && next_class == C_QUOTE) {
        !           504:                    type = IS_STRING;
        !           505:                } else if (type < IS_BOOL && ((jp->state == T3 && next_state == OK) || (jp->state == F4 && next_state == OK))) {
        !           506:                    type = IS_BOOL;
        !           507:                } else if (type < IS_NULL && jp->state == N3 && next_state == OK) {
        !           508:                    type = IS_NULL;
        !           509:                } else if (type != IS_STRING && next_class > C_WHITE) {
        !           510:                    utf16_to_utf8(&buf, next_char);
        !           511:                }
        !           512:                jp->state = next_state;
        !           513:                } else {
        !           514: /*
        !           515:     Perform one of the predefined actions.
        !           516: */
        !           517:             switch (next_state) {
        !           518: /* empty } */
        !           519:             case -9:
        !           520:                 if (!pop(jp, MODE_KEY)) {
        !           521:                     FREE_BUFFERS();
        !           522:                     return false;
        !           523:                 }
        !           524:                 jp->state = OK;
        !           525:                 break;
        !           526: /* } */
        !           527:             case -8:
        !           528:                 if (type != -1 && jp->stack[jp->top] == MODE_OBJECT)
        !           529:                 {
        !           530:                     zval *mval;
        !           531:                     smart_str_0(&buf);
        !           532: 
        !           533:                     json_create_zval(&mval, &buf, type);
        !           534: 
        !           535:                     if (!assoc) {
        !           536:                         add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
        !           537:                         Z_DELREF_P(mval);
        !           538:                     } else {
        !           539:                         add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
        !           540:                     }
        !           541:                     key.len = 0;
        !           542:                     buf.len = 0;
        !           543:                     JSON_RESET_TYPE();
        !           544:                 }
        !           545: 
        !           546: 
        !           547:                 if (!pop(jp, MODE_OBJECT)) {
        !           548:                     FREE_BUFFERS();
        !           549:                     return false;
        !           550:                 }
        !           551:                 jp->state = OK;
        !           552:                 break;
        !           553: /* ] */
        !           554:             case -7:
        !           555:             {
        !           556:                 if (type != -1 && jp->stack[jp->top] == MODE_ARRAY)
        !           557:                 {
        !           558:                     zval *mval;
        !           559:                     smart_str_0(&buf);
        !           560: 
        !           561:                     json_create_zval(&mval, &buf, type);
        !           562:                     add_next_index_zval(jp->the_zstack[jp->top], mval);
        !           563:                     buf.len = 0;
        !           564:                     JSON_RESET_TYPE();
        !           565:                 }
        !           566: 
        !           567:                 if (!pop(jp, MODE_ARRAY)) {
        !           568:                     FREE_BUFFERS();
        !           569:                     return false;
        !           570:                 }
        !           571:                 jp->state = OK;
        !           572:             }
        !           573:                        break;
        !           574: /* { */
        !           575:             case -6:
        !           576:                 if (!push(jp, MODE_KEY)) {
        !           577:                     FREE_BUFFERS();
        !           578:                     return false;
        !           579:                 }
        !           580: 
        !           581:                 jp->state = OB;
        !           582:                 if (jp->top > 0) {
        !           583:                     zval *obj;
        !           584: 
        !           585:                     if (jp->top == 1) {
        !           586:                         obj = z;
        !           587:                        } else {
        !           588:                         ALLOC_INIT_ZVAL(obj);
        !           589:                     }
        !           590: 
        !           591:                     if (!assoc) {
        !           592:                         object_init(obj);
        !           593:                     } else {
        !           594:                         array_init(obj);
        !           595:                     }
        !           596: 
        !           597:                     jp->the_zstack[jp->top] = obj;
        !           598: 
        !           599:                     if (jp->top > 1) {
        !           600:                         attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
        !           601:                     }
        !           602: 
        !           603:                     JSON_RESET_TYPE();
        !           604:                 }
        !           605: 
        !           606:                 break;
        !           607: /* [ */
        !           608:             case -5:
        !           609:                 if (!push(jp, MODE_ARRAY)) {
        !           610:                     FREE_BUFFERS();
        !           611:                     return false;
        !           612:                 }
        !           613:                 jp->state = AR;
        !           614: 
        !           615:                 if (jp->top > 0) {
        !           616:                     zval *arr;
        !           617: 
        !           618:                     if (jp->top == 1) {
        !           619:                         arr = z;
        !           620:                     } else {
        !           621:                         ALLOC_INIT_ZVAL(arr);
        !           622:                     }
        !           623: 
        !           624:                     array_init(arr);
        !           625:                     jp->the_zstack[jp->top] = arr;
        !           626: 
        !           627:                     if (jp->top > 1) {
        !           628:                         attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
        !           629:                     }
        !           630: 
        !           631:                     JSON_RESET_TYPE();
        !           632:                 }
        !           633: 
        !           634:                 break;
        !           635: 
        !           636: /* " */
        !           637:             case -4:
        !           638:                 switch (jp->stack[jp->top]) {
        !           639:                 case MODE_KEY:
        !           640:                     jp->state = CO;
        !           641:                     smart_str_0(&buf);
        !           642:                     SWAP_BUFFERS(buf, key);
        !           643:                     JSON_RESET_TYPE();
        !           644:                     break;
        !           645:                 case MODE_ARRAY:
        !           646:                 case MODE_OBJECT:
        !           647:                     jp->state = OK;
        !           648:                     break;
        !           649:                                case MODE_DONE:
        !           650:                                        if (type == IS_STRING) {
        !           651:                                                smart_str_0(&buf);
        !           652:                                                ZVAL_STRINGL(z, buf.c, buf.len, 1);
        !           653:                                                jp->state = OK;
        !           654:                                                break;
        !           655:                                        }
        !           656:                                        /* fall through if not IS_STRING */
        !           657:                 default:
        !           658:                     FREE_BUFFERS();
        !           659:                     jp->error_code = PHP_JSON_ERROR_SYNTAX;
        !           660:                     return false;
        !           661:                 }
        !           662:                 break;
        !           663: /* , */
        !           664:             case -3:
        !           665:             {
        !           666:                 zval *mval;
        !           667: 
        !           668:                 if (type != -1 &&
        !           669:                     (jp->stack[jp->top] == MODE_OBJECT ||
        !           670:                      jp->stack[jp->top] == MODE_ARRAY))
        !           671:                 {
        !           672:                     smart_str_0(&buf);
        !           673:                     json_create_zval(&mval, &buf, type);
        !           674:                 }
        !           675: 
        !           676:                 switch (jp->stack[jp->top]) {
        !           677:                     case MODE_OBJECT:
        !           678:                         if (pop(jp, MODE_OBJECT) && push(jp, MODE_KEY)) {
        !           679:                             if (type != -1) {
        !           680:                                 if (!assoc) {
        !           681:                                     add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
        !           682:                                     Z_DELREF_P(mval);
        !           683:                                 } else {
        !           684:                                     add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
        !           685:                                 }
        !           686:                                 key.len = 0;
        !           687:                             }
        !           688:                             jp->state = KE;
        !           689:                         }
        !           690:                         break;
        !           691:                     case MODE_ARRAY:
        !           692:                         if (type != -1) {
        !           693:                             add_next_index_zval(jp->the_zstack[jp->top], mval);
        !           694:                         }
        !           695:                         jp->state = VA;
        !           696:                         break;
        !           697:                     default:
        !           698:                         FREE_BUFFERS();
        !           699:                         jp->error_code = PHP_JSON_ERROR_SYNTAX;
        !           700:                         return false;
        !           701:                 }
        !           702:                 buf.len = 0;
        !           703:                 JSON_RESET_TYPE();
        !           704:             }
        !           705:             break;
        !           706: /* : */
        !           707:             case -2:
        !           708:                 if (pop(jp, MODE_KEY) && push(jp, MODE_OBJECT)) {
        !           709:                     jp->state = VA;
        !           710:                     break;
        !           711:                 }
        !           712: /*
        !           713:     syntax error
        !           714: */
        !           715:             default:
        !           716:                 {
        !           717:                                        jp->error_code = PHP_JSON_ERROR_SYNTAX;
        !           718:                     FREE_BUFFERS();
        !           719:                     return false;
        !           720:                 }
        !           721:             }
        !           722:         }
        !           723:     }
        !           724: 
        !           725:     FREE_BUFFERS();
        !           726:        if (jp->state == OK && pop(jp, MODE_DONE)) {
        !           727:                return true;
        !           728:        }
        !           729: 
        !           730:        jp->error_code = PHP_JSON_ERROR_SYNTAX;
        !           731:        return false;
        !           732: }
        !           733: 
        !           734: 
        !           735: /*
        !           736:  * Local variables:
        !           737:  * tab-width: 4
        !           738:  * c-basic-offset: 4
        !           739:  * End:
        !           740:  * vim600: noet sw=4 ts=4
        !           741:  * vim<600: noet sw=4 ts=4
        !           742:  */

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