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