File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / json / JSON_parser.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:34:40 2012 UTC (12 years, 2 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_3elwix, v5_4_29p0, v5_4_29, v5_4_20p0, v5_4_20, v5_4_17p0, v5_4_17, HEAD
php 5.4.3+patches

    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:  */

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