fizx-ordered_json 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +29 -0
- data/CHANGELOG +22 -0
- data/README +4 -0
- data/Rakefile +35 -0
- data/ext/Makefile +149 -0
- data/ext/json-c-0.8/AUTHORS +2 -0
- data/ext/json-c-0.8/COPYING +19 -0
- data/ext/json-c-0.8/ChangeLog +73 -0
- data/ext/json-c-0.8/INSTALL +229 -0
- data/ext/json-c-0.8/Makefile.am +43 -0
- data/ext/json-c-0.8/Makefile.in +734 -0
- data/ext/json-c-0.8/NEWS +1 -0
- data/ext/json-c-0.8/README +20 -0
- data/ext/json-c-0.8/aclocal.m4 +8794 -0
- data/ext/json-c-0.8/arraylist.c +93 -0
- data/ext/json-c-0.8/arraylist.h +45 -0
- data/ext/json-c-0.8/bits.h +27 -0
- data/ext/json-c-0.8/config.guess +1526 -0
- data/ext/json-c-0.8/config.h.in +121 -0
- data/ext/json-c-0.8/config.sub +1658 -0
- data/ext/json-c-0.8/configure +14243 -0
- data/ext/json-c-0.8/configure.in +33 -0
- data/ext/json-c-0.8/debug.c +98 -0
- data/ext/json-c-0.8/debug.h +42 -0
- data/ext/json-c-0.8/depcomp +530 -0
- data/ext/json-c-0.8/doc/html/annotated.html +40 -0
- data/ext/json-c-0.8/doc/html/arraylist_8h.html +234 -0
- data/ext/json-c-0.8/doc/html/bits_8h.html +144 -0
- data/ext/json-c-0.8/doc/html/config_8h.html +606 -0
- data/ext/json-c-0.8/doc/html/debug_8h.html +386 -0
- data/ext/json-c-0.8/doc/html/doxygen.css +473 -0
- data/ext/json-c-0.8/doc/html/doxygen.png +0 -0
- data/ext/json-c-0.8/doc/html/files.html +42 -0
- data/ext/json-c-0.8/doc/html/functions.html +206 -0
- data/ext/json-c-0.8/doc/html/functions_vars.html +206 -0
- data/ext/json-c-0.8/doc/html/globals.html +445 -0
- data/ext/json-c-0.8/doc/html/globals_defs.html +200 -0
- data/ext/json-c-0.8/doc/html/globals_enum.html +50 -0
- data/ext/json-c-0.8/doc/html/globals_eval.html +135 -0
- data/ext/json-c-0.8/doc/html/globals_func.html +194 -0
- data/ext/json-c-0.8/doc/html/globals_type.html +58 -0
- data/ext/json-c-0.8/doc/html/globals_vars.html +50 -0
- data/ext/json-c-0.8/doc/html/index.html +25 -0
- data/ext/json-c-0.8/doc/html/json_8h.html +26 -0
- data/ext/json-c-0.8/doc/html/json__object_8h.html +1042 -0
- data/ext/json-c-0.8/doc/html/json__object__private_8h.html +69 -0
- data/ext/json-c-0.8/doc/html/json__tokener_8h.html +360 -0
- data/ext/json-c-0.8/doc/html/json__util_8h.html +100 -0
- data/ext/json-c-0.8/doc/html/linkhash_8h.html +734 -0
- data/ext/json-c-0.8/doc/html/printbuf_8h.html +171 -0
- data/ext/json-c-0.8/doc/html/structarray__list.html +104 -0
- data/ext/json-c-0.8/doc/html/structjson__object.html +141 -0
- data/ext/json-c-0.8/doc/html/structjson__object__iter.html +87 -0
- data/ext/json-c-0.8/doc/html/structjson__tokener.html +206 -0
- data/ext/json-c-0.8/doc/html/structjson__tokener__srec.html +104 -0
- data/ext/json-c-0.8/doc/html/structlh__entry.html +105 -0
- data/ext/json-c-0.8/doc/html/structlh__table.html +275 -0
- data/ext/json-c-0.8/doc/html/structprintbuf.html +87 -0
- data/ext/json-c-0.8/doc/html/tab_b.gif +0 -0
- data/ext/json-c-0.8/doc/html/tab_l.gif +0 -0
- data/ext/json-c-0.8/doc/html/tab_r.gif +0 -0
- data/ext/json-c-0.8/doc/html/tabs.css +102 -0
- data/ext/json-c-0.8/doc/html/unionjson__object_1_1data.html +140 -0
- data/ext/json-c-0.8/install-sh +519 -0
- data/ext/json-c-0.8/json.h +31 -0
- data/ext/json-c-0.8/json.pc.in +11 -0
- data/ext/json-c-0.8/json_object.c +511 -0
- data/ext/json-c-0.8/json_object.h +310 -0
- data/ext/json-c-0.8/json_object_private.h +44 -0
- data/ext/json-c-0.8/json_tokener.c +517 -0
- data/ext/json-c-0.8/json_tokener.h +90 -0
- data/ext/json-c-0.8/json_util.c +122 -0
- data/ext/json-c-0.8/json_util.h +23 -0
- data/ext/json-c-0.8/linkhash.c +218 -0
- data/ext/json-c-0.8/linkhash.h +264 -0
- data/ext/json-c-0.8/ltmain.sh +7880 -0
- data/ext/json-c-0.8/missing +360 -0
- data/ext/json-c-0.8/printbuf.c +145 -0
- data/ext/json-c-0.8/printbuf.h +38 -0
- data/ext/json-c-0.8/test1.c +164 -0
- data/ext/json-c-0.8/test2.c +20 -0
- data/ext/json-c-0.8/test3.c +22 -0
- data/ext/ordered_json_c.c +199 -0
- data/lib/ordered_json.rb +26 -0
- data/ordered_json.gemspec +102 -0
- data/test/crashing_example.rb +1 -0
- data/test/ordered_json_test.rb +86 -0
- data/test/pretty.json +11 -0
- metadata +91 -50
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
|
|
5
|
+
* Michael Clark <michael@metaparadigm.com>
|
|
6
|
+
*
|
|
7
|
+
* This library is free software; you can redistribute it and/or modify
|
|
8
|
+
* it under the terms of the MIT license. See COPYING for details.
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
#include "config.h"
|
|
13
|
+
|
|
14
|
+
#include <stdio.h>
|
|
15
|
+
#include <stdlib.h>
|
|
16
|
+
#include <stddef.h>
|
|
17
|
+
#include <ctype.h>
|
|
18
|
+
#include <string.h>
|
|
19
|
+
|
|
20
|
+
#include "bits.h"
|
|
21
|
+
#include "debug.h"
|
|
22
|
+
#include "printbuf.h"
|
|
23
|
+
#include "arraylist.h"
|
|
24
|
+
#include "json_object.h"
|
|
25
|
+
#include "json_tokener.h"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
#if !HAVE_STRNCASECMP && defined(_MSC_VER)
|
|
29
|
+
/* MSC has the version as _strnicmp */
|
|
30
|
+
# define strncasecmp _strnicmp
|
|
31
|
+
#elif !HAVE_STRNCASECMP
|
|
32
|
+
# error You do not have strncasecmp on your system.
|
|
33
|
+
#endif /* HAVE_STRNCASECMP */
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
static const char* json_null_str = "null";
|
|
37
|
+
static const char* json_true_str = "true";
|
|
38
|
+
static const char* json_false_str = "false";
|
|
39
|
+
|
|
40
|
+
const char* json_tokener_errors[] = {
|
|
41
|
+
"success",
|
|
42
|
+
"continue",
|
|
43
|
+
"nesting to deep",
|
|
44
|
+
"unexpected end of data",
|
|
45
|
+
"unexpected character",
|
|
46
|
+
"null expected",
|
|
47
|
+
"boolean expected",
|
|
48
|
+
"number expected",
|
|
49
|
+
"array value separator ',' expected",
|
|
50
|
+
"quoted object property name expected",
|
|
51
|
+
"object property name separator ':' expected",
|
|
52
|
+
"object value separator ',' expected",
|
|
53
|
+
"invalid string sequence",
|
|
54
|
+
"expected comment",
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
struct json_tokener* json_tokener_new()
|
|
59
|
+
{
|
|
60
|
+
struct json_tokener *tok = calloc(1, sizeof(struct json_tokener));
|
|
61
|
+
tok->pb = printbuf_new();
|
|
62
|
+
json_tokener_reset(tok);
|
|
63
|
+
return tok;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
void json_tokener_free(struct json_tokener *tok)
|
|
67
|
+
{
|
|
68
|
+
json_tokener_reset(tok);
|
|
69
|
+
if(tok) printbuf_free(tok->pb);
|
|
70
|
+
free(tok);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
|
|
74
|
+
{
|
|
75
|
+
tok->stack[depth].state = json_tokener_state_eatws;
|
|
76
|
+
tok->stack[depth].saved_state = json_tokener_state_start;
|
|
77
|
+
json_object_put(tok->stack[depth].current);
|
|
78
|
+
tok->stack[depth].current = NULL;
|
|
79
|
+
free(tok->stack[depth].obj_field_name);
|
|
80
|
+
tok->stack[depth].obj_field_name = NULL;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
void json_tokener_reset(struct json_tokener *tok)
|
|
84
|
+
{
|
|
85
|
+
int i;
|
|
86
|
+
for(i = tok->depth; i >= 0; i--)
|
|
87
|
+
json_tokener_reset_level(tok, i);
|
|
88
|
+
tok->depth = 0;
|
|
89
|
+
tok->err = json_tokener_success;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
struct json_object* json_tokener_parse(char *str)
|
|
93
|
+
{
|
|
94
|
+
struct json_tokener* tok;
|
|
95
|
+
struct json_object* obj;
|
|
96
|
+
|
|
97
|
+
tok = json_tokener_new();
|
|
98
|
+
obj = json_tokener_parse_ex(tok, str, -1);
|
|
99
|
+
if(tok->err != json_tokener_success)
|
|
100
|
+
obj = error_ptr(-tok->err);
|
|
101
|
+
json_tokener_free(tok);
|
|
102
|
+
return obj;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
#if !HAVE_STRNDUP
|
|
107
|
+
/* CAW: compliant version of strndup() */
|
|
108
|
+
char* strndup(const char* str, size_t n)
|
|
109
|
+
{
|
|
110
|
+
if(str) {
|
|
111
|
+
size_t len = strlen(str);
|
|
112
|
+
size_t nn = min(len,n);
|
|
113
|
+
char* s = (char*)malloc(sizeof(char) * (nn + 1));
|
|
114
|
+
|
|
115
|
+
if(s) {
|
|
116
|
+
memcpy(s, str, nn);
|
|
117
|
+
s[nn] = '\0';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return s;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return NULL;
|
|
124
|
+
}
|
|
125
|
+
#endif
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
#define state tok->stack[tok->depth].state
|
|
129
|
+
#define saved_state tok->stack[tok->depth].saved_state
|
|
130
|
+
#define current tok->stack[tok->depth].current
|
|
131
|
+
#define obj_field_name tok->stack[tok->depth].obj_field_name
|
|
132
|
+
|
|
133
|
+
struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
|
|
134
|
+
char *str, int len)
|
|
135
|
+
{
|
|
136
|
+
struct json_object *obj = NULL;
|
|
137
|
+
char c;
|
|
138
|
+
|
|
139
|
+
tok->char_offset = 0;
|
|
140
|
+
tok->err = json_tokener_success;
|
|
141
|
+
|
|
142
|
+
do {
|
|
143
|
+
if(tok->char_offset == len) {
|
|
144
|
+
if(tok->depth == 0 && state == json_tokener_state_eatws &&
|
|
145
|
+
saved_state == json_tokener_state_finish)
|
|
146
|
+
tok->err = json_tokener_success;
|
|
147
|
+
else
|
|
148
|
+
tok->err = json_tokener_continue;
|
|
149
|
+
goto out;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
c = *str;
|
|
153
|
+
redo_char:
|
|
154
|
+
switch(state) {
|
|
155
|
+
|
|
156
|
+
case json_tokener_state_eatws:
|
|
157
|
+
if(isspace(c)) {
|
|
158
|
+
/* okay */
|
|
159
|
+
} else if(c == '/') {
|
|
160
|
+
printbuf_reset(tok->pb);
|
|
161
|
+
printbuf_memappend(tok->pb, &c, 1);
|
|
162
|
+
state = json_tokener_state_comment_start;
|
|
163
|
+
} else {
|
|
164
|
+
state = saved_state;
|
|
165
|
+
goto redo_char;
|
|
166
|
+
}
|
|
167
|
+
break;
|
|
168
|
+
|
|
169
|
+
case json_tokener_state_start:
|
|
170
|
+
switch(c) {
|
|
171
|
+
case '{':
|
|
172
|
+
state = json_tokener_state_eatws;
|
|
173
|
+
saved_state = json_tokener_state_object_field_start;
|
|
174
|
+
current = json_object_new_object();
|
|
175
|
+
break;
|
|
176
|
+
case '[':
|
|
177
|
+
state = json_tokener_state_eatws;
|
|
178
|
+
saved_state = json_tokener_state_array;
|
|
179
|
+
current = json_object_new_array();
|
|
180
|
+
break;
|
|
181
|
+
case 'N':
|
|
182
|
+
case 'n':
|
|
183
|
+
state = json_tokener_state_null;
|
|
184
|
+
printbuf_reset(tok->pb);
|
|
185
|
+
tok->st_pos = 0;
|
|
186
|
+
goto redo_char;
|
|
187
|
+
case '"':
|
|
188
|
+
case '\'':
|
|
189
|
+
state = json_tokener_state_string;
|
|
190
|
+
printbuf_reset(tok->pb);
|
|
191
|
+
tok->quote_char = c;
|
|
192
|
+
break;
|
|
193
|
+
case 'T':
|
|
194
|
+
case 't':
|
|
195
|
+
case 'F':
|
|
196
|
+
case 'f':
|
|
197
|
+
state = json_tokener_state_boolean;
|
|
198
|
+
printbuf_reset(tok->pb);
|
|
199
|
+
tok->st_pos = 0;
|
|
200
|
+
goto redo_char;
|
|
201
|
+
#if defined(__GNUC__)
|
|
202
|
+
case '0' ... '9':
|
|
203
|
+
#else
|
|
204
|
+
case '0':
|
|
205
|
+
case '1':
|
|
206
|
+
case '2':
|
|
207
|
+
case '3':
|
|
208
|
+
case '4':
|
|
209
|
+
case '5':
|
|
210
|
+
case '6':
|
|
211
|
+
case '7':
|
|
212
|
+
case '8':
|
|
213
|
+
case '9':
|
|
214
|
+
#endif
|
|
215
|
+
case '-':
|
|
216
|
+
state = json_tokener_state_number;
|
|
217
|
+
printbuf_reset(tok->pb);
|
|
218
|
+
tok->is_double = 0;
|
|
219
|
+
goto redo_char;
|
|
220
|
+
default:
|
|
221
|
+
tok->err = json_tokener_error_parse_unexpected;
|
|
222
|
+
goto out;
|
|
223
|
+
}
|
|
224
|
+
break;
|
|
225
|
+
|
|
226
|
+
case json_tokener_state_finish:
|
|
227
|
+
if(tok->depth == 0) goto out;
|
|
228
|
+
obj = json_object_get(current);
|
|
229
|
+
json_tokener_reset_level(tok, tok->depth);
|
|
230
|
+
tok->depth--;
|
|
231
|
+
goto redo_char;
|
|
232
|
+
|
|
233
|
+
case json_tokener_state_null:
|
|
234
|
+
printbuf_memappend(tok->pb, &c, 1);
|
|
235
|
+
if(strncasecmp(json_null_str, tok->pb->buf,
|
|
236
|
+
min(tok->st_pos+1, strlen(json_null_str))) == 0) {
|
|
237
|
+
if(tok->st_pos == strlen(json_null_str)) {
|
|
238
|
+
current = NULL;
|
|
239
|
+
saved_state = json_tokener_state_finish;
|
|
240
|
+
state = json_tokener_state_eatws;
|
|
241
|
+
goto redo_char;
|
|
242
|
+
}
|
|
243
|
+
} else {
|
|
244
|
+
tok->err = json_tokener_error_parse_null;
|
|
245
|
+
goto out;
|
|
246
|
+
}
|
|
247
|
+
tok->st_pos++;
|
|
248
|
+
break;
|
|
249
|
+
|
|
250
|
+
case json_tokener_state_comment_start:
|
|
251
|
+
if(c == '*') {
|
|
252
|
+
state = json_tokener_state_comment;
|
|
253
|
+
} else if(c == '/') {
|
|
254
|
+
state = json_tokener_state_comment_eol;
|
|
255
|
+
} else {
|
|
256
|
+
tok->err = json_tokener_error_parse_comment;
|
|
257
|
+
goto out;
|
|
258
|
+
}
|
|
259
|
+
printbuf_memappend(tok->pb, &c, 1);
|
|
260
|
+
break;
|
|
261
|
+
|
|
262
|
+
case json_tokener_state_comment:
|
|
263
|
+
if(c == '*') state = json_tokener_state_comment_end;
|
|
264
|
+
printbuf_memappend(tok->pb, &c, 1);
|
|
265
|
+
break;
|
|
266
|
+
|
|
267
|
+
case json_tokener_state_comment_eol:
|
|
268
|
+
if(c == '\n') {
|
|
269
|
+
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
|
|
270
|
+
state = json_tokener_state_eatws;
|
|
271
|
+
} else {
|
|
272
|
+
printbuf_memappend(tok->pb, &c, 1);
|
|
273
|
+
}
|
|
274
|
+
break;
|
|
275
|
+
|
|
276
|
+
case json_tokener_state_comment_end:
|
|
277
|
+
printbuf_memappend(tok->pb, &c, 1);
|
|
278
|
+
if(c == '/') {
|
|
279
|
+
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
|
|
280
|
+
state = json_tokener_state_eatws;
|
|
281
|
+
} else {
|
|
282
|
+
state = json_tokener_state_comment;
|
|
283
|
+
}
|
|
284
|
+
break;
|
|
285
|
+
|
|
286
|
+
case json_tokener_state_string:
|
|
287
|
+
if(c == tok->quote_char) {
|
|
288
|
+
current = json_object_new_string(tok->pb->buf);
|
|
289
|
+
saved_state = json_tokener_state_finish;
|
|
290
|
+
state = json_tokener_state_eatws;
|
|
291
|
+
} else if(c == '\\') {
|
|
292
|
+
saved_state = json_tokener_state_string;
|
|
293
|
+
state = json_tokener_state_string_escape;
|
|
294
|
+
} else {
|
|
295
|
+
printbuf_memappend(tok->pb, &c, 1);
|
|
296
|
+
}
|
|
297
|
+
break;
|
|
298
|
+
|
|
299
|
+
case json_tokener_state_string_escape:
|
|
300
|
+
switch(c) {
|
|
301
|
+
case '"':
|
|
302
|
+
case '\\':
|
|
303
|
+
case '/':
|
|
304
|
+
printbuf_memappend(tok->pb, &c, 1);
|
|
305
|
+
state = saved_state;
|
|
306
|
+
break;
|
|
307
|
+
case 'b':
|
|
308
|
+
case 'n':
|
|
309
|
+
case 'r':
|
|
310
|
+
case 't':
|
|
311
|
+
if(c == 'b') printbuf_memappend(tok->pb, "\b", 1);
|
|
312
|
+
else if(c == 'n') printbuf_memappend(tok->pb, "\n", 1);
|
|
313
|
+
else if(c == 'r') printbuf_memappend(tok->pb, "\r", 1);
|
|
314
|
+
else if(c == 't') printbuf_memappend(tok->pb, "\t", 1);
|
|
315
|
+
state = saved_state;
|
|
316
|
+
break;
|
|
317
|
+
case 'u':
|
|
318
|
+
tok->ucs_char = 0;
|
|
319
|
+
tok->st_pos = 0;
|
|
320
|
+
state = json_tokener_state_escape_unicode;
|
|
321
|
+
break;
|
|
322
|
+
default:
|
|
323
|
+
tok->err = json_tokener_error_parse_string;
|
|
324
|
+
goto out;
|
|
325
|
+
}
|
|
326
|
+
break;
|
|
327
|
+
|
|
328
|
+
case json_tokener_state_escape_unicode:
|
|
329
|
+
if(strchr(json_hex_chars, c)) {
|
|
330
|
+
tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
|
|
331
|
+
if(tok->st_pos == 4) {
|
|
332
|
+
unsigned char utf_out[3];
|
|
333
|
+
if (tok->ucs_char < 0x80) {
|
|
334
|
+
utf_out[0] = tok->ucs_char;
|
|
335
|
+
printbuf_memappend(tok->pb, (char*)utf_out, 1);
|
|
336
|
+
} else if (tok->ucs_char < 0x800) {
|
|
337
|
+
utf_out[0] = 0xc0 | (tok->ucs_char >> 6);
|
|
338
|
+
utf_out[1] = 0x80 | (tok->ucs_char & 0x3f);
|
|
339
|
+
printbuf_memappend(tok->pb, (char*)utf_out, 2);
|
|
340
|
+
} else {
|
|
341
|
+
utf_out[0] = 0xe0 | (tok->ucs_char >> 12);
|
|
342
|
+
utf_out[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
|
|
343
|
+
utf_out[2] = 0x80 | (tok->ucs_char & 0x3f);
|
|
344
|
+
printbuf_memappend(tok->pb, (char*)utf_out, 3);
|
|
345
|
+
}
|
|
346
|
+
state = saved_state;
|
|
347
|
+
}
|
|
348
|
+
} else {
|
|
349
|
+
tok->err = json_tokener_error_parse_string;
|
|
350
|
+
goto out;
|
|
351
|
+
}
|
|
352
|
+
break;
|
|
353
|
+
|
|
354
|
+
case json_tokener_state_boolean:
|
|
355
|
+
printbuf_memappend(tok->pb, &c, 1);
|
|
356
|
+
if(strncasecmp(json_true_str, tok->pb->buf,
|
|
357
|
+
min(tok->st_pos+1, strlen(json_true_str))) == 0) {
|
|
358
|
+
if(tok->st_pos == strlen(json_true_str)) {
|
|
359
|
+
current = json_object_new_boolean(1);
|
|
360
|
+
saved_state = json_tokener_state_finish;
|
|
361
|
+
state = json_tokener_state_eatws;
|
|
362
|
+
goto redo_char;
|
|
363
|
+
}
|
|
364
|
+
} else if(strncasecmp(json_false_str, tok->pb->buf,
|
|
365
|
+
min(tok->st_pos+1, strlen(json_false_str))) == 0) {
|
|
366
|
+
if(tok->st_pos == strlen(json_false_str)) {
|
|
367
|
+
current = json_object_new_boolean(0);
|
|
368
|
+
saved_state = json_tokener_state_finish;
|
|
369
|
+
state = json_tokener_state_eatws;
|
|
370
|
+
goto redo_char;
|
|
371
|
+
}
|
|
372
|
+
} else {
|
|
373
|
+
tok->err = json_tokener_error_parse_boolean;
|
|
374
|
+
goto out;
|
|
375
|
+
}
|
|
376
|
+
tok->st_pos++;
|
|
377
|
+
break;
|
|
378
|
+
|
|
379
|
+
case json_tokener_state_number:
|
|
380
|
+
if(c && strchr(json_number_chars, c)) {
|
|
381
|
+
printbuf_memappend(tok->pb, &c, 1);
|
|
382
|
+
if(c == '.' || c == 'e' || c == 'E') tok->is_double = 1;
|
|
383
|
+
} else {
|
|
384
|
+
int numi;
|
|
385
|
+
double numd;
|
|
386
|
+
if(!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
|
|
387
|
+
current = json_object_new_int(numi);
|
|
388
|
+
} else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) {
|
|
389
|
+
current = json_object_new_double(numd);
|
|
390
|
+
} else {
|
|
391
|
+
tok->err = json_tokener_error_parse_number;
|
|
392
|
+
goto out;
|
|
393
|
+
}
|
|
394
|
+
saved_state = json_tokener_state_finish;
|
|
395
|
+
state = json_tokener_state_eatws;
|
|
396
|
+
goto redo_char;
|
|
397
|
+
}
|
|
398
|
+
break;
|
|
399
|
+
|
|
400
|
+
case json_tokener_state_array:
|
|
401
|
+
if(c == ']') {
|
|
402
|
+
saved_state = json_tokener_state_finish;
|
|
403
|
+
state = json_tokener_state_eatws;
|
|
404
|
+
} else {
|
|
405
|
+
if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
|
|
406
|
+
tok->err = json_tokener_error_depth;
|
|
407
|
+
goto out;
|
|
408
|
+
}
|
|
409
|
+
state = json_tokener_state_array_add;
|
|
410
|
+
tok->depth++;
|
|
411
|
+
json_tokener_reset_level(tok, tok->depth);
|
|
412
|
+
goto redo_char;
|
|
413
|
+
}
|
|
414
|
+
break;
|
|
415
|
+
|
|
416
|
+
case json_tokener_state_array_add:
|
|
417
|
+
json_object_array_add(current, obj);
|
|
418
|
+
saved_state = json_tokener_state_array_sep;
|
|
419
|
+
state = json_tokener_state_eatws;
|
|
420
|
+
goto redo_char;
|
|
421
|
+
|
|
422
|
+
case json_tokener_state_array_sep:
|
|
423
|
+
if(c == ']') {
|
|
424
|
+
saved_state = json_tokener_state_finish;
|
|
425
|
+
state = json_tokener_state_eatws;
|
|
426
|
+
} else if(c == ',') {
|
|
427
|
+
saved_state = json_tokener_state_array;
|
|
428
|
+
state = json_tokener_state_eatws;
|
|
429
|
+
} else {
|
|
430
|
+
tok->err = json_tokener_error_parse_array;
|
|
431
|
+
goto out;
|
|
432
|
+
}
|
|
433
|
+
break;
|
|
434
|
+
|
|
435
|
+
case json_tokener_state_object_field_start:
|
|
436
|
+
if(c == '}') {
|
|
437
|
+
saved_state = json_tokener_state_finish;
|
|
438
|
+
state = json_tokener_state_eatws;
|
|
439
|
+
} else if (c == '"' || c == '\'') {
|
|
440
|
+
tok->quote_char = c;
|
|
441
|
+
printbuf_reset(tok->pb);
|
|
442
|
+
state = json_tokener_state_object_field;
|
|
443
|
+
} else {
|
|
444
|
+
tok->err = json_tokener_error_parse_object_key_name;
|
|
445
|
+
goto out;
|
|
446
|
+
}
|
|
447
|
+
break;
|
|
448
|
+
|
|
449
|
+
case json_tokener_state_object_field:
|
|
450
|
+
if(c == tok->quote_char) {
|
|
451
|
+
obj_field_name = strdup(tok->pb->buf);
|
|
452
|
+
saved_state = json_tokener_state_object_field_end;
|
|
453
|
+
state = json_tokener_state_eatws;
|
|
454
|
+
} else if(c == '\\') {
|
|
455
|
+
saved_state = json_tokener_state_object_field;
|
|
456
|
+
state = json_tokener_state_string_escape;
|
|
457
|
+
} else {
|
|
458
|
+
printbuf_memappend(tok->pb, &c, 1);
|
|
459
|
+
}
|
|
460
|
+
break;
|
|
461
|
+
|
|
462
|
+
case json_tokener_state_object_field_end:
|
|
463
|
+
if(c == ':') {
|
|
464
|
+
saved_state = json_tokener_state_object_value;
|
|
465
|
+
state = json_tokener_state_eatws;
|
|
466
|
+
} else {
|
|
467
|
+
tok->err = json_tokener_error_parse_object_key_sep;
|
|
468
|
+
goto out;
|
|
469
|
+
}
|
|
470
|
+
break;
|
|
471
|
+
|
|
472
|
+
case json_tokener_state_object_value:
|
|
473
|
+
if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
|
|
474
|
+
tok->err = json_tokener_error_depth;
|
|
475
|
+
goto out;
|
|
476
|
+
}
|
|
477
|
+
state = json_tokener_state_object_value_add;
|
|
478
|
+
tok->depth++;
|
|
479
|
+
json_tokener_reset_level(tok, tok->depth);
|
|
480
|
+
goto redo_char;
|
|
481
|
+
|
|
482
|
+
case json_tokener_state_object_value_add:
|
|
483
|
+
json_object_object_add(current, obj_field_name, obj);
|
|
484
|
+
free(obj_field_name);
|
|
485
|
+
obj_field_name = NULL;
|
|
486
|
+
saved_state = json_tokener_state_object_sep;
|
|
487
|
+
state = json_tokener_state_eatws;
|
|
488
|
+
goto redo_char;
|
|
489
|
+
|
|
490
|
+
case json_tokener_state_object_sep:
|
|
491
|
+
if(c == '}') {
|
|
492
|
+
saved_state = json_tokener_state_finish;
|
|
493
|
+
state = json_tokener_state_eatws;
|
|
494
|
+
} else if(c == ',') {
|
|
495
|
+
saved_state = json_tokener_state_object_field_start;
|
|
496
|
+
state = json_tokener_state_eatws;
|
|
497
|
+
} else {
|
|
498
|
+
tok->err = json_tokener_error_parse_object_value_sep;
|
|
499
|
+
goto out;
|
|
500
|
+
}
|
|
501
|
+
break;
|
|
502
|
+
|
|
503
|
+
}
|
|
504
|
+
str++;
|
|
505
|
+
tok->char_offset++;
|
|
506
|
+
} while(c);
|
|
507
|
+
|
|
508
|
+
if(state != json_tokener_state_finish &&
|
|
509
|
+
saved_state != json_tokener_state_finish)
|
|
510
|
+
tok->err = json_tokener_error_parse_eof;
|
|
511
|
+
|
|
512
|
+
out:
|
|
513
|
+
if(tok->err == json_tokener_success) return json_object_get(current);
|
|
514
|
+
MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
|
|
515
|
+
json_tokener_errors[tok->err], tok->char_offset);
|
|
516
|
+
return NULL;
|
|
517
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
|
|
5
|
+
* Michael Clark <michael@metaparadigm.com>
|
|
6
|
+
*
|
|
7
|
+
* This library is free software; you can redistribute it and/or modify
|
|
8
|
+
* it under the terms of the MIT license. See COPYING for details.
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
#ifndef _json_tokener_h_
|
|
13
|
+
#define _json_tokener_h_
|
|
14
|
+
|
|
15
|
+
#include <stddef.h>
|
|
16
|
+
#include "json_object.h"
|
|
17
|
+
|
|
18
|
+
enum json_tokener_error {
|
|
19
|
+
json_tokener_success,
|
|
20
|
+
json_tokener_continue,
|
|
21
|
+
json_tokener_error_depth,
|
|
22
|
+
json_tokener_error_parse_eof,
|
|
23
|
+
json_tokener_error_parse_unexpected,
|
|
24
|
+
json_tokener_error_parse_null,
|
|
25
|
+
json_tokener_error_parse_boolean,
|
|
26
|
+
json_tokener_error_parse_number,
|
|
27
|
+
json_tokener_error_parse_array,
|
|
28
|
+
json_tokener_error_parse_object_key_name,
|
|
29
|
+
json_tokener_error_parse_object_key_sep,
|
|
30
|
+
json_tokener_error_parse_object_value_sep,
|
|
31
|
+
json_tokener_error_parse_string,
|
|
32
|
+
json_tokener_error_parse_comment
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
enum json_tokener_state {
|
|
36
|
+
json_tokener_state_eatws,
|
|
37
|
+
json_tokener_state_start,
|
|
38
|
+
json_tokener_state_finish,
|
|
39
|
+
json_tokener_state_null,
|
|
40
|
+
json_tokener_state_comment_start,
|
|
41
|
+
json_tokener_state_comment,
|
|
42
|
+
json_tokener_state_comment_eol,
|
|
43
|
+
json_tokener_state_comment_end,
|
|
44
|
+
json_tokener_state_string,
|
|
45
|
+
json_tokener_state_string_escape,
|
|
46
|
+
json_tokener_state_escape_unicode,
|
|
47
|
+
json_tokener_state_boolean,
|
|
48
|
+
json_tokener_state_number,
|
|
49
|
+
json_tokener_state_array,
|
|
50
|
+
json_tokener_state_array_add,
|
|
51
|
+
json_tokener_state_array_sep,
|
|
52
|
+
json_tokener_state_object_field_start,
|
|
53
|
+
json_tokener_state_object_field,
|
|
54
|
+
json_tokener_state_object_field_end,
|
|
55
|
+
json_tokener_state_object_value,
|
|
56
|
+
json_tokener_state_object_value_add,
|
|
57
|
+
json_tokener_state_object_sep
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
struct json_tokener_srec
|
|
61
|
+
{
|
|
62
|
+
enum json_tokener_state state, saved_state;
|
|
63
|
+
struct json_object *obj;
|
|
64
|
+
struct json_object *current;
|
|
65
|
+
char *obj_field_name;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
#define JSON_TOKENER_MAX_DEPTH 32
|
|
69
|
+
|
|
70
|
+
struct json_tokener
|
|
71
|
+
{
|
|
72
|
+
char *str;
|
|
73
|
+
struct printbuf *pb;
|
|
74
|
+
int depth, is_double, st_pos, char_offset;
|
|
75
|
+
ptrdiff_t err;
|
|
76
|
+
unsigned int ucs_char;
|
|
77
|
+
char quote_char;
|
|
78
|
+
struct json_tokener_srec stack[JSON_TOKENER_MAX_DEPTH];
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
extern const char* json_tokener_errors[];
|
|
82
|
+
|
|
83
|
+
extern struct json_tokener* json_tokener_new(void);
|
|
84
|
+
extern void json_tokener_free(struct json_tokener *tok);
|
|
85
|
+
extern void json_tokener_reset(struct json_tokener *tok);
|
|
86
|
+
extern struct json_object* json_tokener_parse(char *str);
|
|
87
|
+
extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
|
|
88
|
+
char *str, int len);
|
|
89
|
+
|
|
90
|
+
#endif
|