Back to index

php5  5.3.10
JSON_parser.c
Go to the documentation of this file.
00001 /* JSON_parser.c */
00002 
00003 /* 2005-12-30 */
00004 
00005 /*
00006 Copyright (c) 2005 JSON.org
00007 
00008 Permission is hereby granted, free of charge, to any person obtaining a copy
00009 of this software and associated documentation files (the "Software"), to deal
00010 in the Software without restriction, including without limitation the rights
00011 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00012 copies of the Software, and to permit persons to whom the Software is
00013 furnished to do so, subject to the following conditions:
00014 
00015 The above copyright notice and this permission notice shall be included in all
00016 copies or substantial portions of the Software.
00017 
00018 The Software shall be used for Good, not Evil.
00019 
00020 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00021 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00022 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00023 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00024 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00025 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00026 SOFTWARE.
00027 */
00028 
00029 #include <stdio.h>
00030 #include "JSON_parser.h"
00031 
00032 /* Windows defines IN for documentation */
00033 #undef IN
00034 
00035 #define true  1
00036 #define false 0
00037 #define __   -1     /* the universal error code */
00038 
00039 /*
00040     Characters are mapped into these 31 character classes. This allows for
00041     a significant reduction in the size of the state transition table.
00042 */
00043 
00044 enum classes {
00045     C_SPACE,  /* space */
00046     C_WHITE,  /* other whitespace */
00047     C_LCURB,  /* {  */
00048     C_RCURB,  /* } */
00049     C_LSQRB,  /* [ */
00050     C_RSQRB,  /* ] */
00051     C_COLON,  /* : */
00052     C_COMMA,  /* , */
00053     C_QUOTE,  /* " */
00054     C_BACKS,  /* \ */
00055     C_SLASH,  /* / */
00056     C_PLUS,   /* + */
00057     C_MINUS,  /* - */
00058     C_POINT,  /* . */
00059     C_ZERO ,  /* 0 */
00060     C_DIGIT,  /* 123456789 */
00061     C_LOW_A,  /* a */
00062     C_LOW_B,  /* b */
00063     C_LOW_C,  /* c */
00064     C_LOW_D,  /* d */
00065     C_LOW_E,  /* e */
00066     C_LOW_F,  /* f */
00067     C_LOW_L,  /* l */
00068     C_LOW_N,  /* n */
00069     C_LOW_R,  /* r */
00070     C_LOW_S,  /* s */
00071     C_LOW_T,  /* t */
00072     C_LOW_U,  /* u */
00073     C_ABCDF,  /* ABCDF */
00074     C_E,      /* E */
00075     C_ETC,    /* everything else */
00076     NR_CLASSES
00077 };
00078 
00079 static const int ascii_class[128] = {
00080 /*
00081     This array maps the 128 ASCII characters into character classes.
00082     The remaining Unicode characters should be mapped to C_ETC.
00083     Non-whitespace control characters are errors.
00084 */
00085     __,      __,      __,      __,      __,      __,      __,      __,
00086     __,      C_WHITE, C_WHITE, __,      __,      C_WHITE, __,      __,
00087     __,      __,      __,      __,      __,      __,      __,      __,
00088     __,      __,      __,      __,      __,      __,      __,      __,
00089 
00090     C_SPACE, C_ETC,   C_QUOTE, C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
00091     C_ETC,   C_ETC,   C_ETC,   C_PLUS,  C_COMMA, C_MINUS, C_POINT, C_SLASH,
00092     C_ZERO,  C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT,
00093     C_DIGIT, C_DIGIT, C_COLON, C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
00094 
00095     C_ETC,   C_ABCDF, C_ABCDF, C_ABCDF, C_ABCDF, C_E,     C_ABCDF, C_ETC,
00096     C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
00097     C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
00098     C_ETC,   C_ETC,   C_ETC,   C_LSQRB, C_BACKS, C_RSQRB, C_ETC,   C_ETC,
00099 
00100     C_ETC,   C_LOW_A, C_LOW_B, C_LOW_C, C_LOW_D, C_LOW_E, C_LOW_F, C_ETC,
00101     C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_LOW_L, C_ETC,   C_LOW_N, C_ETC,
00102     C_ETC,   C_ETC,   C_LOW_R, C_LOW_S, C_LOW_T, C_LOW_U, C_ETC,   C_ETC,
00103     C_ETC,   C_ETC,   C_ETC,   C_LCURB, C_ETC,   C_RCURB, C_ETC,   C_ETC
00104 };
00105 
00106 
00107 /*
00108     The state codes.
00109 */
00110 enum states {
00111     GO,  /* start    */
00112     OK,  /* ok       */
00113     OB,  /* object   */
00114     KE,  /* key      */
00115     CO,  /* colon    */
00116     VA,  /* value    */
00117     AR,  /* array    */
00118     ST,  /* string   */
00119     ES,  /* escape   */
00120     U1,  /* u1       */
00121     U2,  /* u2       */
00122     U3,  /* u3       */
00123     U4,  /* u4       */
00124     MI,  /* minus    */
00125     ZE,  /* zero     */
00126     IN,  /* integer  */
00127     FR,  /* fraction */
00128     E1,  /* e        */
00129     E2,  /* ex       */
00130     E3,  /* exp      */
00131     T1,  /* tr       */
00132     T2,  /* tru      */
00133     T3,  /* true     */
00134     F1,  /* fa       */
00135     F2,  /* fal      */
00136     F3,  /* fals     */
00137     F4,  /* false    */
00138     N1,  /* nu       */
00139     N2,  /* nul      */
00140     N3,  /* null     */
00141     NR_STATES
00142 };
00143 
00144 
00145 static const int state_transition_table[NR_STATES][NR_CLASSES] = {
00146 /*
00147     The state transition table takes the current state and the current symbol,
00148     and returns either a new state or an action. An action is represented as a
00149     negative number. A JSON text is accepted if at the end of the text the
00150     state is OK and if the mode is MODE_DONE.
00151 
00152                  white                                      1-9                                   ABCDF  etc
00153              space |  {  }  [  ]  :  ,  "  \  /  +  -  .  0  |  a  b  c  d  e  f  l  n  r  s  t  u  |  E  |*/
00154 /*start  GO*/ {GO,GO,-6,__,-5,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
00155 /*ok     OK*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
00156 /*object OB*/ {OB,OB,__,-9,__,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
00157 /*key    KE*/ {KE,KE,__,__,__,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
00158 /*colon  CO*/ {CO,CO,__,__,__,__,-2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
00159 /*value  VA*/ {VA,VA,-6,__,-5,__,__,__,ST,__,__,__,MI,__,ZE,IN,__,__,__,__,__,F1,__,N1,__,__,T1,__,__,__,__},
00160 /*array  AR*/ {AR,AR,-6,__,-5,-7,__,__,ST,__,__,__,MI,__,ZE,IN,__,__,__,__,__,F1,__,N1,__,__,T1,__,__,__,__},
00161 /*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},
00162 /*escape ES*/ {__,__,__,__,__,__,__,__,ST,ST,ST,__,__,__,__,__,__,ST,__,__,__,ST,__,ST,ST,__,ST,U1,__,__,__},
00163 /*u1     U1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U2,U2,U2,U2,U2,U2,U2,U2,__,__,__,__,__,__,U2,U2,__},
00164 /*u2     U2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U3,U3,U3,U3,U3,U3,U3,U3,__,__,__,__,__,__,U3,U3,__},
00165 /*u3     U3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U4,U4,U4,U4,U4,U4,U4,U4,__,__,__,__,__,__,U4,U4,__},
00166 /*u4     U4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,ST,ST,ST,ST,ST,ST,ST,ST,__,__,__,__,__,__,ST,ST,__},
00167 /*minus  MI*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,ZE,IN,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
00168 /*zero   ZE*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,FR,__,__,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
00169 /*int    IN*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,FR,IN,IN,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
00170 /*frac   FR*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,FR,FR,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
00171 /*e      E1*/ {__,__,__,__,__,__,__,__,__,__,__,E2,E2,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
00172 /*ex     E2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
00173 /*exp    E3*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
00174 /*tr     T1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T2,__,__,__,__,__,__},
00175 /*tru    T2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T3,__,__,__},
00176 /*true   T3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__},
00177 /*fa     F1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F2,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
00178 /*fal    F2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F3,__,__,__,__,__,__,__,__},
00179 /*fals   F3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F4,__,__,__,__,__},
00180 /*false  F4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__},
00181 /*nu     N1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N2,__,__,__},
00182 /*nul    N2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N3,__,__,__,__,__,__,__,__},
00183 /*null   N3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__},
00184 };
00185 
00186 
00187 /*
00188     These modes can be pushed on the stack.
00189 */
00190 enum modes {
00191     MODE_ARRAY, 
00192     MODE_DONE,  
00193     MODE_KEY,   
00194     MODE_OBJECT,
00195 };
00196 
00197 
00198 /*
00199     Push a mode onto the stack. Return false if there is overflow.
00200 */
00201 static int
00202 push(JSON_parser jp, int mode)
00203 {
00204     jp->top += 1;
00205     if (jp->top >= jp->depth) {
00206               jp->error_code = PHP_JSON_ERROR_DEPTH;
00207         return false;
00208     }
00209     jp->stack[jp->top] = mode;
00210     return true;
00211 }
00212 
00213 
00214 /*
00215     Pop the stack, assuring that the current mode matches the expectation.
00216     Return false if there is underflow or if the modes mismatch.
00217 */
00218 static int
00219 pop(JSON_parser jp, int mode)
00220 {
00221     if (jp->top < 0 || jp->stack[jp->top] != mode) {
00222               jp->error_code = PHP_JSON_ERROR_STATE_MISMATCH;
00223         return false;
00224     }
00225     jp->top -= 1;
00226     return true;
00227 }
00228 
00229 /*
00230     new_JSON_checker starts the checking process by constructing a JSON_checker
00231     object. It takes a depth parameter that restricts the level of maximum
00232     nesting.
00233 
00234     To continue the process, call JSON_checker_char for each character in the
00235     JSON text, and then call JSON_checker_done to obtain the final result.
00236     These functions are fully reentrant.
00237 
00238     The JSON_checker object will be deleted by JSON_checker_done.
00239     JSON_checker_char will delete the JSON_checker object if it sees an error.
00240 */
00241 JSON_parser
00242 new_JSON_parser(int depth)
00243 {
00244     JSON_parser jp = (JSON_parser)emalloc(sizeof(struct JSON_parser_struct));
00245     jp->state = GO;
00246     jp->depth = depth;
00247     jp->top = -1;
00248        jp->error_code = PHP_JSON_ERROR_NONE;
00249     jp->stack = (int*)ecalloc(depth, sizeof(int));
00250     if (depth > JSON_PARSER_DEFAULT_DEPTH) {
00251         jp->the_zstack = (zval **)safe_emalloc(depth, sizeof(zval), 0);
00252     } else {
00253         jp->the_zstack = &jp->the_static_zstack[0];
00254     }
00255     push(jp, MODE_DONE);
00256     return jp;
00257 }
00258 
00259 /*
00260     Delete the JSON_parser object.
00261 */
00262 int
00263 free_JSON_parser(JSON_parser jp)
00264 {
00265     efree((void*)jp->stack);
00266     if (jp->the_zstack != &jp->the_static_zstack[0]) {
00267         efree(jp->the_zstack);
00268     }
00269     efree((void*)jp);
00270     return false;
00271 }
00272 
00273 static int dehexchar(char c)
00274 {
00275     if (c >= '0' && c <= '9')
00276     {
00277         return c - '0';
00278     }
00279     else if (c >= 'A' && c <= 'F')
00280     {
00281         return c - ('A' - 10);
00282     }
00283     else if (c >= 'a' && c <= 'f')
00284     {
00285         return c - ('a' - 10);
00286     }
00287     else
00288     {
00289         return -1;
00290     }
00291 }
00292 
00293 
00294 static void json_create_zval(zval **z, smart_str *buf, int type)
00295 {
00296     ALLOC_INIT_ZVAL(*z);
00297 
00298     if (type == IS_LONG)
00299     {
00300               if (buf->c[0] == '-') {
00301                      buf->len--;
00302               }
00303 
00304               if (buf->len >= MAX_LENGTH_OF_LONG - 1) {
00305                      if (buf->len == MAX_LENGTH_OF_LONG - 1) {
00306                             int cmp = strcmp(buf->c + (buf->c[0] == '-'), long_min_digits);
00307 
00308                             if (!(cmp < 0 || (cmp == 0 && buf->c[0] == '-'))) {
00309                                    goto use_double;
00310                             }
00311                      } else {
00312                             goto use_double;
00313                      }
00314               }
00315 
00316               ZVAL_LONG(*z, strtol(buf->c, NULL, 10));
00317     }
00318     else if (type == IS_DOUBLE)
00319     {
00320 use_double:
00321         ZVAL_DOUBLE(*z, zend_strtod(buf->c, NULL));
00322     }
00323     else if (type == IS_STRING)
00324     {
00325         ZVAL_STRINGL(*z, buf->c, buf->len, 1);
00326     }
00327     else if (type == IS_BOOL)
00328     {
00329         ZVAL_BOOL(*z, (*(buf->c) == 't'));
00330     }
00331     else /* type == IS_NULL) || type unknown */
00332     {
00333         ZVAL_NULL(*z);
00334     }
00335 }
00336 
00337 
00338 static void utf16_to_utf8(smart_str *buf, unsigned short utf16)
00339 {
00340     if (utf16 < 0x80)
00341     {
00342         smart_str_appendc(buf, (unsigned char) utf16);
00343     }
00344     else if (utf16 < 0x800)
00345     {
00346         smart_str_appendc(buf, 0xc0 | (utf16 >> 6));
00347         smart_str_appendc(buf, 0x80 | (utf16 & 0x3f));
00348     }
00349     else if ((utf16 & 0xfc00) == 0xdc00
00350                 && buf->len >= 3
00351                 && ((unsigned char) buf->c[buf->len - 3]) == 0xed
00352                 && ((unsigned char) buf->c[buf->len - 2] & 0xf0) == 0xa0
00353                 && ((unsigned char) buf->c[buf->len - 1] & 0xc0) == 0x80)
00354     {
00355         /* found surrogate pair */
00356         unsigned long utf32;
00357 
00358         utf32 = (((buf->c[buf->len - 2] & 0xf) << 16)
00359                     | ((buf->c[buf->len - 1] & 0x3f) << 10)
00360                     | (utf16 & 0x3ff)) + 0x10000;
00361         buf->len -= 3;
00362 
00363         smart_str_appendc(buf, (unsigned char) (0xf0 | (utf32 >> 18)));
00364         smart_str_appendc(buf, 0x80 | ((utf32 >> 12) & 0x3f));
00365         smart_str_appendc(buf, 0x80 | ((utf32 >> 6) & 0x3f));
00366         smart_str_appendc(buf, 0x80 | (utf32 & 0x3f));
00367     }
00368     else
00369     {
00370         smart_str_appendc(buf, 0xe0 | (utf16 >> 12));
00371         smart_str_appendc(buf, 0x80 | ((utf16 >> 6) & 0x3f));
00372         smart_str_appendc(buf, 0x80 | (utf16 & 0x3f));
00373     }
00374 }
00375 
00376 static void attach_zval(JSON_parser jp, int up, int cur, smart_str *key, int assoc TSRMLS_DC)
00377 {
00378     zval *root = jp->the_zstack[up];
00379     zval *child =  jp->the_zstack[cur];
00380     int up_mode = jp->stack[up];
00381 
00382     if (up_mode == MODE_ARRAY)
00383     {
00384         add_next_index_zval(root, child);
00385     }
00386     else if (up_mode == MODE_OBJECT)
00387     {
00388         if (!assoc)
00389         {
00390             add_property_zval_ex(root, (key->len ? key->c : "_empty_"), (key->len ? (key->len + 1) : sizeof("_empty_")), child TSRMLS_CC);
00391             Z_DELREF_P(child);
00392         }
00393         else
00394         {
00395             add_assoc_zval_ex(root, (key->len ? key->c : ""), (key->len ? (key->len + 1) : sizeof("")), child);
00396         }
00397         key->len = 0;
00398     }
00399 }
00400 
00401 
00402 #define FREE_BUFFERS() smart_str_free(&buf); smart_str_free(&key);
00403 #define SWAP_BUFFERS(from, to) do { \
00404         char *t1 = from.c; \
00405         int t2 = from.a; \
00406         from.c = to.c; \
00407         from.a = to.a; \
00408         to.c = t1; \
00409         to.a = t2; \
00410         to.len = from.len; \
00411         from.len = 0; \
00412         } while(0);
00413 #define JSON_RESET_TYPE() type = -1;
00414 
00415 /*
00416     The JSON_parser takes a UTF-16 encoded string and determines if it is a
00417     syntactically correct JSON text. Along the way, it creates a PHP variable.
00418 
00419     It is implemented as a Pushdown Automaton; that means it is a finite state
00420     machine with a stack.
00421 */
00422 int
00423 parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int assoc TSRMLS_DC)
00424 {
00425     int next_char;  /* the next character */
00426     int next_class;  /* the next character class */
00427     int next_state;  /* the next state */
00428     int the_index;
00429 
00430     smart_str buf = {0};
00431     smart_str key = {0};
00432 
00433     unsigned short utf16 = 0;
00434     int type;
00435 
00436        JSON_RESET_TYPE();
00437 
00438     for (the_index = 0; the_index < length; the_index += 1) {
00439         next_char = utf16_json[the_index];
00440               if (next_char >= 128) {
00441                      next_class = C_ETC;
00442               } else {
00443                      next_class = ascii_class[next_char];
00444                      if (next_class <= __) {
00445                             jp->error_code = PHP_JSON_ERROR_CTRL_CHAR;
00446                             FREE_BUFFERS();
00447                             return false;
00448                      }
00449               }
00450 /*
00451     Get the next state from the transition table.
00452 */
00453         next_state = state_transition_table[jp->state][next_class];
00454         if (next_state >= 0) {
00455 /*
00456     Change the state and iterate
00457 */
00458                      if (type == IS_STRING) {
00459                    if (next_state == ST && jp->state != U4) {
00460                        if (jp->state != ES) {
00461                            utf16_to_utf8(&buf, next_char);
00462                        } else {
00463                            switch (next_char) {
00464                                case 'b':
00465                                    smart_str_appendc(&buf, '\b');
00466                                    break;
00467                                case 't':
00468                                    smart_str_appendc(&buf, '\t');
00469                                    break;
00470                                case 'n':
00471                                    smart_str_appendc(&buf, '\n');
00472                                    break;
00473                                case 'f':
00474                                    smart_str_appendc(&buf, '\f');
00475                                    break;
00476                                case 'r':
00477                                    smart_str_appendc(&buf, '\r');
00478                                    break;
00479                                default:
00480                                    utf16_to_utf8(&buf, next_char);
00481                                    break;
00482                            }
00483                        }
00484                    } else if (next_state == U2) {
00485                        utf16 = dehexchar(next_char) << 12;
00486                    } else if (next_state == U3) {
00487                        utf16 += dehexchar(next_char) << 8;
00488                    } else if (next_state == U4) {
00489                        utf16 += dehexchar(next_char) << 4;
00490                    } else if (next_state == ST && jp->state == U4) {
00491                        utf16 += dehexchar(next_char);
00492                        utf16_to_utf8(&buf, utf16);
00493                    }
00494                } else if (type < IS_LONG && (next_class == C_DIGIT || next_class == C_ZERO)) {
00495                    type = IS_LONG;
00496                    smart_str_appendc(&buf, next_char);
00497                } else if (type == IS_LONG && next_state == E1) {
00498                    type = IS_DOUBLE;
00499                    smart_str_appendc(&buf, next_char);
00500                } else if (type < IS_DOUBLE && next_class == C_POINT) {
00501                    type = IS_DOUBLE;
00502                    smart_str_appendc(&buf, next_char);
00503                } else if (type < IS_STRING && next_class == C_QUOTE) {
00504                    type = IS_STRING;
00505                } else if (type < IS_BOOL && ((jp->state == T3 && next_state == OK) || (jp->state == F4 && next_state == OK))) {
00506                    type = IS_BOOL;
00507                } else if (type < IS_NULL && jp->state == N3 && next_state == OK) {
00508                    type = IS_NULL;
00509                } else if (type != IS_STRING && next_class > C_WHITE) {
00510                    utf16_to_utf8(&buf, next_char);
00511                }
00512               jp->state = next_state;
00513               } else {
00514 /*
00515     Perform one of the predefined actions.
00516 */
00517             switch (next_state) {
00518 /* empty } */
00519             case -9:
00520                 if (!pop(jp, MODE_KEY)) {
00521                     FREE_BUFFERS();
00522                     return false;
00523                 }
00524                 jp->state = OK;
00525                 break;
00526 /* } */
00527             case -8:
00528                 if (type != -1 && jp->stack[jp->top] == MODE_OBJECT)
00529                 {
00530                     zval *mval;
00531                     smart_str_0(&buf);
00532 
00533                     json_create_zval(&mval, &buf, type);
00534 
00535                     if (!assoc) {
00536                         add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
00537                         Z_DELREF_P(mval);
00538                     } else {
00539                         add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
00540                     }
00541                     key.len = 0;
00542                     buf.len = 0;
00543                     JSON_RESET_TYPE();
00544                 }
00545 
00546 
00547                 if (!pop(jp, MODE_OBJECT)) {
00548                     FREE_BUFFERS();
00549                     return false;
00550                 }
00551                 jp->state = OK;
00552                 break;
00553 /* ] */
00554             case -7:
00555             {
00556                 if (type != -1 && jp->stack[jp->top] == MODE_ARRAY)
00557                 {
00558                     zval *mval;
00559                     smart_str_0(&buf);
00560 
00561                     json_create_zval(&mval, &buf, type);
00562                     add_next_index_zval(jp->the_zstack[jp->top], mval);
00563                     buf.len = 0;
00564                     JSON_RESET_TYPE();
00565                 }
00566 
00567                 if (!pop(jp, MODE_ARRAY)) {
00568                     FREE_BUFFERS();
00569                     return false;
00570                 }
00571                 jp->state = OK;
00572             }
00573                      break;
00574 /* { */
00575             case -6:
00576                 if (!push(jp, MODE_KEY)) {
00577                     FREE_BUFFERS();
00578                     return false;
00579                 }
00580 
00581                 jp->state = OB;
00582                 if (jp->top > 0) {
00583                     zval *obj;
00584 
00585                     if (jp->top == 1) {
00586                         obj = z;
00587                      } else {
00588                         ALLOC_INIT_ZVAL(obj);
00589                     }
00590 
00591                     if (!assoc) {
00592                         object_init(obj);
00593                     } else {
00594                         array_init(obj);
00595                     }
00596 
00597                     jp->the_zstack[jp->top] = obj;
00598 
00599                     if (jp->top > 1) {
00600                         attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
00601                     }
00602 
00603                     JSON_RESET_TYPE();
00604                 }
00605 
00606                 break;
00607 /* [ */
00608             case -5:
00609                 if (!push(jp, MODE_ARRAY)) {
00610                     FREE_BUFFERS();
00611                     return false;
00612                 }
00613                 jp->state = AR;
00614 
00615                 if (jp->top > 0) {
00616                     zval *arr;
00617 
00618                     if (jp->top == 1) {
00619                         arr = z;
00620                     } else {
00621                         ALLOC_INIT_ZVAL(arr);
00622                     }
00623 
00624                     array_init(arr);
00625                     jp->the_zstack[jp->top] = arr;
00626 
00627                     if (jp->top > 1) {
00628                         attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
00629                     }
00630 
00631                     JSON_RESET_TYPE();
00632                 }
00633 
00634                 break;
00635 
00636 /* " */
00637             case -4:
00638                 switch (jp->stack[jp->top]) {
00639                 case MODE_KEY:
00640                     jp->state = CO;
00641                     smart_str_0(&buf);
00642                     SWAP_BUFFERS(buf, key);
00643                     JSON_RESET_TYPE();
00644                     break;
00645                 case MODE_ARRAY:
00646                 case MODE_OBJECT:
00647                     jp->state = OK;
00648                     break;
00649                             case MODE_DONE:
00650                                    if (type == IS_STRING) {
00651                                           smart_str_0(&buf);
00652                                           ZVAL_STRINGL(z, buf.c, buf.len, 1);
00653                                           jp->state = OK;
00654                                           break;
00655                                    }
00656                                    /* fall through if not IS_STRING */
00657                 default:
00658                     FREE_BUFFERS();
00659                     jp->error_code = PHP_JSON_ERROR_SYNTAX;
00660                     return false;
00661                 }
00662                 break;
00663 /* , */
00664             case -3:
00665             {
00666                 zval *mval;
00667 
00668                 if (type != -1 &&
00669                     (jp->stack[jp->top] == MODE_OBJECT ||
00670                      jp->stack[jp->top] == MODE_ARRAY))
00671                 {
00672                     smart_str_0(&buf);
00673                     json_create_zval(&mval, &buf, type);
00674                 }
00675 
00676                 switch (jp->stack[jp->top]) {
00677                     case MODE_OBJECT:
00678                         if (pop(jp, MODE_OBJECT) && push(jp, MODE_KEY)) {
00679                             if (type != -1) {
00680                                 if (!assoc) {
00681                                     add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
00682                                     Z_DELREF_P(mval);
00683                                 } else {
00684                                     add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
00685                                 }
00686                                 key.len = 0;
00687                             }
00688                             jp->state = KE;
00689                         }
00690                         break;
00691                     case MODE_ARRAY:
00692                         if (type != -1) {
00693                             add_next_index_zval(jp->the_zstack[jp->top], mval);
00694                         }
00695                         jp->state = VA;
00696                         break;
00697                     default:
00698                         FREE_BUFFERS();
00699                         jp->error_code = PHP_JSON_ERROR_SYNTAX;
00700                         return false;
00701                 }
00702                 buf.len = 0;
00703                 JSON_RESET_TYPE();
00704             }
00705             break;
00706 /* : */
00707             case -2:
00708                 if (pop(jp, MODE_KEY) && push(jp, MODE_OBJECT)) {
00709                     jp->state = VA;
00710                     break;
00711                 }
00712 /*
00713     syntax error
00714 */
00715             default:
00716                 {
00717                                    jp->error_code = PHP_JSON_ERROR_SYNTAX;
00718                     FREE_BUFFERS();
00719                     return false;
00720                 }
00721             }
00722         }
00723     }
00724 
00725     FREE_BUFFERS();
00726        if (jp->state == OK && pop(jp, MODE_DONE)) {
00727               return true;
00728        }
00729 
00730        jp->error_code = PHP_JSON_ERROR_SYNTAX;
00731        return false;
00732 }
00733 
00734 
00735 /*
00736  * Local variables:
00737  * tab-width: 4
00738  * c-basic-offset: 4
00739  * End:
00740  * vim600: noet sw=4 ts=4
00741  * vim<600: noet sw=4 ts=4
00742  */