Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8553 | superturbo | 1 | /* vim: set et ts=3 sw=3 sts=3 ft=c: |
2 | * |
||
3 | * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved. |
||
4 | * https://github.com/udp/json-parser |
||
5 | * |
||
6 | * Redistribution and use in source and binary forms, with or without |
||
7 | * modification, are permitted provided that the following conditions |
||
8 | * are met: |
||
9 | * |
||
10 | * 1. Redistributions of source code must retain the above copyright |
||
11 | * notice, this list of conditions and the following disclaimer. |
||
12 | * |
||
13 | * 2. Redistributions in binary form must reproduce the above copyright |
||
14 | * notice, this list of conditions and the following disclaimer in the |
||
15 | * documentation and/or other materials provided with the distribution. |
||
16 | * |
||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||
27 | * SUCH DAMAGE. |
||
28 | */ |
||
29 | |||
30 | #include "json.h" |
||
31 | |||
32 | #ifdef _MSC_VER |
||
33 | #ifndef _CRT_SECURE_NO_WARNINGS |
||
34 | #define _CRT_SECURE_NO_WARNINGS |
||
35 | #endif |
||
36 | #include |
||
37 | #endif |
||
38 | |||
39 | const struct _json_value json_value_none; |
||
40 | |||
41 | #include |
||
42 | #include |
||
43 | #include |
||
44 | #include |
||
45 | |||
46 | typedef unsigned int json_uchar; |
||
47 | |||
48 | /* There has to be a better way to do this */ |
||
49 | static const json_int_t JSON_INT_MAX = sizeof(json_int_t) == 1 |
||
50 | ? INT8_MAX |
||
51 | : (sizeof(json_int_t) == 2 |
||
52 | ? INT16_MAX |
||
53 | : (sizeof(json_int_t) == 4 |
||
54 | ? INT32_MAX |
||
55 | : INT64_MAX)); |
||
56 | |||
57 | static unsigned char hex_value (json_char c) |
||
58 | { |
||
59 | if (isdigit(c)) |
||
60 | return c - '0'; |
||
61 | |||
62 | switch (c) { |
||
63 | case 'a': case 'A': return 0x0A; |
||
64 | case 'b': case 'B': return 0x0B; |
||
65 | case 'c': case 'C': return 0x0C; |
||
66 | case 'd': case 'D': return 0x0D; |
||
67 | case 'e': case 'E': return 0x0E; |
||
68 | case 'f': case 'F': return 0x0F; |
||
69 | default: return 0xFF; |
||
70 | } |
||
71 | } |
||
72 | |||
73 | static int would_overflow (json_int_t value, json_char b) |
||
74 | { |
||
75 | return ((JSON_INT_MAX - (b - '0')) / 10 ) < value; |
||
76 | } |
||
77 | |||
78 | typedef struct |
||
79 | { |
||
80 | unsigned long used_memory; |
||
81 | |||
82 | unsigned int uint_max; |
||
83 | unsigned long ulong_max; |
||
84 | |||
85 | json_settings settings; |
||
86 | int first_pass; |
||
87 | |||
88 | const json_char * ptr; |
||
89 | unsigned int cur_line, cur_col; |
||
90 | |||
91 | } json_state; |
||
92 | |||
93 | static void * default_alloc (size_t size, int zero, void * user_data) |
||
94 | { |
||
95 | return zero ? calloc (1, size) : malloc (size); |
||
96 | } |
||
97 | |||
98 | static void default_free (void * ptr, void * user_data) |
||
99 | { |
||
100 | free (ptr); |
||
101 | } |
||
102 | |||
103 | static void * json_alloc (json_state * state, unsigned long size, int zero) |
||
104 | { |
||
105 | if ((state->ulong_max - state->used_memory) < size) |
||
106 | return 0; |
||
107 | |||
108 | if (state->settings.max_memory |
||
109 | && (state->used_memory += size) > state->settings.max_memory) |
||
110 | { |
||
111 | return 0; |
||
112 | } |
||
113 | |||
114 | return state->settings.mem_alloc (size, zero, state->settings.user_data); |
||
115 | } |
||
116 | |||
117 | static int new_value (json_state * state, |
||
118 | json_value ** top, json_value ** root, json_value ** alloc, |
||
119 | json_type type) |
||
120 | { |
||
121 | json_value * value; |
||
122 | int values_size; |
||
123 | |||
124 | if (!state->first_pass) |
||
125 | { |
||
126 | value = *top = *alloc; |
||
127 | *alloc = (*alloc)->_reserved.next_alloc; |
||
128 | |||
129 | if (!*root) |
||
130 | *root = value; |
||
131 | |||
132 | switch (value->type) |
||
133 | { |
||
134 | case json_array: |
||
135 | |||
136 | if (value->u.array.length == 0) |
||
137 | break; |
||
138 | |||
139 | if (! (value->u.array.values = (json_value **) json_alloc |
||
140 | (state, value->u.array.length * sizeof (json_value *), 0)) ) |
||
141 | { |
||
142 | return 0; |
||
143 | } |
||
144 | |||
145 | value->u.array.length = 0; |
||
146 | break; |
||
147 | |||
148 | case json_object: |
||
149 | |||
150 | if (value->u.object.length == 0) |
||
151 | break; |
||
152 | |||
153 | values_size = sizeof (*value->u.object.values) * value->u.object.length; |
||
154 | |||
155 | if (! (value->u.object.values = (json_object_entry *) json_alloc |
||
156 | (state, values_size + ((unsigned long) value->u.object.values), 0)) ) |
||
157 | { |
||
158 | return 0; |
||
159 | } |
||
160 | |||
161 | value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size; |
||
162 | |||
163 | value->u.object.length = 0; |
||
164 | break; |
||
165 | |||
166 | case json_string: |
||
167 | |||
168 | if (! (value->u.string.ptr = (json_char *) json_alloc |
||
169 | (state, (value->u.string.length + 1) * sizeof (json_char), 0)) ) |
||
170 | { |
||
171 | return 0; |
||
172 | } |
||
173 | |||
174 | value->u.string.length = 0; |
||
175 | break; |
||
176 | |||
177 | default: |
||
178 | break; |
||
179 | }; |
||
180 | |||
181 | return 1; |
||
182 | } |
||
183 | |||
184 | if (! (value = (json_value *) json_alloc |
||
185 | (state, sizeof (json_value) + state->settings.value_extra, 1))) |
||
186 | { |
||
187 | return 0; |
||
188 | } |
||
189 | |||
190 | if (!*root) |
||
191 | *root = value; |
||
192 | |||
193 | value->type = type; |
||
194 | value->parent = *top; |
||
195 | |||
196 | #ifdef JSON_TRACK_SOURCE |
||
197 | value->line = state->cur_line; |
||
198 | value->col = state->cur_col; |
||
199 | #endif |
||
200 | |||
201 | if (*alloc) |
||
202 | (*alloc)->_reserved.next_alloc = value; |
||
203 | |||
204 | *alloc = *top = value; |
||
205 | |||
206 | return 1; |
||
207 | } |
||
208 | |||
209 | #define whitespace \ |
||
210 | case '\n': ++ state.cur_line; state.cur_col = 0; \ |
||
211 | case ' ': case '\t': case '\r' |
||
212 | |||
213 | #define string_add(b) \ |
||
214 | do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0); |
||
215 | |||
216 | #define line_and_col \ |
||
217 | state.cur_line, state.cur_col |
||
218 | |||
219 | static const long |
||
220 | flag_next = 1 << 0, |
||
221 | flag_reproc = 1 << 1, |
||
222 | flag_need_comma = 1 << 2, |
||
223 | flag_seek_value = 1 << 3, |
||
224 | flag_escaped = 1 << 4, |
||
225 | flag_string = 1 << 5, |
||
226 | flag_need_colon = 1 << 6, |
||
227 | flag_done = 1 << 7, |
||
228 | flag_num_negative = 1 << 8, |
||
229 | flag_num_zero = 1 << 9, |
||
230 | flag_num_e = 1 << 10, |
||
231 | flag_num_e_got_sign = 1 << 11, |
||
232 | flag_num_e_negative = 1 << 12, |
||
233 | flag_line_comment = 1 << 13, |
||
234 | flag_block_comment = 1 << 14, |
||
235 | flag_num_got_decimal = 1 << 15; |
||
236 | |||
237 | json_value * json_parse_ex (json_settings * settings, |
||
238 | const json_char * json, |
||
239 | size_t length, |
||
240 | char * error_buf) |
||
241 | { |
||
242 | json_char error [json_error_max]; |
||
243 | const json_char * end; |
||
244 | json_value * top, * root, * alloc = 0; |
||
245 | json_state state = { 0 }; |
||
246 | long flags = 0; |
||
247 | double num_digits = 0, num_e = 0; |
||
248 | double num_fraction = 0; |
||
249 | |||
250 | /* Skip UTF-8 BOM |
||
251 | */ |
||
252 | if (length >= 3 && ((unsigned char) json [0]) == 0xEF |
||
253 | && ((unsigned char) json [1]) == 0xBB |
||
254 | && ((unsigned char) json [2]) == 0xBF) |
||
255 | { |
||
256 | json += 3; |
||
257 | length -= 3; |
||
258 | } |
||
259 | |||
260 | error[0] = '\0'; |
||
261 | end = (json + length); |
||
262 | |||
263 | memcpy (&state.settings, settings, sizeof (json_settings)); |
||
264 | |||
265 | if (!state.settings.mem_alloc) |
||
266 | state.settings.mem_alloc = default_alloc; |
||
267 | |||
268 | if (!state.settings.mem_free) |
||
269 | state.settings.mem_free = default_free; |
||
270 | |||
271 | memset (&state.uint_max, 0xFF, sizeof (state.uint_max)); |
||
272 | memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max)); |
||
273 | |||
274 | state.uint_max -= 8; /* limit of how much can be added before next check */ |
||
275 | state.ulong_max -= 8; |
||
276 | |||
277 | for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass) |
||
278 | { |
||
279 | json_uchar uchar; |
||
280 | unsigned char uc_b1, uc_b2, uc_b3, uc_b4; |
||
281 | json_char * string = 0; |
||
282 | unsigned int string_length = 0; |
||
283 | |||
284 | top = root = 0; |
||
285 | flags = flag_seek_value; |
||
286 | |||
287 | state.cur_line = 1; |
||
288 | |||
289 | for (state.ptr = json ;; ++ state.ptr) |
||
290 | { |
||
291 | json_char b = (state.ptr == end ? 0 : *state.ptr); |
||
292 | |||
293 | if (flags & flag_string) |
||
294 | { |
||
295 | if (!b) |
||
296 | { sprintf (error, "Unexpected EOF in string (at %d:%d)", line_and_col); |
||
297 | goto e_failed; |
||
298 | } |
||
299 | |||
300 | if (string_length > state.uint_max) |
||
301 | goto e_overflow; |
||
302 | |||
303 | if (flags & flag_escaped) |
||
304 | { |
||
305 | flags &= ~ flag_escaped; |
||
306 | |||
307 | switch (b) |
||
308 | { |
||
309 | case 'b': string_add ('\b'); break; |
||
310 | case 'f': string_add ('\f'); break; |
||
311 | case 'n': string_add ('\n'); break; |
||
312 | case 'r': string_add ('\r'); break; |
||
313 | case 't': string_add ('\t'); break; |
||
314 | case 'u': |
||
315 | |||
316 | if (end - state.ptr <= 4 || |
||
317 | (uc_b1 = hex_value (*++ state.ptr)) == 0xFF || |
||
318 | (uc_b2 = hex_value (*++ state.ptr)) == 0xFF || |
||
319 | (uc_b3 = hex_value (*++ state.ptr)) == 0xFF || |
||
320 | (uc_b4 = hex_value (*++ state.ptr)) == 0xFF) |
||
321 | { |
||
322 | sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col); |
||
323 | goto e_failed; |
||
324 | } |
||
325 | |||
326 | uc_b1 = (uc_b1 << 4) | uc_b2; |
||
327 | uc_b2 = (uc_b3 << 4) | uc_b4; |
||
328 | uchar = (uc_b1 << 8) | uc_b2; |
||
329 | |||
330 | if ((uchar & 0xF800) == 0xD800) { |
||
331 | json_uchar uchar2; |
||
332 | |||
333 | if (end - state.ptr <= 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' || |
||
334 | (uc_b1 = hex_value (*++ state.ptr)) == 0xFF || |
||
335 | (uc_b2 = hex_value (*++ state.ptr)) == 0xFF || |
||
336 | (uc_b3 = hex_value (*++ state.ptr)) == 0xFF || |
||
337 | (uc_b4 = hex_value (*++ state.ptr)) == 0xFF) |
||
338 | { |
||
339 | sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col); |
||
340 | goto e_failed; |
||
341 | } |
||
342 | |||
343 | uc_b1 = (uc_b1 << 4) | uc_b2; |
||
344 | uc_b2 = (uc_b3 << 4) | uc_b4; |
||
345 | uchar2 = (uc_b1 << 8) | uc_b2; |
||
346 | |||
347 | uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF); |
||
348 | } |
||
349 | |||
350 | if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F)) |
||
351 | { |
||
352 | string_add ((json_char) uchar); |
||
353 | break; |
||
354 | } |
||
355 | |||
356 | if (uchar <= 0x7FF) |
||
357 | { |
||
358 | if (state.first_pass) |
||
359 | string_length += 2; |
||
360 | else |
||
361 | { string [string_length ++] = 0xC0 | (uchar >> 6); |
||
362 | string [string_length ++] = 0x80 | (uchar & 0x3F); |
||
363 | } |
||
364 | |||
365 | break; |
||
366 | } |
||
367 | |||
368 | if (uchar <= 0xFFFF) { |
||
369 | if (state.first_pass) |
||
370 | string_length += 3; |
||
371 | else |
||
372 | { string [string_length ++] = 0xE0 | (uchar >> 12); |
||
373 | string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F); |
||
374 | string [string_length ++] = 0x80 | (uchar & 0x3F); |
||
375 | } |
||
376 | |||
377 | break; |
||
378 | } |
||
379 | |||
380 | if (state.first_pass) |
||
381 | string_length += 4; |
||
382 | else |
||
383 | { string [string_length ++] = 0xF0 | (uchar >> 18); |
||
384 | string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F); |
||
385 | string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F); |
||
386 | string [string_length ++] = 0x80 | (uchar & 0x3F); |
||
387 | } |
||
388 | |||
389 | break; |
||
390 | |||
391 | default: |
||
392 | string_add (b); |
||
393 | }; |
||
394 | |||
395 | continue; |
||
396 | } |
||
397 | |||
398 | if (b == '\\') |
||
399 | { |
||
400 | flags |= flag_escaped; |
||
401 | continue; |
||
402 | } |
||
403 | |||
404 | if (b == '"') |
||
405 | { |
||
406 | if (!state.first_pass) |
||
407 | string [string_length] = 0; |
||
408 | |||
409 | flags &= ~ flag_string; |
||
410 | string = 0; |
||
411 | |||
412 | switch (top->type) |
||
413 | { |
||
414 | case json_string: |
||
415 | |||
416 | top->u.string.length = string_length; |
||
417 | flags |= flag_next; |
||
418 | |||
419 | break; |
||
420 | |||
421 | case json_object: |
||
422 | |||
423 | if (state.first_pass) |
||
424 | (*(json_char **) &top->u.object.values) += string_length + 1; |
||
425 | else |
||
426 | { |
||
427 | top->u.object.values [top->u.object.length].name |
||
428 | = (json_char *) top->_reserved.object_mem; |
||
429 | |||
430 | top->u.object.values [top->u.object.length].name_length |
||
431 | = string_length; |
||
432 | |||
433 | (*(json_char **) &top->_reserved.object_mem) += string_length + 1; |
||
434 | } |
||
435 | |||
436 | flags |= flag_seek_value | flag_need_colon; |
||
437 | continue; |
||
438 | |||
439 | default: |
||
440 | break; |
||
441 | }; |
||
442 | } |
||
443 | else |
||
444 | { |
||
445 | string_add (b); |
||
446 | continue; |
||
447 | } |
||
448 | } |
||
449 | |||
450 | if (state.settings.settings & json_enable_comments) |
||
451 | { |
||
452 | if (flags & (flag_line_comment | flag_block_comment)) |
||
453 | { |
||
454 | if (flags & flag_line_comment) |
||
455 | { |
||
456 | if (b == '\r' || b == '\n' || !b) |
||
457 | { |
||
458 | flags &= ~ flag_line_comment; |
||
459 | -- state.ptr; /* so null can be reproc'd */ |
||
460 | } |
||
461 | |||
462 | continue; |
||
463 | } |
||
464 | |||
465 | if (flags & flag_block_comment) |
||
466 | { |
||
467 | if (!b) |
||
468 | { sprintf (error, "%d:%d: Unexpected EOF in block comment", line_and_col); |
||
469 | goto e_failed; |
||
470 | } |
||
471 | |||
472 | if (b == '*' && state.ptr < (end - 1) && state.ptr [1] == '/') |
||
473 | { |
||
474 | flags &= ~ flag_block_comment; |
||
475 | ++ state.ptr; /* skip closing sequence */ |
||
476 | } |
||
477 | |||
478 | continue; |
||
479 | } |
||
480 | } |
||
481 | else if (b == '/') |
||
482 | { |
||
483 | if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object) |
||
484 | { sprintf (error, "%d:%d: Comment not allowed here", line_and_col); |
||
485 | goto e_failed; |
||
486 | } |
||
487 | |||
488 | if (++ state.ptr == end) |
||
489 | { sprintf (error, "%d:%d: EOF unexpected", line_and_col); |
||
490 | goto e_failed; |
||
491 | } |
||
492 | |||
493 | switch (b = *state.ptr) |
||
494 | { |
||
495 | case '/': |
||
496 | flags |= flag_line_comment; |
||
497 | continue; |
||
498 | |||
499 | case '*': |
||
500 | flags |= flag_block_comment; |
||
501 | continue; |
||
502 | |||
503 | default: |
||
504 | sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", line_and_col, b); |
||
505 | goto e_failed; |
||
506 | }; |
||
507 | } |
||
508 | } |
||
509 | |||
510 | if (flags & flag_done) |
||
511 | { |
||
512 | if (!b) |
||
513 | break; |
||
514 | |||
515 | switch (b) |
||
516 | { |
||
517 | whitespace: |
||
518 | continue; |
||
519 | |||
520 | default: |
||
521 | |||
522 | sprintf (error, "%d:%d: Trailing garbage: `%c`", |
||
523 | state.cur_line, state.cur_col, b); |
||
524 | |||
525 | goto e_failed; |
||
526 | }; |
||
527 | } |
||
528 | |||
529 | if (flags & flag_seek_value) |
||
530 | { |
||
531 | switch (b) |
||
532 | { |
||
533 | whitespace: |
||
534 | continue; |
||
535 | |||
536 | case ']': |
||
537 | |||
538 | if (top && top->type == json_array) |
||
539 | flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next; |
||
540 | else |
||
541 | { sprintf (error, "%d:%d: Unexpected ]", line_and_col); |
||
542 | goto e_failed; |
||
543 | } |
||
544 | |||
545 | break; |
||
546 | |||
547 | default: |
||
548 | |||
549 | if (flags & flag_need_comma) |
||
550 | { |
||
551 | if (b == ',') |
||
552 | { flags &= ~ flag_need_comma; |
||
553 | continue; |
||
554 | } |
||
555 | else |
||
556 | { |
||
557 | sprintf (error, "%d:%d: Expected , before %c", |
||
558 | state.cur_line, state.cur_col, b); |
||
559 | |||
560 | goto e_failed; |
||
561 | } |
||
562 | } |
||
563 | |||
564 | if (flags & flag_need_colon) |
||
565 | { |
||
566 | if (b == ':') |
||
567 | { flags &= ~ flag_need_colon; |
||
568 | continue; |
||
569 | } |
||
570 | else |
||
571 | { |
||
572 | sprintf (error, "%d:%d: Expected : before %c", |
||
573 | state.cur_line, state.cur_col, b); |
||
574 | |||
575 | goto e_failed; |
||
576 | } |
||
577 | } |
||
578 | |||
579 | flags &= ~ flag_seek_value; |
||
580 | |||
581 | switch (b) |
||
582 | { |
||
583 | case '{': |
||
584 | |||
585 | if (!new_value (&state, &top, &root, &alloc, json_object)) |
||
586 | goto e_alloc_failure; |
||
587 | |||
588 | continue; |
||
589 | |||
590 | case '[': |
||
591 | |||
592 | if (!new_value (&state, &top, &root, &alloc, json_array)) |
||
593 | goto e_alloc_failure; |
||
594 | |||
595 | flags |= flag_seek_value; |
||
596 | continue; |
||
597 | |||
598 | case '"': |
||
599 | |||
600 | if (!new_value (&state, &top, &root, &alloc, json_string)) |
||
601 | goto e_alloc_failure; |
||
602 | |||
603 | flags |= flag_string; |
||
604 | |||
605 | string = top->u.string.ptr; |
||
606 | string_length = 0; |
||
607 | |||
608 | continue; |
||
609 | |||
610 | case 't': |
||
611 | |||
612 | if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' || |
||
613 | *(++ state.ptr) != 'u' || *(++ state.ptr) != 'e') |
||
614 | { |
||
615 | goto e_unknown_value; |
||
616 | } |
||
617 | |||
618 | if (!new_value (&state, &top, &root, &alloc, json_boolean)) |
||
619 | goto e_alloc_failure; |
||
620 | |||
621 | top->u.boolean = 1; |
||
622 | |||
623 | flags |= flag_next; |
||
624 | break; |
||
625 | |||
626 | case 'f': |
||
627 | |||
628 | if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' || |
||
629 | *(++ state.ptr) != 'l' || *(++ state.ptr) != 's' || |
||
630 | *(++ state.ptr) != 'e') |
||
631 | { |
||
632 | goto e_unknown_value; |
||
633 | } |
||
634 | |||
635 | if (!new_value (&state, &top, &root, &alloc, json_boolean)) |
||
636 | goto e_alloc_failure; |
||
637 | |||
638 | flags |= flag_next; |
||
639 | break; |
||
640 | |||
641 | case 'n': |
||
642 | |||
643 | if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' || |
||
644 | *(++ state.ptr) != 'l' || *(++ state.ptr) != 'l') |
||
645 | { |
||
646 | goto e_unknown_value; |
||
647 | } |
||
648 | |||
649 | if (!new_value (&state, &top, &root, &alloc, json_null)) |
||
650 | goto e_alloc_failure; |
||
651 | |||
652 | flags |= flag_next; |
||
653 | break; |
||
654 | |||
655 | default: |
||
656 | |||
657 | if (isdigit (b) || b == '-') |
||
658 | { |
||
659 | if (!new_value (&state, &top, &root, &alloc, json_integer)) |
||
660 | goto e_alloc_failure; |
||
661 | |||
662 | if (!state.first_pass) |
||
663 | { |
||
664 | while (isdigit (b) || b == '+' || b == '-' |
||
665 | || b == 'e' || b == 'E' || b == '.') |
||
666 | { |
||
667 | if ( (++ state.ptr) == end) |
||
668 | { |
||
669 | b = 0; |
||
670 | break; |
||
671 | } |
||
672 | |||
673 | b = *state.ptr; |
||
674 | } |
||
675 | |||
676 | flags |= flag_next | flag_reproc; |
||
677 | break; |
||
678 | } |
||
679 | |||
680 | flags &= ~ (flag_num_negative | flag_num_e | |
||
681 | flag_num_e_got_sign | flag_num_e_negative | |
||
682 | flag_num_zero); |
||
683 | |||
684 | num_digits = 0; |
||
685 | num_fraction = 0; |
||
686 | num_e = 0; |
||
687 | |||
688 | if (b != '-') |
||
689 | { |
||
690 | flags |= flag_reproc; |
||
691 | break; |
||
692 | } |
||
693 | |||
694 | flags |= flag_num_negative; |
||
695 | continue; |
||
696 | } |
||
697 | else |
||
698 | { sprintf (error, "%d:%d: Unexpected %c when seeking value", line_and_col, b); |
||
699 | goto e_failed; |
||
700 | } |
||
701 | }; |
||
702 | }; |
||
703 | } |
||
704 | else |
||
705 | { |
||
706 | switch (top->type) |
||
707 | { |
||
708 | case json_object: |
||
709 | |||
710 | switch (b) |
||
711 | { |
||
712 | whitespace: |
||
713 | continue; |
||
714 | |||
715 | case '"': |
||
716 | |||
717 | if (flags & flag_need_comma) |
||
718 | { sprintf (error, "%d:%d: Expected , before \"", line_and_col); |
||
719 | goto e_failed; |
||
720 | } |
||
721 | |||
722 | flags |= flag_string; |
||
723 | |||
724 | string = (json_char *) top->_reserved.object_mem; |
||
725 | string_length = 0; |
||
726 | |||
727 | break; |
||
728 | |||
729 | case '}': |
||
730 | |||
731 | flags = (flags & ~ flag_need_comma) | flag_next; |
||
732 | break; |
||
733 | |||
734 | case ',': |
||
735 | |||
736 | if (flags & flag_need_comma) |
||
737 | { |
||
738 | flags &= ~ flag_need_comma; |
||
739 | break; |
||
740 | } |
||
741 | |||
742 | default: |
||
743 | sprintf (error, "%d:%d: Unexpected `%c` in object", line_and_col, b); |
||
744 | goto e_failed; |
||
745 | }; |
||
746 | |||
747 | break; |
||
748 | |||
749 | case json_integer: |
||
750 | case json_double: |
||
751 | |||
752 | if (isdigit (b)) |
||
753 | { |
||
754 | ++ num_digits; |
||
755 | |||
756 | if (top->type == json_integer || flags & flag_num_e) |
||
757 | { |
||
758 | if (! (flags & flag_num_e)) |
||
759 | { |
||
760 | if (flags & flag_num_zero) |
||
761 | { sprintf (error, "%d:%d: Unexpected `0` before `%c`", line_and_col, b); |
||
762 | goto e_failed; |
||
763 | } |
||
764 | |||
765 | if (num_digits == 1 && b == '0') |
||
766 | flags |= flag_num_zero; |
||
767 | } |
||
768 | else |
||
769 | { |
||
770 | flags |= flag_num_e_got_sign; |
||
771 | num_e = (num_e * 10) + (b - '0'); |
||
772 | continue; |
||
773 | } |
||
774 | |||
775 | if (would_overflow(top->u.integer, b)) |
||
776 | { -- num_digits; |
||
777 | -- state.ptr; |
||
778 | top->type = json_double; |
||
779 | top->u.dbl = (double)top->u.integer; |
||
780 | continue; |
||
781 | } |
||
782 | |||
783 | top->u.integer = (top->u.integer * 10) + (b - '0'); |
||
784 | continue; |
||
785 | } |
||
786 | |||
787 | if (flags & flag_num_got_decimal) |
||
788 | num_fraction = (num_fraction * 10) + (b - '0'); |
||
789 | else |
||
790 | top->u.dbl = (top->u.dbl * 10) + (b - '0'); |
||
791 | |||
792 | continue; |
||
793 | } |
||
794 | |||
795 | if (b == '+' || b == '-') |
||
796 | { |
||
797 | if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign)) |
||
798 | { |
||
799 | flags |= flag_num_e_got_sign; |
||
800 | |||
801 | if (b == '-') |
||
802 | flags |= flag_num_e_negative; |
||
803 | |||
804 | continue; |
||
805 | } |
||
806 | } |
||
807 | else if (b == '.' && top->type == json_integer) |
||
808 | { |
||
809 | if (!num_digits) |
||
810 | { sprintf (error, "%d:%d: Expected digit before `.`", line_and_col); |
||
811 | goto e_failed; |
||
812 | } |
||
813 | |||
814 | top->type = json_double; |
||
815 | top->u.dbl = (double) top->u.integer; |
||
816 | |||
817 | flags |= flag_num_got_decimal; |
||
818 | num_digits = 0; |
||
819 | continue; |
||
820 | } |
||
821 | |||
822 | if (! (flags & flag_num_e)) |
||
823 | { |
||
824 | if (top->type == json_double) |
||
825 | { |
||
826 | if (!num_digits) |
||
827 | { sprintf (error, "%d:%d: Expected digit after `.`", line_and_col); |
||
828 | goto e_failed; |
||
829 | } |
||
830 | |||
831 | top->u.dbl += num_fraction / pow (10.0, num_digits); |
||
832 | } |
||
833 | |||
834 | if (b == 'e' || b == 'E') |
||
835 | { |
||
836 | flags |= flag_num_e; |
||
837 | |||
838 | if (top->type == json_integer) |
||
839 | { |
||
840 | top->type = json_double; |
||
841 | top->u.dbl = (double) top->u.integer; |
||
842 | } |
||
843 | |||
844 | num_digits = 0; |
||
845 | flags &= ~ flag_num_zero; |
||
846 | |||
847 | continue; |
||
848 | } |
||
849 | } |
||
850 | else |
||
851 | { |
||
852 | if (!num_digits) |
||
853 | { sprintf (error, "%d:%d: Expected digit after `e`", line_and_col); |
||
854 | goto e_failed; |
||
855 | } |
||
856 | |||
857 | top->u.dbl *= pow (10.0, (flags & flag_num_e_negative ? - num_e : num_e)); |
||
858 | } |
||
859 | |||
860 | if (flags & flag_num_negative) |
||
861 | { |
||
862 | if (top->type == json_integer) |
||
863 | top->u.integer = - top->u.integer; |
||
864 | else |
||
865 | top->u.dbl = - top->u.dbl; |
||
866 | } |
||
867 | |||
868 | flags |= flag_next | flag_reproc; |
||
869 | break; |
||
870 | |||
871 | default: |
||
872 | break; |
||
873 | }; |
||
874 | } |
||
875 | |||
876 | if (flags & flag_reproc) |
||
877 | { |
||
878 | flags &= ~ flag_reproc; |
||
879 | -- state.ptr; |
||
880 | } |
||
881 | |||
882 | if (flags & flag_next) |
||
883 | { |
||
884 | flags = (flags & ~ flag_next) | flag_need_comma; |
||
885 | |||
886 | if (!top->parent) |
||
887 | { |
||
888 | /* root value done */ |
||
889 | |||
890 | flags |= flag_done; |
||
891 | continue; |
||
892 | } |
||
893 | |||
894 | if (top->parent->type == json_array) |
||
895 | flags |= flag_seek_value; |
||
896 | |||
897 | if (!state.first_pass) |
||
898 | { |
||
899 | json_value * parent = top->parent; |
||
900 | |||
901 | switch (parent->type) |
||
902 | { |
||
903 | case json_object: |
||
904 | |||
905 | parent->u.object.values |
||
906 | [parent->u.object.length].value = top; |
||
907 | |||
908 | break; |
||
909 | |||
910 | case json_array: |
||
911 | |||
912 | parent->u.array.values |
||
913 | [parent->u.array.length] = top; |
||
914 | |||
915 | break; |
||
916 | |||
917 | default: |
||
918 | break; |
||
919 | }; |
||
920 | } |
||
921 | |||
922 | if ( (++ top->parent->u.array.length) > state.uint_max) |
||
923 | goto e_overflow; |
||
924 | |||
925 | top = top->parent; |
||
926 | |||
927 | continue; |
||
928 | } |
||
929 | } |
||
930 | |||
931 | alloc = root; |
||
932 | } |
||
933 | |||
934 | return root; |
||
935 | |||
936 | e_unknown_value: |
||
937 | |||
938 | sprintf (error, "%d:%d: Unknown value", line_and_col); |
||
939 | goto e_failed; |
||
940 | |||
941 | e_alloc_failure: |
||
942 | |||
943 | strcpy (error, "Memory allocation failure"); |
||
944 | goto e_failed; |
||
945 | |||
946 | e_overflow: |
||
947 | |||
948 | sprintf (error, "%d:%d: Too long (caught overflow)", line_and_col); |
||
949 | goto e_failed; |
||
950 | |||
951 | e_failed: |
||
952 | |||
953 | if (error_buf) |
||
954 | { |
||
955 | if (*error) |
||
956 | strcpy (error_buf, error); |
||
957 | else |
||
958 | strcpy (error_buf, "Unknown error"); |
||
959 | } |
||
960 | |||
961 | if (state.first_pass) |
||
962 | alloc = root; |
||
963 | |||
964 | while (alloc) |
||
965 | { |
||
966 | top = alloc->_reserved.next_alloc; |
||
967 | state.settings.mem_free (alloc, state.settings.user_data); |
||
968 | alloc = top; |
||
969 | } |
||
970 | |||
971 | if (!state.first_pass) |
||
972 | json_value_free_ex (&state.settings, root); |
||
973 | |||
974 | return 0; |
||
975 | } |
||
976 | |||
977 | json_value * json_parse (const json_char * json, size_t length) |
||
978 | { |
||
979 | json_settings settings = { 0 }; |
||
980 | return json_parse_ex (&settings, json, length, 0); |
||
981 | } |
||
982 | |||
983 | void json_value_free_ex (json_settings * settings, json_value * value) |
||
984 | { |
||
985 | json_value * cur_value; |
||
986 | |||
987 | if (!value) |
||
988 | return; |
||
989 | |||
990 | value->parent = 0; |
||
991 | |||
992 | while (value) |
||
993 | { |
||
994 | switch (value->type) |
||
995 | { |
||
996 | case json_array: |
||
997 | |||
998 | if (!value->u.array.length) |
||
999 | { |
||
1000 | settings->mem_free (value->u.array.values, settings->user_data); |
||
1001 | break; |
||
1002 | } |
||
1003 | |||
1004 | value = value->u.array.values [-- value->u.array.length]; |
||
1005 | continue; |
||
1006 | |||
1007 | case json_object: |
||
1008 | |||
1009 | if (!value->u.object.length) |
||
1010 | { |
||
1011 | settings->mem_free (value->u.object.values, settings->user_data); |
||
1012 | break; |
||
1013 | } |
||
1014 | |||
1015 | value = value->u.object.values [-- value->u.object.length].value; |
||
1016 | continue; |
||
1017 | |||
1018 | case json_string: |
||
1019 | |||
1020 | settings->mem_free (value->u.string.ptr, settings->user_data); |
||
1021 | break; |
||
1022 | |||
1023 | default: |
||
1024 | break; |
||
1025 | }; |
||
1026 | |||
1027 | cur_value = value; |
||
1028 | value = value->parent; |
||
1029 | settings->mem_free (cur_value, settings->user_data); |
||
1030 | } |
||
1031 | } |
||
1032 | |||
1033 | void json_value_free (json_value * value) |
||
1034 | { |
||
1035 | json_settings settings = { 0 }; |
||
1036 | settings.mem_free = default_free; |
||
1037 | json_value_free_ex (&settings, value); |
||
1038 | }>>>>=>=>=>><>><>><>><>=>><>><>><>=>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>>> |
||
1039 |