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