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 "gravity_json.h"
31 #include "gravity_utils.h"
32 #include "gravity_memory.h"
33 #include "gravity_array.h"
34 #include "gravity_config.h"
35
36 #include <inttypes.h>
37 #include <math.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <fcntl.h>
41 #include <ctype.h>
42 #include <assert.h>
43
44 #ifdef _MSC_VER
45 #ifndef _CRT_SECURE_NO_WARNINGS
46 #define _CRT_SECURE_NO_WARNINGS
47 #endif
48 #endif
49
50 // MARK: - JSON Serializer -
51 // Written by Marco Bambini
52
53 #define JSON_MINSIZE 4096
54 #define JSON_NEWLINE "\n"
55 #define JSON_NEWLINE_CHAR '\n'
56 #define JSON_PRETTYLINE " "
57 #define JSON_PRETTYSIZE 4
58 #define JSON_WRITE_COLUMN json_write_raw(json, ":", 1, false, false)
59 #define JSON_WRITE_COMMA json_write_raw(json, ",", 1, false, false);
60
61 #define JSON_POP_CTX(j) marray_pop(j->context)
62 #define JSON_PUSH_CTX(j,x) marray_push(JSON_CONTEXT, j->context, x);
63 #define JSON_CURR_CTX(j) marray_last(j->context)
64
65 #define JSON_ESCAPE(c) do { \
66 new_buffer[j] = '\\'; \
67 new_buffer[j+1] = (c); \
68 j+=2; \
69 } while(0); \
70
71 typedef enum {
72 JSON_CONTEXT_ROOT = 0,
73 JSON_CONTEXT_OBJECT = 1,
74 JSON_CONTEXT_ARRAY = 2
75 } JSON_CONTEXT;
76 typedef marray_t(JSON_CONTEXT) JSON_CONTEXT_R;
77
78 // MARK: -
79
80 struct json_t {
81 char *buffer;
82 size_t blen;
83 size_t bused;
84
85 const char *label;
86 uint32_t options;
87 JSON_CONTEXT_R context;
88 };
89
json_new(void)90 json_t *json_new (void) {
91 json_t *json = mem_alloc(NULL, sizeof(json_t));
92 assert(json);
93
94 json->buffer = mem_alloc(NULL, JSON_MINSIZE);
95 assert(json->buffer);
96
97 json->blen = JSON_MINSIZE;
98 json->bused = 0;
99 json->options = json_opt_none;
100 marray_init(json->context);
101 marray_push(JSON_CONTEXT, json->context, JSON_CONTEXT_ROOT);
102
103 return json;
104 }
105
json_free(json_t * json)106 void json_free (json_t *json) {
107 JSON_CONTEXT context = marray_pop(json->context);
108 if (context != JSON_CONTEXT_ROOT) assert(0);
109
110 marray_destroy(json->context);
111 mem_free(json->buffer);
112 mem_free(json);
113 }
114
115 // MARK: - Private
116
json_write_raw(json_t * json,const char * buffer,size_t len,bool escape,bool is_pretty)117 static void json_write_raw (json_t *json, const char *buffer, size_t len, bool escape, bool is_pretty) {
118 // pretty output disabled in this version
119 is_pretty = false;
120
121 bool pretty_mask = json_option_isset(json, json_opt_prettify);
122 uint32_t ident_count = ((uint32_t) marray_size(json->context)) - 1;
123 size_t prettylen = (is_pretty && pretty_mask) ? (ident_count * JSON_PRETTYSIZE) : 0;
124 size_t escapelen = (escape) ? 2 : 0;
125
126 // check buffer reallocation
127 size_t reqlen = json->bused + len + prettylen + escapelen + JSON_MINSIZE;
128 if (reqlen >= json->blen) {
129 json->buffer = mem_realloc(NULL, json->buffer, json->blen + reqlen);
130 assert(json->buffer);
131 json->blen += reqlen;
132 }
133
134 if (is_pretty && pretty_mask) {
135 for (uint32_t i=0; i<ident_count; ++i) {
136 memcpy(json->buffer+json->bused, JSON_PRETTYLINE, JSON_PRETTYSIZE);
137 json->bused += JSON_PRETTYSIZE;
138 }
139 }
140
141 if (escape) {
142 memcpy(json->buffer+json->bused, "\"", 1);
143 json->bused += 1;
144 }
145
146 memcpy(json->buffer+json->bused, buffer, len);
147 json->bused += len;
148
149 if (escape) {
150 memcpy(json->buffer+json->bused, "\"", 1);
151 json->bused += 1;
152 }
153 }
154
json_write_escaped(json_t * json,const char * buffer,size_t len,bool escape,bool is_pretty)155 static void json_write_escaped (json_t *json, const char *buffer, size_t len, bool escape, bool is_pretty) {
156 if (!len) {
157 json_write_raw(json, "", 0, escape, is_pretty);
158 return;
159 }
160
161 char *new_buffer = mem_alloc(NULL, len*2);
162 size_t j = 0;
163 assert(new_buffer);
164
165 for (size_t i=0; i<len; ++i) {
166 char c = buffer[i];
167 switch (c) {
168 case '"' : JSON_ESCAPE ('\"'); continue;
169 case '\\': JSON_ESCAPE ('\\'); continue;
170 case '\b': JSON_ESCAPE ('b'); continue;
171 case '\f': JSON_ESCAPE ('f'); continue;
172 case '\n': JSON_ESCAPE ('n'); continue;
173 case '\r': JSON_ESCAPE ('r'); continue;
174 case '\t': JSON_ESCAPE ('t'); continue;
175
176 default: new_buffer[j] = c; ++j;break;
177 };
178 }
179
180 json_write_raw(json, new_buffer, j, escape, is_pretty);
181 mem_free(new_buffer);
182 }
183
json_check_comma(json_t * json)184 static void json_check_comma (json_t *json) {
185 if (json_option_isset(json, json_opt_need_comma)) {
186 JSON_WRITE_COMMA;
187 } else {
188 json_set_option(json, json_opt_need_comma);
189 }
190 }
191
192 // MARK: - Public
193
json_begin_object(json_t * json,const char * key)194 void json_begin_object (json_t *json, const char *key) {
195 json_check_comma(json);
196
197 // ignore given key if not inside an object
198 if (JSON_CURR_CTX(json) != JSON_CONTEXT_OBJECT) {
199 key = NULL;
200 }
201
202 if (key) {
203 json_write_raw (json, key, strlen(key), true, true);
204 JSON_WRITE_COLUMN;
205 }
206
207 JSON_PUSH_CTX(json, JSON_CONTEXT_OBJECT);
208 json_write_raw(json, "{", 1, false, (key == NULL));
209
210 json_clear_option(json, json_opt_need_comma);
211 }
212
json_end_object(json_t * json)213 void json_end_object (json_t *json) {
214 JSON_POP_CTX(json);
215
216 json_set_option(json, json_opt_need_comma);
217 json_write_raw(json, "}", 1, false, true);
218 }
219
json_begin_array(json_t * json,const char * key)220 void json_begin_array (json_t *json, const char *key) {
221 json_check_comma(json);
222
223 // ignore given key if not inside an object
224 if (JSON_CURR_CTX(json) != JSON_CONTEXT_OBJECT) {
225 key = NULL;
226 }
227
228 if (key) {
229 json_write_raw (json, key, strlen(key), true, true);
230 JSON_WRITE_COLUMN;
231 }
232
233 JSON_PUSH_CTX(json, JSON_CONTEXT_ARRAY);
234 json_write_raw(json, "[", 1, false, (key == NULL));
235
236 json_clear_option(json, json_opt_need_comma);
237 }
238
json_end_array(json_t * json)239 void json_end_array (json_t *json) {
240 JSON_POP_CTX(json);
241
242 json_set_option(json, json_opt_need_comma);
243 json_write_raw(json, "]", 1, false, true);
244 }
245
json_add_string(json_t * json,const char * key,const char * value,size_t len)246 void json_add_string (json_t *json, const char *key, const char *value, size_t len) {
247 json_check_comma(json);
248
249 if (!value) {
250 json_add_null(json, key);
251 return;
252 }
253
254 if (key) {
255 json_write_raw (json, key, strlen(key), true, true);
256 JSON_WRITE_COLUMN;
257 }
258
259 // check if string value needs to be escaped
260 bool write_escaped = false;
261 for (size_t i=0; i<len; ++i) {
262 if (value[i] == '"') {write_escaped = true; break;}
263 }
264 if (len == 0) write_escaped = true;
265
266 if (write_escaped)
267 json_write_escaped(json, value, len, true, (key == NULL));
268 else
269 json_write_raw(json, value, len, true, (key == NULL));
270 }
271
json_add_cstring(json_t * json,const char * key,const char * value)272 void json_add_cstring (json_t *json, const char *key, const char *value) {
273 json_add_string(json, key, value, (value) ? strlen(value) : 0);
274 }
275
json_add_int(json_t * json,const char * key,int64_t value)276 void json_add_int (json_t *json, const char *key, int64_t value) {
277 json_check_comma(json);
278
279 char buffer[512];
280 size_t len = snprintf(buffer, sizeof(buffer), "%" PRId64, value);
281
282 if (key) {
283 json_write_raw (json, key, strlen(key), true, true);
284 JSON_WRITE_COLUMN;
285 }
286
287 json_write_raw(json, buffer, len, false, (key == NULL));
288 }
289
json_add_double(json_t * json,const char * key,double value)290 void json_add_double (json_t *json, const char *key, double value) {
291 json_check_comma(json);
292
293 char buffer[512];
294 // was %g but we don't like scientific notation nor the missing .0 in case of float number with no decimals
295 size_t len = snprintf(buffer, sizeof(buffer), "%f", value);
296
297 if (key) {
298 json_write_raw (json, key, strlen(key), true, true);
299 JSON_WRITE_COLUMN;
300 }
301
302 json_write_raw(json, buffer, len, false, (key == NULL));
303 }
304
json_add_bool(json_t * json,const char * key,bool bvalue)305 void json_add_bool (json_t *json, const char *key, bool bvalue) {
306 json_check_comma(json);
307
308 const char *value = (bvalue) ? "true" : "false";
309
310 if (key) {
311 json_write_raw (json, key, strlen(key), true, true);
312 JSON_WRITE_COLUMN;
313 }
314
315 json_write_raw(json, value, strlen(value), false, (key == NULL));
316 }
317
json_add_null(json_t * json,const char * key)318 void json_add_null (json_t *json, const char *key) {
319 json_check_comma (json);
320
321 if (key) {
322 json_write_raw (json, key, strlen(key), true, true);
323 JSON_WRITE_COLUMN;
324 }
325
326 json_write_raw(json, "null", 4, false, (key == NULL));
327 }
328
json_set_label(json_t * json,const char * key)329 void json_set_label (json_t *json, const char *key) {
330 if (JSON_CURR_CTX(json) != JSON_CONTEXT_OBJECT) return;
331 json->label = key;
332 }
333
json_get_label(json_t * json,const char * key)334 const char *json_get_label (json_t *json, const char *key) {
335 if (JSON_CURR_CTX(json) != JSON_CONTEXT_OBJECT) return NULL;
336
337 if (json->label) {
338 const char *result = json->label;
339 json->label = NULL;
340 return result;
341 }
342
343 if (key) return key;
344 assert(0);
345 return NULL;
346 }
347
348 // MARK: - Buffer
349
json_buffer(json_t * json,size_t * len)350 char *json_buffer (json_t *json, size_t *len) {
351 assert(json->buffer);
352 if (len) *len = json->bused;
353 return json->buffer;
354 }
355
json_write_file(json_t * json,const char * path)356 bool json_write_file (json_t *json, const char *path) {
357 return file_write(path, json->buffer, json->bused);
358 }
359
360 // MARK: - Options
361
json_get_options(json_t * json)362 uint32_t json_get_options (json_t *json) {
363 return json->options;
364 }
365
json_set_option(json_t * json,json_opt_mask option_value)366 void json_set_option (json_t *json, json_opt_mask option_value) {
367 json->options |= option_value;
368 }
369
json_option_isset(json_t * json,json_opt_mask option_value)370 bool json_option_isset (json_t *json, json_opt_mask option_value) {
371 return (json->options & option_value);
372 }
373
json_clear_option(json_t * json,json_opt_mask option_value)374 void json_clear_option (json_t *json, json_opt_mask option_value) {
375 json->options &= ~option_value;
376 }
377
378 #undef JSON_MINSIZE
379 #undef JSON_NEWLINE
380 #undef JSON_NEWLINE_CHAR
381 #undef JSON_PRETTYLINE
382 #undef JSON_PRETTYSIZE
383 #undef JSON_WRITE_SEP
384 #undef JSON_TERM_FIELD
385
386 // MARK: - JSON Parser -
387 // Written by https://github.com/udp/json-parser
388
389 const struct _json_value json_value_none;
390 typedef unsigned int json_uchar;
391
hex_value(json_char c)392 static unsigned char hex_value (json_char c)
393 {
394 if (isdigit(c))
395 return c - '0';
396
397 switch (c) {
398 case 'a': case 'A': return 0x0A;
399 case 'b': case 'B': return 0x0B;
400 case 'c': case 'C': return 0x0C;
401 case 'd': case 'D': return 0x0D;
402 case 'e': case 'E': return 0x0E;
403 case 'f': case 'F': return 0x0F;
404 default: return 0xFF;
405 }
406 }
407
408 typedef struct
409 {
410 unsigned long used_memory;
411
412 unsigned int uint_max;
413 unsigned long ulong_max;
414
415 json_settings settings;
416 int first_pass;
417
418 const json_char * ptr;
419 unsigned int cur_line, cur_col;
420
421 } json_state;
422
default_alloc(size_t size,int zero,void * user_data)423 static void * default_alloc (size_t size, int zero, void * user_data)
424 {
425 #pragma unused(zero, user_data)
426 return mem_alloc(NULL, size);
427 //return zero ? calloc (1, size) : malloc (size);
428 }
429
default_free(void * ptr,void * user_data)430 static void default_free (void * ptr, void * user_data)
431 {
432 #pragma unused(user_data)
433 mem_free(ptr);
434 //free (ptr);
435 }
436
json_alloc(json_state * state,unsigned long size,int zero)437 static void * json_alloc (json_state * state, unsigned long size, int zero)
438 {
439 if ((state->ulong_max - state->used_memory) < size)
440 return 0;
441
442 if (state->settings.max_memory
443 && (state->used_memory += size) > state->settings.max_memory)
444 {
445 return 0;
446 }
447
448 return state->settings.memory_alloc (size, zero, state->settings.user_data);
449 }
450
new_value(json_state * state,json_value ** top,json_value ** root,json_value ** alloc,json_type type)451 static int new_value (json_state * state,
452 json_value ** top, json_value ** root, json_value ** alloc,
453 json_type type)
454 {
455 json_value * value;
456 int values_size;
457
458 if (!state->first_pass)
459 {
460 value = *top = *alloc;
461 *alloc = (*alloc)->_reserved.next_alloc;
462
463 if (!*root)
464 *root = value;
465
466 switch (value->type)
467 {
468 case json_array:
469
470 if (value->u.array.length == 0)
471 break;
472
473 if (! (value->u.array.values = (json_value **) json_alloc
474 (state, value->u.array.length * sizeof (json_value *), 0)) )
475 {
476 return 0;
477 }
478
479 value->u.array.length = 0;
480 break;
481
482 case json_object:
483
484 if (value->u.object.length == 0)
485 break;
486
487 values_size = sizeof (*value->u.object.values) * value->u.object.length;
488
489 if (! (value->u.object.values = (json_object_entry *) json_alloc
490 (state, values_size + ((unsigned long) value->u.object.values), 0)) )
491 {
492 return 0;
493 }
494
495 value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
496
497 value->u.object.length = 0;
498 break;
499
500 case json_string:
501
502 if (! (value->u.string.ptr = (json_char *) json_alloc
503 (state, (value->u.string.length + 1) * sizeof (json_char), 0)) )
504 {
505 return 0;
506 }
507
508 value->u.string.length = 0;
509 break;
510
511 default:
512 break;
513 };
514
515 return 1;
516 }
517
518 if (! (value = (json_value *) json_alloc
519 (state, (unsigned long)(sizeof (json_value) + state->settings.value_extra), 1)))
520 {
521 return 0;
522 }
523
524 if (!*root)
525 *root = value;
526
527 value->type = type;
528 value->parent = *top;
529
530 #ifdef JSON_TRACK_SOURCE
531 value->line = state->cur_line;
532 value->col = state->cur_col;
533 #endif
534
535 if (*alloc)
536 (*alloc)->_reserved.next_alloc = value;
537
538 *alloc = *top = value;
539
540 return 1;
541 }
542
543 #define whitespace \
544 case '\n': ++ state.cur_line; state.cur_col = 0; \
545 case ' ': case '\t': case '\r'
546
547 #define string_add(b) \
548 do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0);
549
550 #define line_and_col \
551 state.cur_line, state.cur_col
552
553 static const long
554 flag_next = 1 << 0,
555 flag_reproc = 1 << 1,
556 flag_need_comma = 1 << 2,
557 flag_seek_value = 1 << 3,
558 flag_escaped = 1 << 4,
559 flag_string = 1 << 5,
560 flag_need_colon = 1 << 6,
561 flag_done = 1 << 7,
562 flag_num_negative = 1 << 8,
563 flag_num_zero = 1 << 9,
564 flag_num_e = 1 << 10,
565 flag_num_e_got_sign = 1 << 11,
566 flag_num_e_negative = 1 << 12,
567 flag_line_comment = 1 << 13,
568 flag_block_comment = 1 << 14;
569
json_parse_ex(json_settings * settings,const json_char * json,size_t length,char * error_buf)570 json_value * json_parse_ex (json_settings * settings,
571 const json_char * json,
572 size_t length,
573 char * error_buf)
574 {
575 json_char error [json_error_max];
576 const json_char * end;
577 json_value *top, *root = NULL, * alloc = 0;
578 json_state state = EMPTY_STATE_STRUCT;
579 long flags;
580 long num_digits = 0, num_e = 0;
581 json_int_t num_fraction = 0;
582
583 /* Skip UTF-8 BOM
584 */
585 if (length >= 3 && ((unsigned char) json [0]) == 0xEF
586 && ((unsigned char) json [1]) == 0xBB
587 && ((unsigned char) json [2]) == 0xBF)
588 {
589 json += 3;
590 length -= 3;
591 }
592
593 error[0] = '\0';
594 end = (json + length);
595
596 memcpy (&state.settings, settings, sizeof (json_settings));
597
598 if (!state.settings.memory_alloc)
599 state.settings.memory_alloc = default_alloc;
600
601 if (!state.settings.memory_free)
602 state.settings.memory_free = default_free;
603
604 memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
605 memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
606
607 state.uint_max -= 8; /* limit of how much can be added before next check */
608 state.ulong_max -= 8;
609
610 for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)
611 {
612 json_uchar uchar;
613 unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
614 json_char * string = 0;
615 unsigned int string_length = 0;
616
617 top = root = 0;
618 flags = flag_seek_value;
619
620 state.cur_line = 1;
621
622 for (state.ptr = json ;; ++ state.ptr)
623 {
624 json_char b = (state.ptr == end ? 0 : *state.ptr);
625
626 if (flags & flag_string)
627 {
628 if (!b)
629 { sprintf (error, "Unexpected EOF in string (at %d:%d)", line_and_col);
630 goto e_failed;
631 }
632
633 if (string_length > state.uint_max)
634 goto e_overflow;
635
636 if (flags & flag_escaped)
637 {
638 flags &= ~ flag_escaped;
639
640 switch (b)
641 {
642 case 'b': string_add ('\b'); break;
643 case 'f': string_add ('\f'); break;
644 case 'n': string_add ('\n'); break;
645 case 'r': string_add ('\r'); break;
646 case 't': string_add ('\t'); break;
647 case 'u':
648
649 if (end - state.ptr < 4 ||
650 (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
651 (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
652 (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
653 (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
654 {
655 sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
656 goto e_failed;
657 }
658
659 uc_b1 = (uc_b1 << 4) | uc_b2;
660 uc_b2 = (uc_b3 << 4) | uc_b4;
661 uchar = (uc_b1 << 8) | uc_b2;
662
663 if ((uchar & 0xF800) == 0xD800) {
664 json_uchar uchar2;
665
666 if (end - state.ptr < 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' ||
667 (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
668 (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
669 (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
670 (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
671 {
672 sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
673 goto e_failed;
674 }
675
676 uc_b1 = (uc_b1 << 4) | uc_b2;
677 uc_b2 = (uc_b3 << 4) | uc_b4;
678 uchar2 = (uc_b1 << 8) | uc_b2;
679
680 uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF);
681 }
682
683 if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F))
684 {
685 string_add ((json_char) uchar);
686 break;
687 }
688
689 if (uchar <= 0x7FF)
690 {
691 if (state.first_pass)
692 string_length += 2;
693 else
694 { string [string_length ++] = 0xC0 | (uchar >> 6);
695 string [string_length ++] = 0x80 | (uchar & 0x3F);
696 }
697
698 break;
699 }
700
701 if (uchar <= 0xFFFF) {
702 if (state.first_pass)
703 string_length += 3;
704 else
705 { string [string_length ++] = 0xE0 | (uchar >> 12);
706 string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
707 string [string_length ++] = 0x80 | (uchar & 0x3F);
708 }
709
710 break;
711 }
712
713 if (state.first_pass)
714 string_length += 4;
715 else
716 { string [string_length ++] = 0xF0 | (uchar >> 18);
717 string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F);
718 string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
719 string [string_length ++] = 0x80 | (uchar & 0x3F);
720 }
721
722 break;
723
724 default:
725 string_add (b);
726 };
727
728 continue;
729 }
730
731 if (b == '\\')
732 {
733 flags |= flag_escaped;
734 continue;
735 }
736
737 if (b == '"')
738 {
739 if (!state.first_pass)
740 string [string_length] = 0;
741
742 flags &= ~ flag_string;
743 string = 0;
744
745 switch (top->type)
746 {
747 case json_string:
748
749 top->u.string.length = string_length;
750 flags |= flag_next;
751
752 break;
753
754 case json_object:
755
756 if (state.first_pass)
757 (*(json_char **) &top->u.object.values) += string_length + 1;
758 else
759 {
760 top->u.object.values [top->u.object.length].name
761 = (json_char *) top->_reserved.object_mem;
762
763 top->u.object.values [top->u.object.length].name_length
764 = string_length;
765
766 (*(json_char **) &top->_reserved.object_mem) += string_length + 1;
767 }
768
769 flags |= flag_seek_value | flag_need_colon;
770 continue;
771
772 default:
773 break;
774 };
775 }
776 else
777 {
778 string_add (b);
779 continue;
780 }
781 }
782
783 if (state.settings.settings & json_enable_comments)
784 {
785 if (flags & (flag_line_comment | flag_block_comment))
786 {
787 if (flags & flag_line_comment)
788 {
789 if (b == '\r' || b == '\n' || !b)
790 {
791 flags &= ~ flag_line_comment;
792 -- state.ptr; /* so null can be reproc'd */
793 }
794
795 continue;
796 }
797
798 if (flags & flag_block_comment)
799 {
800 if (!b)
801 { sprintf (error, "%d:%d: Unexpected EOF in block comment", line_and_col);
802 goto e_failed;
803 }
804
805 if (b == '*' && state.ptr < (end - 1) && state.ptr [1] == '/')
806 {
807 flags &= ~ flag_block_comment;
808 ++ state.ptr; /* skip closing sequence */
809 }
810
811 continue;
812 }
813 }
814 else if (b == '/')
815 {
816 if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
817 { sprintf (error, "%d:%d: Comment not allowed here", line_and_col);
818 goto e_failed;
819 }
820
821 if (++ state.ptr == end)
822 { sprintf (error, "%d:%d: EOF unexpected", line_and_col);
823 goto e_failed;
824 }
825
826 switch (b = *state.ptr)
827 {
828 case '/':
829 flags |= flag_line_comment;
830 continue;
831
832 case '*':
833 flags |= flag_block_comment;
834 continue;
835
836 default:
837 sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", line_and_col, b);
838 goto e_failed;
839 };
840 }
841 }
842
843 if (flags & flag_done)
844 {
845 if (!b)
846 break;
847
848 switch (b)
849 {
850 whitespace:
851 continue;
852
853 default:
854
855 sprintf (error, "%d:%d: Trailing garbage: `%c`",
856 state.cur_line, state.cur_col, b);
857
858 goto e_failed;
859 };
860 }
861
862 if (flags & flag_seek_value)
863 {
864 switch (b)
865 {
866 whitespace:
867 continue;
868
869 case ']':
870
871 if (top && top->type == json_array)
872 flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
873 else
874 { sprintf (error, "%d:%d: Unexpected ]", line_and_col);
875 goto e_failed;
876 }
877
878 break;
879
880 default:
881
882 if (flags & flag_need_comma)
883 {
884 if (b == ',')
885 { flags &= ~ flag_need_comma;
886 continue;
887 }
888 else
889 {
890 sprintf (error, "%d:%d: Expected , before %c",
891 state.cur_line, state.cur_col, b);
892
893 goto e_failed;
894 }
895 }
896
897 if (flags & flag_need_colon)
898 {
899 if (b == ':')
900 { flags &= ~ flag_need_colon;
901 continue;
902 }
903 else
904 {
905 sprintf (error, "%d:%d: Expected : before %c",
906 state.cur_line, state.cur_col, b);
907
908 goto e_failed;
909 }
910 }
911
912 flags &= ~ flag_seek_value;
913
914 switch (b)
915 {
916 case '{':
917
918 if (!new_value (&state, &top, &root, &alloc, json_object))
919 goto e_alloc_failure;
920
921 continue;
922
923 case '[':
924
925 if (!new_value (&state, &top, &root, &alloc, json_array))
926 goto e_alloc_failure;
927
928 flags |= flag_seek_value;
929 continue;
930
931 case '"':
932
933 if (!new_value (&state, &top, &root, &alloc, json_string))
934 goto e_alloc_failure;
935
936 flags |= flag_string;
937
938 string = top->u.string.ptr;
939 string_length = 0;
940
941 continue;
942
943 case 't':
944
945 if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||
946 *(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')
947 {
948 goto e_unknown_value;
949 }
950
951 if (!new_value (&state, &top, &root, &alloc, json_boolean))
952 goto e_alloc_failure;
953
954 top->u.boolean = 1;
955
956 flags |= flag_next;
957 break;
958
959 case 'f':
960
961 if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||
962 *(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||
963 *(++ state.ptr) != 'e')
964 {
965 goto e_unknown_value;
966 }
967
968 if (!new_value (&state, &top, &root, &alloc, json_boolean))
969 goto e_alloc_failure;
970
971 flags |= flag_next;
972 break;
973
974 case 'n':
975
976 if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||
977 *(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')
978 {
979 goto e_unknown_value;
980 }
981
982 if (!new_value (&state, &top, &root, &alloc, json_null))
983 goto e_alloc_failure;
984
985 flags |= flag_next;
986 break;
987
988 default:
989
990 if (isdigit (b) || b == '-')
991 {
992 if (!new_value (&state, &top, &root, &alloc, json_integer))
993 goto e_alloc_failure;
994
995 if (!state.first_pass)
996 {
997 while (isdigit (b) || b == '+' || b == '-'
998 || b == 'e' || b == 'E' || b == '.')
999 {
1000 if ( (++ state.ptr) == end)
1001 {
1002 b = 0;
1003 break;
1004 }
1005
1006 b = *state.ptr;
1007 }
1008
1009 flags |= flag_next | flag_reproc;
1010 break;
1011 }
1012
1013 flags &= ~ (flag_num_negative | flag_num_e |
1014 flag_num_e_got_sign | flag_num_e_negative |
1015 flag_num_zero);
1016
1017 num_digits = 0;
1018 num_fraction = 0;
1019 num_e = 0;
1020
1021 if (b != '-')
1022 {
1023 flags |= flag_reproc;
1024 break;
1025 }
1026
1027 flags |= flag_num_negative;
1028 continue;
1029 }
1030 else
1031 { sprintf (error, "%d:%d: Unexpected %c when seeking value", line_and_col, b);
1032 goto e_failed;
1033 }
1034 };
1035 };
1036 }
1037 else
1038 {
1039 switch (top->type)
1040 {
1041 case json_object:
1042
1043 switch (b)
1044 {
1045 whitespace:
1046 continue;
1047
1048 case '"':
1049
1050 if (flags & flag_need_comma)
1051 { sprintf (error, "%d:%d: Expected , before \"", line_and_col);
1052 goto e_failed;
1053 }
1054
1055 flags |= flag_string;
1056
1057 string = (json_char *) top->_reserved.object_mem;
1058 string_length = 0;
1059
1060 break;
1061
1062 case '}':
1063
1064 flags = (flags & ~ flag_need_comma) | flag_next;
1065 break;
1066
1067 case ',':
1068
1069 if (flags & flag_need_comma)
1070 {
1071 flags &= ~ flag_need_comma;
1072 break;
1073 }
1074
1075 default:
1076 sprintf (error, "%d:%d: Unexpected `%c` in object", line_and_col, b);
1077 goto e_failed;
1078 };
1079
1080 break;
1081
1082 case json_integer:
1083 case json_double:
1084
1085 if (isdigit (b))
1086 {
1087 ++ num_digits;
1088
1089 if (top->type == json_integer || flags & flag_num_e)
1090 {
1091 if (! (flags & flag_num_e))
1092 {
1093 if (flags & flag_num_zero)
1094 { sprintf (error, "%d:%d: Unexpected `0` before `%c`", line_and_col, b);
1095 goto e_failed;
1096 }
1097
1098 if (num_digits == 1 && b == '0')
1099 flags |= flag_num_zero;
1100 }
1101 else
1102 {
1103 flags |= flag_num_e_got_sign;
1104 num_e = (num_e * 10) + (b - '0');
1105 continue;
1106 }
1107
1108 top->u.integer = (top->u.integer * 10) + (b - '0');
1109 continue;
1110 }
1111
1112 num_fraction = (num_fraction * 10) + (b - '0');
1113 continue;
1114 }
1115
1116 if (b == '+' || b == '-')
1117 {
1118 if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign))
1119 {
1120 flags |= flag_num_e_got_sign;
1121
1122 if (b == '-')
1123 flags |= flag_num_e_negative;
1124
1125 continue;
1126 }
1127 }
1128 else if (b == '.' && top->type == json_integer)
1129 {
1130 if (!num_digits)
1131 { sprintf (error, "%d:%d: Expected digit before `.`", line_and_col);
1132 goto e_failed;
1133 }
1134
1135 top->type = json_double;
1136 top->u.dbl = (double) top->u.integer;
1137
1138 num_digits = 0;
1139 continue;
1140 }
1141
1142 if (! (flags & flag_num_e))
1143 {
1144 if (top->type == json_double)
1145 {
1146 if (!num_digits)
1147 { sprintf (error, "%d:%d: Expected digit after `.`", line_and_col);
1148 goto e_failed;
1149 }
1150
1151 top->u.dbl += ((double) num_fraction) / (pow (10.0, (double) num_digits));
1152 }
1153
1154 if (b == 'e' || b == 'E')
1155 {
1156 flags |= flag_num_e;
1157
1158 if (top->type == json_integer)
1159 {
1160 top->type = json_double;
1161 top->u.dbl = (double) top->u.integer;
1162 }
1163
1164 num_digits = 0;
1165 flags &= ~ flag_num_zero;
1166
1167 continue;
1168 }
1169 }
1170 else
1171 {
1172 if (!num_digits)
1173 { sprintf (error, "%d:%d: Expected digit after `e`", line_and_col);
1174 goto e_failed;
1175 }
1176
1177 top->u.dbl *= pow (10.0, (double)
1178 (flags & flag_num_e_negative ? - num_e : num_e));
1179 }
1180
1181 if (flags & flag_num_negative)
1182 {
1183 if (top->type == json_integer)
1184 top->u.integer = - top->u.integer;
1185 else
1186 top->u.dbl = - top->u.dbl;
1187 }
1188
1189 flags |= flag_next | flag_reproc;
1190 break;
1191
1192 default:
1193 break;
1194 };
1195 }
1196
1197 if (flags & flag_reproc)
1198 {
1199 flags &= ~ flag_reproc;
1200 -- state.ptr;
1201 }
1202
1203 if (flags & flag_next)
1204 {
1205 flags = (flags & ~ flag_next) | flag_need_comma;
1206
1207 if (!top->parent)
1208 {
1209 /* root value done */
1210
1211 flags |= flag_done;
1212 continue;
1213 }
1214
1215 if (top->parent->type == json_array)
1216 flags |= flag_seek_value;
1217
1218 if (!state.first_pass)
1219 {
1220 json_value * parent = top->parent;
1221
1222 switch (parent->type)
1223 {
1224 case json_object:
1225
1226 parent->u.object.values
1227 [parent->u.object.length].value = top;
1228
1229 break;
1230
1231 case json_array:
1232
1233 parent->u.array.values
1234 [parent->u.array.length] = top;
1235
1236 break;
1237
1238 default:
1239 break;
1240 };
1241 }
1242
1243 if ( (++ top->parent->u.array.length) > state.uint_max)
1244 goto e_overflow;
1245
1246 top = top->parent;
1247
1248 continue;
1249 }
1250 }
1251
1252 alloc = root;
1253 }
1254
1255 return root;
1256
1257 e_unknown_value:
1258
1259 sprintf (error, "%d:%d: Unknown value", line_and_col);
1260 goto e_failed;
1261
1262 e_alloc_failure:
1263
1264 strcpy (error, "Memory allocation failure");
1265 goto e_failed;
1266
1267 e_overflow:
1268
1269 sprintf (error, "%d:%d: Too long (caught overflow)", line_and_col);
1270 goto e_failed;
1271
1272 e_failed:
1273
1274 if (error_buf)
1275 {
1276 if (*error)
1277 strcpy (error_buf, error);
1278 else
1279 strcpy (error_buf, "Unknown error");
1280 }
1281
1282 if (state.first_pass)
1283 alloc = root;
1284
1285 while (alloc)
1286 {
1287 top = alloc->_reserved.next_alloc;
1288 state.settings.memory_free (alloc, state.settings.user_data);
1289 alloc = top;
1290 }
1291
1292 if (!state.first_pass)
1293 json_value_free_ex (&state.settings, root);
1294
1295 return 0;
1296 }
1297
json_parse(const json_char * json,size_t length)1298 json_value * json_parse (const json_char * json, size_t length)
1299 {
1300 json_settings settings = EMPTY_SETTINGS_STRUCT;
1301 return json_parse_ex (&settings, json, length, 0);
1302 }
1303
json_value_free_ex(json_settings * settings,json_value * value)1304 void json_value_free_ex (json_settings * settings, json_value * value)
1305 {
1306 json_value * cur_value;
1307
1308 if (!value)
1309 return;
1310
1311 value->parent = 0;
1312
1313 while (value)
1314 {
1315 switch (value->type)
1316 {
1317 case json_array:
1318
1319 if (!value->u.array.length)
1320 {
1321 if (value->u.array.values) settings->memory_free (value->u.array.values, settings->user_data);
1322 break;
1323 }
1324
1325 value = value->u.array.values [-- value->u.array.length];
1326 continue;
1327
1328 case json_object:
1329
1330 if (!value->u.object.length)
1331 {
1332 settings->memory_free (value->u.object.values, settings->user_data);
1333 break;
1334 }
1335
1336 value = value->u.object.values [-- value->u.object.length].value;
1337 continue;
1338
1339 case json_string:
1340
1341 settings->memory_free (value->u.string.ptr, settings->user_data);
1342 break;
1343
1344 default:
1345 break;
1346 };
1347
1348 cur_value = value;
1349 value = value->parent;
1350 settings->memory_free (cur_value, settings->user_data);
1351 }
1352 }
1353
json_value_free(json_value * value)1354 void json_value_free (json_value * value)
1355 {
1356 json_settings settings = EMPTY_SETTINGS_STRUCT;
1357 settings.memory_free = default_free;
1358 json_value_free_ex (&settings, value);
1359 }
1360