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
202 : push(JSON_parser jp, int mode)
203 2078 : {
204 2078 : jp->top += 1;
205 2078 : if (jp->top >= jp->depth) {
206 3 : jp->error_code = PHP_JSON_ERROR_DEPTH;
207 3 : return false;
208 : }
209 2075 : jp->stack[jp->top] = mode;
210 2075 : 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
219 : pop(JSON_parser jp, int mode)
220 931 : {
221 931 : if (jp->top < 0 || jp->stack[jp->top] != mode) {
222 6 : jp->error_code = PHP_JSON_ERROR_STATE_MISMATCH;
223 6 : return false;
224 : }
225 925 : jp->top -= 1;
226 925 : 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
242 : new_JSON_parser(int depth)
243 135 : {
244 135 : JSON_parser jp = (JSON_parser)emalloc(sizeof(struct JSON_parser_struct));
245 135 : jp->state = GO;
246 135 : jp->depth = depth;
247 135 : jp->top = -1;
248 135 : jp->error_code = PHP_JSON_ERROR_NONE;
249 135 : jp->stack = (int*)ecalloc(depth, sizeof(int));
250 135 : if (depth > JSON_PARSER_DEFAULT_DEPTH) {
251 0 : jp->the_zstack = (zval **)safe_emalloc(depth, sizeof(zval), 0);
252 : } else {
253 135 : jp->the_zstack = &jp->the_static_zstack[0];
254 : }
255 135 : push(jp, MODE_DONE);
256 135 : return jp;
257 : }
258 :
259 : /*
260 : Delete the JSON_parser object.
261 : */
262 : int
263 : free_JSON_parser(JSON_parser jp)
264 135 : {
265 135 : efree((void*)jp->stack);
266 135 : if (jp->the_zstack != &jp->the_static_zstack[0]) {
267 0 : efree(jp->the_zstack);
268 : }
269 135 : efree((void*)jp);
270 135 : return false;
271 : }
272 :
273 : static int dehexchar(char c)
274 600 : {
275 600 : if (c >= '0' && c <= '9')
276 : {
277 261 : return c - '0';
278 : }
279 339 : else if (c >= 'A' && c <= 'F')
280 : {
281 88 : return c - ('A' - 10);
282 : }
283 251 : else if (c >= 'a' && c <= 'f')
284 : {
285 251 : return c - ('a' - 10);
286 : }
287 : else
288 : {
289 0 : return -1;
290 : }
291 : }
292 :
293 :
294 : static void json_create_zval(zval **z, smart_str *buf, int type)
295 548 : {
296 548 : ALLOC_INIT_ZVAL(*z);
297 :
298 548 : if (type == IS_LONG)
299 : {
300 209 : if (buf->c[0] == '-') {
301 8 : buf->len--;
302 : }
303 :
304 209 : if (buf->len >= MAX_LENGTH_OF_LONG - 1) {
305 10 : if (buf->len == MAX_LENGTH_OF_LONG - 1) {
306 8 : int cmp = strcmp(buf->c + (buf->c[0] == '-'), long_min_digits);
307 :
308 8 : if (!(cmp < 0 || (cmp == 0 && buf->c[0] == '-'))) {
309 : goto use_double;
310 : }
311 : } else {
312 2 : goto use_double;
313 : }
314 : }
315 :
316 207 : ZVAL_LONG(*z, strtol(buf->c, NULL, 10));
317 : }
318 339 : else if (type == IS_DOUBLE)
319 : {
320 62 : use_double:
321 62 : ZVAL_DOUBLE(*z, zend_strtod(buf->c, NULL));
322 : }
323 279 : else if (type == IS_STRING)
324 : {
325 223 : ZVAL_STRINGL(*z, buf->c, buf->len, 1);
326 : }
327 56 : else if (type == IS_BOOL)
328 : {
329 38 : ZVAL_BOOL(*z, (*(buf->c) == 't'));
330 : }
331 : else /* type == IS_NULL) || type unknown */
332 : {
333 18 : ZVAL_NULL(*z);
334 : }
335 548 : }
336 :
337 :
338 : static void utf16_to_utf8(smart_str *buf, unsigned short utf16)
339 6795 : {
340 6795 : if (utf16 < 0x80)
341 : {
342 6625 : smart_str_appendc(buf, (unsigned char) utf16);
343 : }
344 170 : else if (utf16 < 0x800)
345 : {
346 8 : smart_str_appendc(buf, 0xc0 | (utf16 >> 6));
347 8 : smart_str_appendc(buf, 0x80 | (utf16 & 0x3f));
348 : }
349 163 : 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 1 : utf32 = (((buf->c[buf->len - 2] & 0xf) << 16)
359 : | ((buf->c[buf->len - 1] & 0x3f) << 10)
360 : | (utf16 & 0x3ff)) + 0x10000;
361 1 : buf->len -= 3;
362 :
363 1 : smart_str_appendc(buf, (unsigned char) (0xf0 | (utf32 >> 18)));
364 1 : smart_str_appendc(buf, 0x80 | ((utf32 >> 12) & 0x3f));
365 1 : smart_str_appendc(buf, 0x80 | ((utf32 >> 6) & 0x3f));
366 1 : smart_str_appendc(buf, 0x80 | (utf32 & 0x3f));
367 : }
368 : else
369 : {
370 161 : smart_str_appendc(buf, 0xe0 | (utf16 >> 12));
371 161 : smart_str_appendc(buf, 0x80 | ((utf16 >> 6) & 0x3f));
372 161 : smart_str_appendc(buf, 0x80 | (utf16 & 0x3f));
373 : }
374 6795 : }
375 :
376 : static void attach_zval(JSON_parser jp, int up, int cur, smart_str *key, int assoc TSRMLS_DC)
377 1193 : {
378 1193 : zval *root = jp->the_zstack[up];
379 1193 : zval *child = jp->the_zstack[cur];
380 1193 : int up_mode = jp->stack[up];
381 :
382 1193 : if (up_mode == MODE_ARRAY)
383 : {
384 1124 : add_next_index_zval(root, child);
385 : }
386 69 : else if (up_mode == MODE_OBJECT)
387 : {
388 69 : if (!assoc)
389 : {
390 37 : add_property_zval_ex(root, (key->len ? key->c : "_empty_"), (key->len ? (key->len + 1) : sizeof("_empty_")), child TSRMLS_CC);
391 37 : Z_DELREF_P(child);
392 : }
393 : else
394 : {
395 32 : add_assoc_zval_ex(root, (key->len ? key->c : ""), (key->len ? (key->len + 1) : sizeof("")), child);
396 : }
397 69 : key->len = 0;
398 : }
399 1193 : }
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
423 : parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int assoc TSRMLS_DC)
424 135 : {
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 135 : smart_str buf = {0};
431 135 : smart_str key = {0};
432 :
433 135 : unsigned short utf16 = 0;
434 : int type;
435 :
436 135 : JSON_RESET_TYPE();
437 :
438 13924 : for (the_index = 0; the_index < length; the_index += 1) {
439 13868 : next_char = utf16_json[the_index];
440 13868 : if (next_char >= 128) {
441 25 : next_class = C_ETC;
442 : } else {
443 13843 : next_class = ascii_class[next_char];
444 13843 : if (next_class <= __) {
445 1 : jp->error_code = PHP_JSON_ERROR_CTRL_CHAR;
446 1 : FREE_BUFFERS();
447 1 : return false;
448 : }
449 : }
450 : /*
451 : Get the next state from the transition table.
452 : */
453 13867 : next_state = state_transition_table[jp->state][next_class];
454 13867 : if (next_state >= 0) {
455 : /*
456 : Change the state and iterate
457 : */
458 10781 : if (type == IS_STRING) {
459 13084 : if (next_state == ST && jp->state != U4) {
460 5966 : if (jp->state != ES) {
461 5755 : utf16_to_utf8(&buf, next_char);
462 : } else {
463 211 : switch (next_char) {
464 : case 'b':
465 16 : smart_str_appendc(&buf, '\b');
466 16 : break;
467 : case 't':
468 16 : smart_str_appendc(&buf, '\t');
469 16 : break;
470 : case 'n':
471 18 : smart_str_appendc(&buf, '\n');
472 18 : break;
473 : case 'f':
474 16 : smart_str_appendc(&buf, '\f');
475 16 : break;
476 : case 'r':
477 18 : smart_str_appendc(&buf, '\r');
478 18 : break;
479 : default:
480 127 : utf16_to_utf8(&buf, next_char);
481 : break;
482 : }
483 : }
484 1152 : } else if (next_state == U2) {
485 150 : utf16 = dehexchar(next_char) << 12;
486 1002 : } else if (next_state == U3) {
487 150 : utf16 += dehexchar(next_char) << 8;
488 852 : } else if (next_state == U4) {
489 150 : utf16 += dehexchar(next_char) << 4;
490 702 : } else if (next_state == ST && jp->state == U4) {
491 150 : utf16 += dehexchar(next_char);
492 150 : utf16_to_utf8(&buf, utf16);
493 : }
494 3940 : } else if (type < IS_LONG && (next_class == C_DIGIT || next_class == C_ZERO)) {
495 277 : type = IS_LONG;
496 277 : smart_str_appendc(&buf, next_char);
497 3393 : } else if (type == IS_LONG && next_state == E1) {
498 7 : type = IS_DOUBLE;
499 7 : smart_str_appendc(&buf, next_char);
500 3432 : } else if (type < IS_DOUBLE && next_class == C_POINT) {
501 53 : type = IS_DOUBLE;
502 53 : smart_str_appendc(&buf, next_char);
503 3940 : } else if (type < IS_STRING && next_class == C_QUOTE) {
504 614 : type = IS_STRING;
505 2750 : } else if (type < IS_BOOL && ((jp->state == T3 && next_state == OK) || (jp->state == F4 && next_state == OK))) {
506 38 : type = IS_BOOL;
507 2692 : } else if (type < IS_NULL && jp->state == N3 && next_state == OK) {
508 18 : type = IS_NULL;
509 2656 : } else if (type != IS_STRING && next_class > C_WHITE) {
510 763 : utf16_to_utf8(&buf, next_char);
511 : }
512 10781 : jp->state = next_state;
513 : } else {
514 : /*
515 : Perform one of the predefined actions.
516 : */
517 3086 : switch (next_state) {
518 : /* empty } */
519 : case -9:
520 14 : if (!pop(jp, MODE_KEY)) {
521 0 : FREE_BUFFERS();
522 0 : return false;
523 : }
524 14 : jp->state = OK;
525 14 : break;
526 : /* } */
527 : case -8:
528 56 : if (type != -1 && jp->stack[jp->top] == MODE_OBJECT)
529 : {
530 : zval *mval;
531 27 : smart_str_0(&buf);
532 :
533 27 : json_create_zval(&mval, &buf, type);
534 :
535 27 : if (!assoc) {
536 15 : 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 15 : Z_DELREF_P(mval);
538 : } else {
539 12 : add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
540 : }
541 27 : key.len = 0;
542 27 : buf.len = 0;
543 27 : JSON_RESET_TYPE();
544 : }
545 :
546 :
547 56 : if (!pop(jp, MODE_OBJECT)) {
548 1 : FREE_BUFFERS();
549 1 : return false;
550 : }
551 55 : jp->state = OK;
552 55 : break;
553 : /* ] */
554 : case -7:
555 : {
556 152 : if (type != -1 && jp->stack[jp->top] == MODE_ARRAY)
557 : {
558 : zval *mval;
559 56 : smart_str_0(&buf);
560 :
561 56 : json_create_zval(&mval, &buf, type);
562 56 : add_next_index_zval(jp->the_zstack[jp->top], mval);
563 56 : buf.len = 0;
564 56 : JSON_RESET_TYPE();
565 : }
566 :
567 152 : if (!pop(jp, MODE_ARRAY)) {
568 2 : FREE_BUFFERS();
569 2 : return false;
570 : }
571 150 : jp->state = OK;
572 : }
573 150 : break;
574 : /* { */
575 : case -6:
576 89 : if (!push(jp, MODE_KEY)) {
577 0 : FREE_BUFFERS();
578 0 : return false;
579 : }
580 :
581 89 : jp->state = OB;
582 89 : if (jp->top > 0) {
583 : zval *obj;
584 :
585 89 : if (jp->top == 1) {
586 40 : obj = z;
587 : } else {
588 49 : ALLOC_INIT_ZVAL(obj);
589 : }
590 :
591 89 : if (!assoc) {
592 51 : object_init(obj);
593 : } else {
594 38 : array_init(obj);
595 : }
596 :
597 89 : jp->the_zstack[jp->top] = obj;
598 :
599 89 : if (jp->top > 1) {
600 49 : attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
601 : }
602 :
603 89 : JSON_RESET_TYPE();
604 : }
605 :
606 89 : break;
607 : /* [ */
608 : case -5:
609 1199 : if (!push(jp, MODE_ARRAY)) {
610 3 : FREE_BUFFERS();
611 3 : return false;
612 : }
613 1196 : jp->state = AR;
614 :
615 1196 : if (jp->top > 0) {
616 : zval *arr;
617 :
618 1196 : if (jp->top == 1) {
619 52 : arr = z;
620 : } else {
621 1144 : ALLOC_INIT_ZVAL(arr);
622 : }
623 :
624 1196 : array_init(arr);
625 1196 : jp->the_zstack[jp->top] = arr;
626 :
627 1196 : if (jp->top > 1) {
628 1144 : attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
629 : }
630 :
631 1196 : JSON_RESET_TYPE();
632 : }
633 :
634 1196 : break;
635 :
636 : /* " */
637 : case -4:
638 606 : switch (jp->stack[jp->top]) {
639 : case MODE_KEY:
640 365 : jp->state = CO;
641 365 : smart_str_0(&buf);
642 365 : SWAP_BUFFERS(buf, key);
643 365 : JSON_RESET_TYPE();
644 365 : break;
645 : case MODE_ARRAY:
646 : case MODE_OBJECT:
647 228 : jp->state = OK;
648 228 : break;
649 : case MODE_DONE:
650 13 : if (type == IS_STRING) {
651 13 : smart_str_0(&buf);
652 13 : ZVAL_STRINGL(z, buf.c, buf.len, 1);
653 13 : jp->state = OK;
654 13 : break;
655 : }
656 : /* fall through if not IS_STRING */
657 : default:
658 0 : FREE_BUFFERS();
659 0 : return false;
660 : }
661 606 : break;
662 : /* , */
663 : case -3:
664 : {
665 : zval *mval;
666 :
667 539 : if (type != -1 &&
668 : (jp->stack[jp->top] == MODE_OBJECT ||
669 : jp->stack[jp->top] == MODE_ARRAY))
670 : {
671 465 : smart_str_0(&buf);
672 465 : json_create_zval(&mval, &buf, type);
673 : }
674 :
675 539 : switch (jp->stack[jp->top]) {
676 : case MODE_OBJECT:
677 294 : if (pop(jp, MODE_OBJECT) && push(jp, MODE_KEY)) {
678 294 : if (type != -1) {
679 254 : if (!assoc) {
680 126 : add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
681 126 : Z_DELREF_P(mval);
682 : } else {
683 128 : add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
684 : }
685 254 : key.len = 0;
686 : }
687 294 : jp->state = KE;
688 : }
689 294 : break;
690 : case MODE_ARRAY:
691 243 : if (type != -1) {
692 211 : add_next_index_zval(jp->the_zstack[jp->top], mval);
693 : }
694 243 : jp->state = VA;
695 243 : break;
696 : default:
697 2 : FREE_BUFFERS();
698 2 : return false;
699 : }
700 537 : buf.len = 0;
701 537 : JSON_RESET_TYPE();
702 : }
703 537 : break;
704 : /* : */
705 : case -2:
706 361 : if (pop(jp, MODE_KEY) && push(jp, MODE_OBJECT)) {
707 361 : jp->state = VA;
708 361 : break;
709 : }
710 : /*
711 : syntax error
712 : */
713 : default:
714 : {
715 70 : jp->error_code = PHP_JSON_ERROR_SYNTAX;
716 70 : FREE_BUFFERS();
717 70 : return false;
718 : }
719 : }
720 : }
721 : }
722 :
723 56 : FREE_BUFFERS();
724 56 : if (jp->state == OK && pop(jp, MODE_DONE)) {
725 51 : return true;
726 : }
727 :
728 5 : jp->error_code = PHP_JSON_ERROR_SYNTAX;
729 5 : return false;
730 : }
731 :
732 :
733 : /*
734 : * Local variables:
735 : * tab-width: 4
736 : * c-basic-offset: 4
737 : * End:
738 : * vim600: noet sw=4 ts=4
739 : * vim<600: noet sw=4 ts=4
740 : */
|