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