xref: /PHP-5.3/ext/json/JSON_parser.c (revision 9b567fea)
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
push(JSON_parser jp,int mode)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
pop(JSON_parser jp,int mode)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
new_JSON_parser(int depth)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
free_JSON_parser(JSON_parser jp)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 
dehexchar(char c)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 
json_create_zval(zval ** z,smart_str * buf,int type)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 
utf16_to_utf8(smart_str * buf,unsigned short utf16)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 
attach_zval(JSON_parser jp,int up,int cur,smart_str * key,int assoc TSRMLS_DC)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
parse_JSON(JSON_parser jp,zval * z,unsigned short utf16_json[],int length,int assoc TSRMLS_DC)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  */
743