xref: /PHP-5.5/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,int options)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 
utf16_to_utf8(smart_str * buf,unsigned short utf16)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 
attach_zval(JSON_parser jp,int up,int cur,smart_str * key,int assoc TSRMLS_DC)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
parse_JSON_ex(JSON_parser jp,zval * z,unsigned short utf16_json[],int length,int options TSRMLS_DC)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  */
760