| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
/* Copyright (C) 2012-2015 Mark Nunberg. |
|
2
|
|
|
|
|
|
|
* |
|
3
|
|
|
|
|
|
|
* See included LICENSE file for license details. |
|
4
|
|
|
|
|
|
|
*/ |
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
#include "jsonsl.h" |
|
7
|
|
|
|
|
|
|
#include |
|
8
|
|
|
|
|
|
|
#include |
|
9
|
|
|
|
|
|
|
#include |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
#ifdef JSONSL_USE_METRICS |
|
12
|
|
|
|
|
|
|
#define XMETRICS \ |
|
13
|
|
|
|
|
|
|
X(STRINGY_INSIGNIFICANT) \ |
|
14
|
|
|
|
|
|
|
X(STRINGY_SLOWPATH) \ |
|
15
|
|
|
|
|
|
|
X(ALLOWED_WHITESPACE) \ |
|
16
|
|
|
|
|
|
|
X(QUOTE_FASTPATH) \ |
|
17
|
|
|
|
|
|
|
X(SPECIAL_FASTPATH) \ |
|
18
|
|
|
|
|
|
|
X(SPECIAL_WSPOP) \ |
|
19
|
|
|
|
|
|
|
X(SPECIAL_SLOWPATH) \ |
|
20
|
|
|
|
|
|
|
X(GENERIC) \ |
|
21
|
|
|
|
|
|
|
X(STRUCTURAL_TOKEN) \ |
|
22
|
|
|
|
|
|
|
X(SPECIAL_SWITCHFIRST) \ |
|
23
|
|
|
|
|
|
|
X(STRINGY_CATCH) \ |
|
24
|
|
|
|
|
|
|
X(ESCAPES) \ |
|
25
|
|
|
|
|
|
|
X(TOTAL) \ |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
struct jsonsl_metrics_st { |
|
28
|
|
|
|
|
|
|
#define X(m) \ |
|
29
|
|
|
|
|
|
|
unsigned long metric_##m; |
|
30
|
|
|
|
|
|
|
XMETRICS |
|
31
|
|
|
|
|
|
|
#undef X |
|
32
|
|
|
|
|
|
|
}; |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
static struct jsonsl_metrics_st GlobalMetrics = { 0 }; |
|
35
|
|
|
|
|
|
|
static unsigned long GenericCounter[0x100] = { 0 }; |
|
36
|
|
|
|
|
|
|
static unsigned long StringyCatchCounter[0x100] = { 0 }; |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
#define INCR_METRIC(m) \ |
|
39
|
|
|
|
|
|
|
GlobalMetrics.metric_##m++; |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
#define INCR_GENERIC(c) \ |
|
42
|
|
|
|
|
|
|
INCR_METRIC(GENERIC); \ |
|
43
|
|
|
|
|
|
|
GenericCounter[c]++; \ |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
#define INCR_STRINGY_CATCH(c) \ |
|
46
|
|
|
|
|
|
|
INCR_METRIC(STRINGY_CATCH); \ |
|
47
|
|
|
|
|
|
|
StringyCatchCounter[c]++; |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
JSONSL_API |
|
50
|
|
|
|
|
|
|
void jsonsl_dump_global_metrics(void) |
|
51
|
|
|
|
|
|
|
{ |
|
52
|
|
|
|
|
|
|
int ii; |
|
53
|
|
|
|
|
|
|
printf("JSONSL Metrics:\n"); |
|
54
|
|
|
|
|
|
|
#define X(m) \ |
|
55
|
|
|
|
|
|
|
printf("\t%-30s %20lu (%0.2f%%)\n", #m, GlobalMetrics.metric_##m, \ |
|
56
|
|
|
|
|
|
|
(float)((float)(GlobalMetrics.metric_##m/(float)GlobalMetrics.metric_TOTAL)) * 100); |
|
57
|
|
|
|
|
|
|
XMETRICS |
|
58
|
|
|
|
|
|
|
#undef X |
|
59
|
|
|
|
|
|
|
printf("Generic Characters:\n"); |
|
60
|
|
|
|
|
|
|
for (ii = 0; ii < 0xff; ii++) { |
|
61
|
|
|
|
|
|
|
if (GenericCounter[ii]) { |
|
62
|
|
|
|
|
|
|
printf("\t[ %c ] %lu\n", ii, GenericCounter[ii]); |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
} |
|
65
|
|
|
|
|
|
|
printf("Weird string loop\n"); |
|
66
|
|
|
|
|
|
|
for (ii = 0; ii < 0xff; ii++) { |
|
67
|
|
|
|
|
|
|
if (StringyCatchCounter[ii]) { |
|
68
|
|
|
|
|
|
|
printf("\t[ %c ] %lu\n", ii, StringyCatchCounter[ii]); |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
} |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
#else |
|
74
|
|
|
|
|
|
|
#define INCR_METRIC(m) |
|
75
|
|
|
|
|
|
|
#define INCR_GENERIC(c) |
|
76
|
|
|
|
|
|
|
#define INCR_STRINGY_CATCH(c) |
|
77
|
|
|
|
|
|
|
JSONSL_API |
|
78
|
0
|
|
|
|
|
|
void jsonsl_dump_global_metrics(void) { } |
|
79
|
|
|
|
|
|
|
#endif /* JSONSL_USE_METRICS */ |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
#define CASE_DIGITS \ |
|
82
|
|
|
|
|
|
|
case '1': \ |
|
83
|
|
|
|
|
|
|
case '2': \ |
|
84
|
|
|
|
|
|
|
case '3': \ |
|
85
|
|
|
|
|
|
|
case '4': \ |
|
86
|
|
|
|
|
|
|
case '5': \ |
|
87
|
|
|
|
|
|
|
case '6': \ |
|
88
|
|
|
|
|
|
|
case '7': \ |
|
89
|
|
|
|
|
|
|
case '8': \ |
|
90
|
|
|
|
|
|
|
case '9': \ |
|
91
|
|
|
|
|
|
|
case '0': |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
static unsigned extract_special(unsigned); |
|
94
|
|
|
|
|
|
|
static int is_special_end(unsigned); |
|
95
|
|
|
|
|
|
|
static int is_allowed_whitespace(unsigned); |
|
96
|
|
|
|
|
|
|
static int is_allowed_escape(unsigned); |
|
97
|
|
|
|
|
|
|
static char get_escape_equiv(unsigned); |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
JSONSL_API |
|
100
|
33
|
|
|
|
|
|
jsonsl_t jsonsl_new(int nlevels) |
|
101
|
|
|
|
|
|
|
{ |
|
102
|
33
|
|
|
|
|
|
struct jsonsl_st *jsn = (struct jsonsl_st *) |
|
103
|
33
|
|
|
|
|
|
calloc(1, sizeof (*jsn) + |
|
104
|
33
|
|
|
|
|
|
( (nlevels-1) * sizeof (struct jsonsl_state_st) ) |
|
105
|
|
|
|
|
|
|
); |
|
106
|
|
|
|
|
|
|
|
|
107
|
33
|
|
|
|
|
|
jsn->levels_max = nlevels; |
|
108
|
33
|
|
|
|
|
|
jsn->max_callback_level = -1; |
|
109
|
33
|
|
|
|
|
|
jsonsl_reset(jsn); |
|
110
|
33
|
|
|
|
|
|
return jsn; |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
JSONSL_API |
|
114
|
67
|
|
|
|
|
|
void jsonsl_reset(jsonsl_t jsn) |
|
115
|
|
|
|
|
|
|
{ |
|
116
|
|
|
|
|
|
|
unsigned int ii; |
|
117
|
67
|
|
|
|
|
|
jsn->tok_last = 0; |
|
118
|
67
|
|
|
|
|
|
jsn->can_insert = 1; |
|
119
|
67
|
|
|
|
|
|
jsn->pos = 0; |
|
120
|
67
|
|
|
|
|
|
jsn->level = 0; |
|
121
|
67
|
|
|
|
|
|
jsn->stopfl = 0; |
|
122
|
67
|
|
|
|
|
|
jsn->in_escape = 0; |
|
123
|
67
|
|
|
|
|
|
jsn->expecting = 0; |
|
124
|
|
|
|
|
|
|
|
|
125
|
67
|
|
|
|
|
|
memset(jsn->stack, 0, (jsn->levels_max * sizeof (struct jsonsl_state_st))); |
|
126
|
|
|
|
|
|
|
|
|
127
|
33026
|
100
|
|
|
|
|
for (ii = 0; ii < jsn->levels_max; ii++) { |
|
128
|
32959
|
|
|
|
|
|
jsn->stack[ii].level = ii; |
|
129
|
|
|
|
|
|
|
} |
|
130
|
67
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
JSONSL_API |
|
133
|
26
|
|
|
|
|
|
void jsonsl_destroy(jsonsl_t jsn) |
|
134
|
|
|
|
|
|
|
{ |
|
135
|
26
|
50
|
|
|
|
|
if (jsn) { |
|
136
|
26
|
|
|
|
|
|
free(jsn); |
|
137
|
|
|
|
|
|
|
} |
|
138
|
26
|
|
|
|
|
|
} |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
JSONSL_API |
|
141
|
|
|
|
|
|
|
void |
|
142
|
57
|
|
|
|
|
|
jsonsl_feed(jsonsl_t jsn, const jsonsl_char_t *bytes, size_t nbytes) |
|
143
|
|
|
|
|
|
|
{ |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
#define INVOKE_ERROR(eb) \ |
|
146
|
|
|
|
|
|
|
if (jsn->error_callback(jsn, JSONSL_ERROR_##eb, state, (char*)c)) { \ |
|
147
|
|
|
|
|
|
|
goto GT_AGAIN; \ |
|
148
|
|
|
|
|
|
|
} \ |
|
149
|
|
|
|
|
|
|
return; |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
#define STACK_PUSH \ |
|
152
|
|
|
|
|
|
|
if (jsn->level >= (levels_max-1)) { \ |
|
153
|
|
|
|
|
|
|
jsn->error_callback(jsn, JSONSL_ERROR_LEVELS_EXCEEDED, state, (char*)c); \ |
|
154
|
|
|
|
|
|
|
return; \ |
|
155
|
|
|
|
|
|
|
} \ |
|
156
|
|
|
|
|
|
|
state = jsn->stack + (++jsn->level); \ |
|
157
|
|
|
|
|
|
|
state->ignore_callback = jsn->stack[jsn->level-1].ignore_callback; \ |
|
158
|
|
|
|
|
|
|
state->pos_begin = jsn->pos; |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
#define STACK_POP_NOPOS \ |
|
161
|
|
|
|
|
|
|
state->pos_cur = jsn->pos; \ |
|
162
|
|
|
|
|
|
|
state = jsn->stack + (--jsn->level); |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
#define STACK_POP \ |
|
166
|
|
|
|
|
|
|
STACK_POP_NOPOS; \ |
|
167
|
|
|
|
|
|
|
state->pos_cur = jsn->pos; |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
#define CALLBACK_AND_POP_NOPOS(T) \ |
|
170
|
|
|
|
|
|
|
state->pos_cur = jsn->pos; \ |
|
171
|
|
|
|
|
|
|
DO_CALLBACK(T, POP); \ |
|
172
|
|
|
|
|
|
|
state->nescapes = 0; \ |
|
173
|
|
|
|
|
|
|
state = jsn->stack + (--jsn->level); |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
#define CALLBACK_AND_POP(T) \ |
|
176
|
|
|
|
|
|
|
CALLBACK_AND_POP_NOPOS(T); \ |
|
177
|
|
|
|
|
|
|
state->pos_cur = jsn->pos; |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
#define SPECIAL_POP \ |
|
180
|
|
|
|
|
|
|
CALLBACK_AND_POP(SPECIAL); \ |
|
181
|
|
|
|
|
|
|
jsn->expecting = 0; \ |
|
182
|
|
|
|
|
|
|
jsn->tok_last = 0; \ |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
#define CUR_CHAR (*(jsonsl_uchar_t*)c) |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
#define DO_CALLBACK(T, action) \ |
|
187
|
|
|
|
|
|
|
if (jsn->call_##T && \ |
|
188
|
|
|
|
|
|
|
jsn->max_callback_level > state->level && \ |
|
189
|
|
|
|
|
|
|
state->ignore_callback == 0) { \ |
|
190
|
|
|
|
|
|
|
\ |
|
191
|
|
|
|
|
|
|
if (jsn->action_callback_##action) { \ |
|
192
|
|
|
|
|
|
|
jsn->action_callback_##action(jsn, JSONSL_ACTION_##action, state, (jsonsl_char_t*)c); \ |
|
193
|
|
|
|
|
|
|
} else if (jsn->action_callback) { \ |
|
194
|
|
|
|
|
|
|
jsn->action_callback(jsn, JSONSL_ACTION_##action, state, (jsonsl_char_t*)c); \ |
|
195
|
|
|
|
|
|
|
} \ |
|
196
|
|
|
|
|
|
|
if (jsn->stopfl) { return; } \ |
|
197
|
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
/** |
|
200
|
|
|
|
|
|
|
* Verifies that we are able to insert the (non-string) item into a hash. |
|
201
|
|
|
|
|
|
|
*/ |
|
202
|
|
|
|
|
|
|
#define ENSURE_HVAL \ |
|
203
|
|
|
|
|
|
|
if (state->nelem % 2 == 0 && state->type == JSONSL_T_OBJECT) { \ |
|
204
|
|
|
|
|
|
|
INVOKE_ERROR(HKEY_EXPECTED); \ |
|
205
|
|
|
|
|
|
|
} |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
#define VERIFY_SPECIAL(lit) \ |
|
208
|
|
|
|
|
|
|
if (CUR_CHAR != (lit)[jsn->pos - state->pos_begin]) { \ |
|
209
|
|
|
|
|
|
|
INVOKE_ERROR(SPECIAL_EXPECTED); \ |
|
210
|
|
|
|
|
|
|
} |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
#define STATE_SPECIAL_LENGTH \ |
|
213
|
|
|
|
|
|
|
(state)->nescapes |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
#define IS_NORMAL_NUMBER \ |
|
216
|
|
|
|
|
|
|
((state)->special_flags == JSONSL_SPECIALf_UNSIGNED || \ |
|
217
|
|
|
|
|
|
|
(state)->special_flags == JSONSL_SPECIALf_SIGNED) |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
#define STATE_NUM_LAST jsn->tok_last |
|
220
|
|
|
|
|
|
|
|
|
221
|
57
|
|
|
|
|
|
const jsonsl_uchar_t *c = (jsonsl_uchar_t*)bytes; |
|
222
|
57
|
|
|
|
|
|
size_t levels_max = jsn->levels_max; |
|
223
|
57
|
|
|
|
|
|
struct jsonsl_state_st *state = jsn->stack + jsn->level; |
|
224
|
|
|
|
|
|
|
static int chrt_string_nopass[0x100] = { JSONSL_CHARTABLE_string_nopass }; |
|
225
|
57
|
|
|
|
|
|
jsn->base = bytes; |
|
226
|
|
|
|
|
|
|
|
|
227
|
7576
|
100
|
|
|
|
|
for (; nbytes; nbytes--, jsn->pos++, c++) { |
|
228
|
|
|
|
|
|
|
unsigned state_type; |
|
229
|
|
|
|
|
|
|
INCR_METRIC(TOTAL); |
|
230
|
|
|
|
|
|
|
/* Special escape handling for some stuff */ |
|
231
|
7533
|
100
|
|
|
|
|
if (jsn->in_escape) { |
|
232
|
13
|
|
|
|
|
|
jsn->in_escape = 0; |
|
233
|
13
|
50
|
|
|
|
|
if (!is_allowed_escape(CUR_CHAR)) { |
|
234
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(ESCAPE_INVALID); |
|
235
|
13
|
100
|
|
|
|
|
} else if (CUR_CHAR == 'u') { |
|
236
|
4
|
50
|
|
|
|
|
DO_CALLBACK(UESCAPE, UESCAPE); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
237
|
4
|
50
|
|
|
|
|
if (jsn->return_UESCAPE) { |
|
238
|
0
|
|
|
|
|
|
return; |
|
239
|
|
|
|
|
|
|
} |
|
240
|
|
|
|
|
|
|
} |
|
241
|
13
|
|
|
|
|
|
goto GT_NEXT; |
|
242
|
|
|
|
|
|
|
} |
|
243
|
|
|
|
|
|
|
GT_AGAIN: |
|
244
|
|
|
|
|
|
|
/** |
|
245
|
|
|
|
|
|
|
* Several fast-tracks for common cases: |
|
246
|
|
|
|
|
|
|
*/ |
|
247
|
7520
|
|
|
|
|
|
state_type = state->type; |
|
248
|
7520
|
100
|
|
|
|
|
if (state_type & JSONSL_Tf_STRINGY) { |
|
249
|
|
|
|
|
|
|
/* check if our character cannot ever change our current string state |
|
250
|
|
|
|
|
|
|
* or throw an error |
|
251
|
|
|
|
|
|
|
*/ |
|
252
|
1633
|
100
|
|
|
|
|
if ( |
|
253
|
|
|
|
|
|
|
#ifdef JSONSL_USE_WCHAR |
|
254
|
|
|
|
|
|
|
CUR_CHAR >= 0x100 || |
|
255
|
|
|
|
|
|
|
#endif /* JSONSL_USE_WCHAR */ |
|
256
|
1633
|
|
|
|
|
|
(!chrt_string_nopass[CUR_CHAR & 0xff])) { |
|
257
|
|
|
|
|
|
|
INCR_METRIC(STRINGY_INSIGNIFICANT); |
|
258
|
506
|
|
|
|
|
|
goto GT_NEXT; |
|
259
|
1127
|
100
|
|
|
|
|
} else if (CUR_CHAR == '"') { |
|
260
|
1113
|
|
|
|
|
|
goto GT_QUOTE; |
|
261
|
14
|
100
|
|
|
|
|
} else if (CUR_CHAR == '\\') { |
|
262
|
13
|
|
|
|
|
|
goto GT_ESCAPE; |
|
263
|
|
|
|
|
|
|
} else { |
|
264
|
1
|
0
|
|
|
|
|
INVOKE_ERROR(WEIRD_WHITESPACE); |
|
265
|
|
|
|
|
|
|
} |
|
266
|
|
|
|
|
|
|
INCR_METRIC(STRINGY_SLOWPATH); |
|
267
|
|
|
|
|
|
|
|
|
268
|
5887
|
100
|
|
|
|
|
} else if (state_type == JSONSL_T_SPECIAL) { |
|
269
|
|
|
|
|
|
|
/* Fast track for signed/unsigned */ |
|
270
|
137
|
100
|
|
|
|
|
if (IS_NORMAL_NUMBER) { |
|
|
|
100
|
|
|
|
|
|
|
271
|
31
|
100
|
|
|
|
|
if (isdigit(CUR_CHAR)) { |
|
272
|
7
|
|
|
|
|
|
state->nelem = (state->nelem * 10) + (CUR_CHAR-0x30); |
|
273
|
7
|
|
|
|
|
|
goto GT_NEXT; |
|
274
|
|
|
|
|
|
|
} else { |
|
275
|
24
|
|
|
|
|
|
goto GT_SPECIAL_NUMERIC; |
|
276
|
|
|
|
|
|
|
} |
|
277
|
|
|
|
|
|
|
|
|
278
|
106
|
100
|
|
|
|
|
} else if (state->special_flags == JSONSL_SPECIALf_DASH) { |
|
279
|
7
|
100
|
|
|
|
|
if (!isdigit(CUR_CHAR)) { |
|
280
|
1
|
0
|
|
|
|
|
INVOKE_ERROR(INVALID_NUMBER); |
|
281
|
|
|
|
|
|
|
} |
|
282
|
|
|
|
|
|
|
|
|
283
|
6
|
100
|
|
|
|
|
if (CUR_CHAR == '0') { |
|
284
|
2
|
|
|
|
|
|
state->special_flags = JSONSL_SPECIALf_ZERO|JSONSL_SPECIALf_SIGNED; |
|
285
|
4
|
50
|
|
|
|
|
} else if (isdigit(CUR_CHAR)) { |
|
286
|
4
|
|
|
|
|
|
state->special_flags = JSONSL_SPECIALf_SIGNED; |
|
287
|
4
|
|
|
|
|
|
state->nelem = CUR_CHAR - 0x30; |
|
288
|
|
|
|
|
|
|
} else { |
|
289
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(INVALID_NUMBER); |
|
290
|
|
|
|
|
|
|
} |
|
291
|
|
|
|
|
|
|
|
|
292
|
6
|
|
|
|
|
|
goto GT_NEXT; |
|
293
|
|
|
|
|
|
|
|
|
294
|
99
|
100
|
|
|
|
|
} else if (state->special_flags == JSONSL_SPECIALf_ZERO) { |
|
295
|
7
|
100
|
|
|
|
|
if (isdigit(CUR_CHAR)) { |
|
296
|
|
|
|
|
|
|
/* Following a zero! */ |
|
297
|
2
|
0
|
|
|
|
|
INVOKE_ERROR(INVALID_NUMBER); |
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
/* Unset the 'zero' flag: */ |
|
300
|
5
|
50
|
|
|
|
|
if (state->special_flags & JSONSL_SPECIALf_SIGNED) { |
|
301
|
0
|
|
|
|
|
|
state->special_flags = JSONSL_SPECIALf_SIGNED; |
|
302
|
|
|
|
|
|
|
} else { |
|
303
|
5
|
|
|
|
|
|
state->special_flags = JSONSL_SPECIALf_UNSIGNED; |
|
304
|
|
|
|
|
|
|
} |
|
305
|
5
|
|
|
|
|
|
goto GT_SPECIAL_NUMERIC; |
|
306
|
|
|
|
|
|
|
} |
|
307
|
|
|
|
|
|
|
|
|
308
|
92
|
100
|
|
|
|
|
if (state->special_flags & JSONSL_SPECIALf_NUMERIC) { |
|
309
|
|
|
|
|
|
|
GT_SPECIAL_NUMERIC: |
|
310
|
90
|
|
|
|
|
|
switch (CUR_CHAR) { |
|
311
|
|
|
|
|
|
|
CASE_DIGITS |
|
312
|
37
|
|
|
|
|
|
STATE_NUM_LAST = '1'; |
|
313
|
37
|
|
|
|
|
|
goto GT_NEXT; |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
case '.': |
|
316
|
9
|
50
|
|
|
|
|
if (state->special_flags & JSONSL_SPECIALf_FLOAT) { |
|
317
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(INVALID_NUMBER); |
|
318
|
|
|
|
|
|
|
} |
|
319
|
9
|
|
|
|
|
|
state->special_flags |= JSONSL_SPECIALf_FLOAT; |
|
320
|
9
|
|
|
|
|
|
STATE_NUM_LAST = '.'; |
|
321
|
9
|
|
|
|
|
|
goto GT_NEXT; |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
case 'e': |
|
324
|
|
|
|
|
|
|
case 'E': |
|
325
|
9
|
50
|
|
|
|
|
if (state->special_flags & JSONSL_SPECIALf_EXPONENT) { |
|
326
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(INVALID_NUMBER); |
|
327
|
|
|
|
|
|
|
} |
|
328
|
9
|
|
|
|
|
|
state->special_flags |= JSONSL_SPECIALf_EXPONENT; |
|
329
|
9
|
|
|
|
|
|
STATE_NUM_LAST = 'e'; |
|
330
|
9
|
|
|
|
|
|
goto GT_NEXT; |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
case '-': |
|
333
|
|
|
|
|
|
|
case '+': |
|
334
|
4
|
50
|
|
|
|
|
if (STATE_NUM_LAST != 'e') { |
|
335
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(INVALID_NUMBER); |
|
336
|
|
|
|
|
|
|
} |
|
337
|
4
|
|
|
|
|
|
STATE_NUM_LAST = '-'; |
|
338
|
4
|
|
|
|
|
|
goto GT_NEXT; |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
default: |
|
341
|
31
|
50
|
|
|
|
|
if (is_special_end(CUR_CHAR)) { |
|
342
|
31
|
|
|
|
|
|
goto GT_SPECIAL_POP; |
|
343
|
|
|
|
|
|
|
} |
|
344
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(INVALID_NUMBER); |
|
345
|
|
|
|
|
|
|
break; |
|
346
|
|
|
|
|
|
|
} |
|
347
|
|
|
|
|
|
|
} |
|
348
|
|
|
|
|
|
|
/* else if (!NUMERIC) */ |
|
349
|
31
|
100
|
|
|
|
|
if (!is_special_end(CUR_CHAR)) { |
|
350
|
24
|
|
|
|
|
|
STATE_SPECIAL_LENGTH++; |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
/* Verify TRUE, FALSE, NULL */ |
|
353
|
24
|
100
|
|
|
|
|
if (state->special_flags == JSONSL_SPECIALf_TRUE) { |
|
354
|
6
|
50
|
|
|
|
|
VERIFY_SPECIAL("true"); |
|
|
|
0
|
|
|
|
|
|
|
355
|
18
|
100
|
|
|
|
|
} else if (state->special_flags == JSONSL_SPECIALf_FALSE) { |
|
356
|
8
|
50
|
|
|
|
|
VERIFY_SPECIAL("false"); |
|
|
|
0
|
|
|
|
|
|
|
357
|
10
|
50
|
|
|
|
|
} else if (state->special_flags == JSONSL_SPECIALf_NULL) { |
|
358
|
10
|
100
|
|
|
|
|
VERIFY_SPECIAL("null"); |
|
|
|
0
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
} |
|
360
|
|
|
|
|
|
|
INCR_METRIC(SPECIAL_FASTPATH); |
|
361
|
23
|
|
|
|
|
|
goto GT_NEXT; |
|
362
|
|
|
|
|
|
|
} |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
GT_SPECIAL_POP: |
|
365
|
38
|
100
|
|
|
|
|
if (IS_NORMAL_NUMBER) { |
|
|
|
100
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
/* Nothing */ |
|
367
|
21
|
50
|
|
|
|
|
} else if (state->special_flags == JSONSL_SPECIALf_ZERO || |
|
|
|
50
|
|
|
|
|
|
|
368
|
21
|
|
|
|
|
|
state->special_flags == (JSONSL_SPECIALf_ZERO|JSONSL_SPECIALf_SIGNED)) { |
|
369
|
|
|
|
|
|
|
/* 0 is unsigned! */ |
|
370
|
0
|
|
|
|
|
|
state->special_flags = JSONSL_SPECIALf_UNSIGNED; |
|
371
|
21
|
50
|
|
|
|
|
} else if (state->special_flags == JSONSL_SPECIALf_DASH) { |
|
372
|
|
|
|
|
|
|
/* Still in dash! */ |
|
373
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(INVALID_NUMBER); |
|
374
|
21
|
100
|
|
|
|
|
} else if (state->special_flags & JSONSL_SPECIALf_NUMERIC) { |
|
375
|
|
|
|
|
|
|
/* Check that we're not at the end of a token */ |
|
376
|
14
|
100
|
|
|
|
|
if (STATE_NUM_LAST != '1') { |
|
377
|
2
|
0
|
|
|
|
|
INVOKE_ERROR(INVALID_NUMBER); |
|
378
|
|
|
|
|
|
|
} |
|
379
|
7
|
100
|
|
|
|
|
} else if (state->special_flags == JSONSL_SPECIALf_TRUE) { |
|
380
|
2
|
50
|
|
|
|
|
if (STATE_SPECIAL_LENGTH != 4) { |
|
381
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(SPECIAL_INCOMPLETE); |
|
382
|
|
|
|
|
|
|
} |
|
383
|
2
|
|
|
|
|
|
state->nelem = 1; |
|
384
|
5
|
100
|
|
|
|
|
} else if (state->special_flags == JSONSL_SPECIALf_FALSE) { |
|
385
|
2
|
50
|
|
|
|
|
if (STATE_SPECIAL_LENGTH != 5) { |
|
386
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(SPECIAL_INCOMPLETE); |
|
387
|
|
|
|
|
|
|
} |
|
388
|
3
|
50
|
|
|
|
|
} else if (state->special_flags == JSONSL_SPECIALf_NULL) { |
|
389
|
3
|
50
|
|
|
|
|
if (STATE_SPECIAL_LENGTH != 4) { |
|
390
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(SPECIAL_INCOMPLETE); |
|
391
|
|
|
|
|
|
|
} |
|
392
|
|
|
|
|
|
|
} |
|
393
|
36
|
50
|
|
|
|
|
SPECIAL_POP; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
394
|
36
|
|
|
|
|
|
jsn->expecting = ','; |
|
395
|
36
|
100
|
|
|
|
|
if (is_allowed_whitespace(CUR_CHAR)) { |
|
396
|
2
|
|
|
|
|
|
goto GT_NEXT; |
|
397
|
|
|
|
|
|
|
} |
|
398
|
|
|
|
|
|
|
/** |
|
399
|
|
|
|
|
|
|
* This works because we have a non-whitespace token |
|
400
|
|
|
|
|
|
|
* which is not a special token. If this is a structural |
|
401
|
|
|
|
|
|
|
* character then it will be gracefully handled by the |
|
402
|
|
|
|
|
|
|
* switch statement. Otherwise it will default to the 'special' |
|
403
|
|
|
|
|
|
|
* state again, |
|
404
|
|
|
|
|
|
|
*/ |
|
405
|
34
|
|
|
|
|
|
goto GT_STRUCTURAL_TOKEN; |
|
406
|
5750
|
100
|
|
|
|
|
} else if (is_allowed_whitespace(CUR_CHAR)) { |
|
407
|
|
|
|
|
|
|
INCR_METRIC(ALLOWED_WHITESPACE); |
|
408
|
|
|
|
|
|
|
/* So we're not special. Harmless insignificant whitespace |
|
409
|
|
|
|
|
|
|
* passthrough |
|
410
|
|
|
|
|
|
|
*/ |
|
411
|
247
|
|
|
|
|
|
goto GT_NEXT; |
|
412
|
5503
|
100
|
|
|
|
|
} else if (extract_special(CUR_CHAR)) { |
|
413
|
|
|
|
|
|
|
/* not a string, whitespace, or structural token. must be special */ |
|
414
|
42
|
|
|
|
|
|
goto GT_SPECIAL_BEGIN; |
|
415
|
|
|
|
|
|
|
} |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
INCR_GENERIC(CUR_CHAR); |
|
418
|
|
|
|
|
|
|
|
|
419
|
5461
|
100
|
|
|
|
|
if (CUR_CHAR == '"') { |
|
420
|
|
|
|
|
|
|
GT_QUOTE: |
|
421
|
2229
|
|
|
|
|
|
jsn->can_insert = 0; |
|
422
|
2229
|
|
|
|
|
|
switch (state_type) { |
|
423
|
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
/* the end of a string or hash key */ |
|
425
|
|
|
|
|
|
|
case JSONSL_T_STRING: |
|
426
|
31
|
50
|
|
|
|
|
CALLBACK_AND_POP(STRING); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
427
|
31
|
|
|
|
|
|
goto GT_NEXT; |
|
428
|
|
|
|
|
|
|
case JSONSL_T_HKEY: |
|
429
|
1082
|
50
|
|
|
|
|
CALLBACK_AND_POP(HKEY); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
430
|
1082
|
|
|
|
|
|
goto GT_NEXT; |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
case JSONSL_T_OBJECT: |
|
433
|
1107
|
|
|
|
|
|
state->nelem++; |
|
434
|
1107
|
100
|
|
|
|
|
if ( (state->nelem-1) % 2 ) { |
|
435
|
|
|
|
|
|
|
/* Odd, this must be a hash value */ |
|
436
|
24
|
50
|
|
|
|
|
if (jsn->tok_last != ':') { |
|
437
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(MISSING_TOKEN); |
|
438
|
|
|
|
|
|
|
} |
|
439
|
24
|
|
|
|
|
|
jsn->expecting = ','; /* Can't figure out what to expect next */ |
|
440
|
24
|
|
|
|
|
|
jsn->tok_last = 0; |
|
441
|
|
|
|
|
|
|
|
|
442
|
24
|
50
|
|
|
|
|
STACK_PUSH; |
|
443
|
24
|
|
|
|
|
|
state->type = JSONSL_T_STRING; |
|
444
|
24
|
50
|
|
|
|
|
DO_CALLBACK(STRING, PUSH); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
} else { |
|
447
|
|
|
|
|
|
|
/* hash key */ |
|
448
|
1083
|
50
|
|
|
|
|
if (jsn->expecting != '"') { |
|
449
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(STRAY_TOKEN); |
|
450
|
|
|
|
|
|
|
} |
|
451
|
1083
|
|
|
|
|
|
jsn->tok_last = 0; |
|
452
|
1083
|
|
|
|
|
|
jsn->expecting = ':'; |
|
453
|
|
|
|
|
|
|
|
|
454
|
1083
|
100
|
|
|
|
|
STACK_PUSH; |
|
455
|
1082
|
|
|
|
|
|
state->type = JSONSL_T_HKEY; |
|
456
|
1082
|
50
|
|
|
|
|
DO_CALLBACK(HKEY, PUSH); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
} |
|
458
|
1106
|
|
|
|
|
|
goto GT_NEXT; |
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
case JSONSL_T_LIST: |
|
461
|
9
|
|
|
|
|
|
state->nelem++; |
|
462
|
9
|
50
|
|
|
|
|
STACK_PUSH; |
|
463
|
9
|
|
|
|
|
|
state->type = JSONSL_T_STRING; |
|
464
|
9
|
|
|
|
|
|
jsn->expecting = ','; |
|
465
|
9
|
|
|
|
|
|
jsn->tok_last = 0; |
|
466
|
9
|
50
|
|
|
|
|
DO_CALLBACK(STRING, PUSH); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
467
|
9
|
|
|
|
|
|
goto GT_NEXT; |
|
468
|
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
case JSONSL_T_SPECIAL: |
|
470
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(STRAY_TOKEN); |
|
471
|
|
|
|
|
|
|
break; |
|
472
|
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
default: |
|
474
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(STRING_OUTSIDE_CONTAINER); |
|
475
|
|
|
|
|
|
|
break; |
|
476
|
|
|
|
|
|
|
} /* switch(state->type) */ |
|
477
|
4345
|
50
|
|
|
|
|
} else if (CUR_CHAR == '\\') { |
|
478
|
|
|
|
|
|
|
GT_ESCAPE: |
|
479
|
|
|
|
|
|
|
INCR_METRIC(ESCAPES); |
|
480
|
|
|
|
|
|
|
/* Escape */ |
|
481
|
13
|
50
|
|
|
|
|
if ( (state->type & JSONSL_Tf_STRINGY) == 0 ) { |
|
482
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(ESCAPE_OUTSIDE_STRING); |
|
483
|
|
|
|
|
|
|
} |
|
484
|
13
|
|
|
|
|
|
state->nescapes++; |
|
485
|
13
|
|
|
|
|
|
jsn->in_escape = 1; |
|
486
|
13
|
|
|
|
|
|
goto GT_NEXT; |
|
487
|
|
|
|
|
|
|
} /* " or \ */ |
|
488
|
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
GT_STRUCTURAL_TOKEN: |
|
490
|
4379
|
|
|
|
|
|
switch (CUR_CHAR) { |
|
491
|
|
|
|
|
|
|
case ':': |
|
492
|
|
|
|
|
|
|
INCR_METRIC(STRUCTURAL_TOKEN); |
|
493
|
1082
|
50
|
|
|
|
|
if (jsn->expecting != CUR_CHAR) { |
|
494
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(STRAY_TOKEN); |
|
495
|
|
|
|
|
|
|
} |
|
496
|
1082
|
|
|
|
|
|
jsn->tok_last = ':'; |
|
497
|
1082
|
|
|
|
|
|
jsn->can_insert = 1; |
|
498
|
1082
|
|
|
|
|
|
jsn->expecting = '"'; |
|
499
|
1082
|
|
|
|
|
|
goto GT_NEXT; |
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
case ',': |
|
502
|
|
|
|
|
|
|
INCR_METRIC(STRUCTURAL_TOKEN); |
|
503
|
|
|
|
|
|
|
/** |
|
504
|
|
|
|
|
|
|
* The comma is one of the more generic tokens. |
|
505
|
|
|
|
|
|
|
* In the context of an OBJECT, the can_insert flag |
|
506
|
|
|
|
|
|
|
* should never be set, and no other action is |
|
507
|
|
|
|
|
|
|
* necessary. |
|
508
|
|
|
|
|
|
|
*/ |
|
509
|
29
|
50
|
|
|
|
|
if (jsn->expecting != CUR_CHAR) { |
|
510
|
|
|
|
|
|
|
/* make this branch execute only when we haven't manually |
|
511
|
|
|
|
|
|
|
* just placed the ',' in the expecting register. |
|
512
|
|
|
|
|
|
|
*/ |
|
513
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(STRAY_TOKEN); |
|
514
|
|
|
|
|
|
|
} |
|
515
|
|
|
|
|
|
|
|
|
516
|
29
|
100
|
|
|
|
|
if (state->type == JSONSL_T_OBJECT) { |
|
517
|
|
|
|
|
|
|
/* end of hash value, expect a string as a hash key */ |
|
518
|
17
|
|
|
|
|
|
jsn->expecting = '"'; |
|
519
|
|
|
|
|
|
|
} else { |
|
520
|
12
|
|
|
|
|
|
jsn->can_insert = 1; |
|
521
|
|
|
|
|
|
|
} |
|
522
|
|
|
|
|
|
|
|
|
523
|
29
|
|
|
|
|
|
jsn->tok_last = ','; |
|
524
|
29
|
|
|
|
|
|
jsn->expecting = '"'; |
|
525
|
29
|
|
|
|
|
|
goto GT_NEXT; |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
/* new list or object */ |
|
528
|
|
|
|
|
|
|
/* hashes are more common */ |
|
529
|
|
|
|
|
|
|
case '{': |
|
530
|
|
|
|
|
|
|
case '[': |
|
531
|
|
|
|
|
|
|
INCR_METRIC(STRUCTURAL_TOKEN); |
|
532
|
2152
|
50
|
|
|
|
|
if (!jsn->can_insert) { |
|
533
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(CANT_INSERT); |
|
534
|
|
|
|
|
|
|
} |
|
535
|
|
|
|
|
|
|
|
|
536
|
2152
|
100
|
|
|
|
|
ENSURE_HVAL; |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
537
|
2152
|
|
|
|
|
|
state->nelem++; |
|
538
|
|
|
|
|
|
|
|
|
539
|
2152
|
100
|
|
|
|
|
STACK_PUSH; |
|
540
|
|
|
|
|
|
|
/* because the constants match the opening delimiters, we can do this: */ |
|
541
|
2151
|
|
|
|
|
|
state->type = CUR_CHAR; |
|
542
|
2151
|
|
|
|
|
|
state->nelem = 0; |
|
543
|
2151
|
|
|
|
|
|
jsn->can_insert = 1; |
|
544
|
2151
|
100
|
|
|
|
|
if (CUR_CHAR == '{') { |
|
545
|
|
|
|
|
|
|
/* If we're a hash, we expect a key first, which is quouted */ |
|
546
|
1066
|
|
|
|
|
|
jsn->expecting = '"'; |
|
547
|
|
|
|
|
|
|
} |
|
548
|
2151
|
100
|
|
|
|
|
if (CUR_CHAR == JSONSL_T_OBJECT) { |
|
549
|
1066
|
50
|
|
|
|
|
DO_CALLBACK(OBJECT, PUSH); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
} else { |
|
551
|
1085
|
50
|
|
|
|
|
DO_CALLBACK(LIST, PUSH); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
} |
|
553
|
2151
|
|
|
|
|
|
jsn->tok_last = 0; |
|
554
|
2151
|
|
|
|
|
|
goto GT_NEXT; |
|
555
|
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
/* closing of list or object */ |
|
557
|
|
|
|
|
|
|
case '}': |
|
558
|
|
|
|
|
|
|
case ']': |
|
559
|
|
|
|
|
|
|
INCR_METRIC(STRUCTURAL_TOKEN); |
|
560
|
1111
|
50
|
|
|
|
|
if (jsn->tok_last == ',' && jsn->options.allow_trailing_comma == 0) { |
|
|
|
0
|
|
|
|
|
|
|
561
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(TRAILING_COMMA); |
|
562
|
|
|
|
|
|
|
} |
|
563
|
|
|
|
|
|
|
|
|
564
|
1111
|
|
|
|
|
|
jsn->can_insert = 0; |
|
565
|
1111
|
|
|
|
|
|
jsn->level--; |
|
566
|
1111
|
|
|
|
|
|
jsn->expecting = ','; |
|
567
|
1111
|
|
|
|
|
|
jsn->tok_last = 0; |
|
568
|
1111
|
100
|
|
|
|
|
if (CUR_CHAR == ']') { |
|
569
|
572
|
50
|
|
|
|
|
if (state->type != '[') { |
|
570
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(BRACKET_MISMATCH); |
|
571
|
|
|
|
|
|
|
} |
|
572
|
572
|
50
|
|
|
|
|
DO_CALLBACK(LIST, POP); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
} else { |
|
574
|
539
|
50
|
|
|
|
|
if (state->type != '{') { |
|
575
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(BRACKET_MISMATCH); |
|
576
|
539
|
50
|
|
|
|
|
} else if (state->nelem && state->nelem % 2 != 0) { |
|
|
|
50
|
|
|
|
|
|
|
577
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(VALUE_EXPECTED); |
|
578
|
|
|
|
|
|
|
} |
|
579
|
539
|
50
|
|
|
|
|
DO_CALLBACK(OBJECT, POP); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
} |
|
581
|
1111
|
|
|
|
|
|
state = jsn->stack + jsn->level; |
|
582
|
1111
|
|
|
|
|
|
state->pos_cur = jsn->pos; |
|
583
|
1111
|
|
|
|
|
|
goto GT_NEXT; |
|
584
|
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
default: |
|
586
|
|
|
|
|
|
|
GT_SPECIAL_BEGIN: |
|
587
|
|
|
|
|
|
|
/** |
|
588
|
|
|
|
|
|
|
* Not a string, not a structural token, and not benign whitespace. |
|
589
|
|
|
|
|
|
|
* Technically we should iterate over the character always, but since |
|
590
|
|
|
|
|
|
|
* we are not doing full numerical/value decoding anyway (but only hinting), |
|
591
|
|
|
|
|
|
|
* we only check upon entry. |
|
592
|
|
|
|
|
|
|
*/ |
|
593
|
47
|
50
|
|
|
|
|
if (state->type != JSONSL_T_SPECIAL) { |
|
594
|
47
|
|
|
|
|
|
int special_flags = extract_special(CUR_CHAR); |
|
595
|
47
|
100
|
|
|
|
|
if (!special_flags) { |
|
596
|
|
|
|
|
|
|
/** |
|
597
|
|
|
|
|
|
|
* Try to do some heuristics here anyway to figure out what kind of |
|
598
|
|
|
|
|
|
|
* error this is. The 'special' case is a fallback scenario anyway. |
|
599
|
|
|
|
|
|
|
*/ |
|
600
|
5
|
50
|
|
|
|
|
if (CUR_CHAR == '\0') { |
|
601
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(FOUND_NULL_BYTE); |
|
602
|
5
|
100
|
|
|
|
|
} else if (CUR_CHAR < 0x20) { |
|
603
|
1
|
0
|
|
|
|
|
INVOKE_ERROR(WEIRD_WHITESPACE); |
|
604
|
|
|
|
|
|
|
} else { |
|
605
|
4
|
0
|
|
|
|
|
INVOKE_ERROR(SPECIAL_EXPECTED); |
|
606
|
|
|
|
|
|
|
} |
|
607
|
|
|
|
|
|
|
} |
|
608
|
42
|
100
|
|
|
|
|
ENSURE_HVAL; |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
609
|
42
|
|
|
|
|
|
state->nelem++; |
|
610
|
42
|
50
|
|
|
|
|
if (!jsn->can_insert) { |
|
611
|
0
|
0
|
|
|
|
|
INVOKE_ERROR(CANT_INSERT); |
|
612
|
|
|
|
|
|
|
} |
|
613
|
42
|
50
|
|
|
|
|
STACK_PUSH; |
|
614
|
42
|
|
|
|
|
|
state->type = JSONSL_T_SPECIAL; |
|
615
|
42
|
|
|
|
|
|
state->special_flags = special_flags; |
|
616
|
42
|
|
|
|
|
|
STATE_SPECIAL_LENGTH = 1; |
|
617
|
|
|
|
|
|
|
|
|
618
|
42
|
100
|
|
|
|
|
if (special_flags == JSONSL_SPECIALf_UNSIGNED) { |
|
619
|
20
|
|
|
|
|
|
state->nelem = CUR_CHAR - 0x30; |
|
620
|
20
|
|
|
|
|
|
STATE_NUM_LAST = '1'; |
|
621
|
|
|
|
|
|
|
} else { |
|
622
|
22
|
|
|
|
|
|
STATE_NUM_LAST = '-'; |
|
623
|
22
|
|
|
|
|
|
state->nelem = 0; |
|
624
|
|
|
|
|
|
|
} |
|
625
|
42
|
50
|
|
|
|
|
DO_CALLBACK(SPECIAL, PUSH); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
} |
|
627
|
42
|
|
|
|
|
|
goto GT_NEXT; |
|
628
|
|
|
|
|
|
|
} |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
GT_NEXT: |
|
631
|
7519
|
|
|
|
|
|
continue; |
|
632
|
|
|
|
|
|
|
} |
|
633
|
|
|
|
|
|
|
} |
|
634
|
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
JSONSL_API |
|
636
|
15
|
|
|
|
|
|
const char* jsonsl_strerror(jsonsl_error_t err) |
|
637
|
|
|
|
|
|
|
{ |
|
638
|
15
|
50
|
|
|
|
|
if (err == JSONSL_ERROR_SUCCESS) { |
|
639
|
0
|
|
|
|
|
|
return "SUCCESS"; |
|
640
|
|
|
|
|
|
|
} |
|
641
|
|
|
|
|
|
|
#define X(t) \ |
|
642
|
|
|
|
|
|
|
if (err == JSONSL_ERROR_##t) \ |
|
643
|
|
|
|
|
|
|
return #t; |
|
644
|
15
|
50
|
|
|
|
|
JSONSL_XERR; |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
#undef X |
|
646
|
0
|
|
|
|
|
|
return ""; |
|
647
|
|
|
|
|
|
|
} |
|
648
|
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
JSONSL_API |
|
650
|
0
|
|
|
|
|
|
const char *jsonsl_strtype(jsonsl_type_t type) |
|
651
|
|
|
|
|
|
|
{ |
|
652
|
|
|
|
|
|
|
#define X(o,c) \ |
|
653
|
|
|
|
|
|
|
if (type == JSONSL_T_##o) \ |
|
654
|
|
|
|
|
|
|
return #o; |
|
655
|
0
|
0
|
|
|
|
|
JSONSL_XTYPE |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
#undef X |
|
657
|
0
|
|
|
|
|
|
return "UNKNOWN TYPE"; |
|
658
|
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
} |
|
660
|
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
/* |
|
662
|
|
|
|
|
|
|
* |
|
663
|
|
|
|
|
|
|
* JPR/JSONPointer functions |
|
664
|
|
|
|
|
|
|
* |
|
665
|
|
|
|
|
|
|
* |
|
666
|
|
|
|
|
|
|
*/ |
|
667
|
|
|
|
|
|
|
#ifndef JSONSL_NO_JPR |
|
668
|
|
|
|
|
|
|
static |
|
669
|
|
|
|
|
|
|
jsonsl_jpr_type_t |
|
670
|
5
|
|
|
|
|
|
populate_component(char *in, |
|
671
|
|
|
|
|
|
|
struct jsonsl_jpr_component_st *component, |
|
672
|
|
|
|
|
|
|
char **next, |
|
673
|
|
|
|
|
|
|
jsonsl_error_t *errp) |
|
674
|
|
|
|
|
|
|
{ |
|
675
|
|
|
|
|
|
|
unsigned long pctval; |
|
676
|
5
|
|
|
|
|
|
char *c = NULL, *outp = NULL, *end = NULL; |
|
677
|
|
|
|
|
|
|
size_t input_len; |
|
678
|
5
|
|
|
|
|
|
jsonsl_jpr_type_t ret = JSONSL_PATH_NONE; |
|
679
|
|
|
|
|
|
|
|
|
680
|
5
|
50
|
|
|
|
|
if (*next == NULL || *(*next) == '\0') { |
|
|
|
50
|
|
|
|
|
|
|
681
|
0
|
|
|
|
|
|
return JSONSL_PATH_NONE; |
|
682
|
|
|
|
|
|
|
} |
|
683
|
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
/* Replace the next / with a NULL */ |
|
685
|
5
|
|
|
|
|
|
*next = strstr(in, "/"); |
|
686
|
5
|
100
|
|
|
|
|
if (*next != NULL) { |
|
687
|
1
|
|
|
|
|
|
*(*next) = '\0'; /* drop the forward slash */ |
|
688
|
1
|
|
|
|
|
|
input_len = *next - in; |
|
689
|
1
|
|
|
|
|
|
end = *next; |
|
690
|
1
|
|
|
|
|
|
*next += 1; /* next character after the '/' */ |
|
691
|
|
|
|
|
|
|
} else { |
|
692
|
4
|
|
|
|
|
|
input_len = strlen(in); |
|
693
|
4
|
|
|
|
|
|
end = in + input_len + 1; |
|
694
|
|
|
|
|
|
|
} |
|
695
|
|
|
|
|
|
|
|
|
696
|
5
|
|
|
|
|
|
component->pstr = in; |
|
697
|
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
/* Check for special components of interest */ |
|
699
|
5
|
100
|
|
|
|
|
if (*in == JSONSL_PATH_WILDCARD_CHAR && input_len == 1) { |
|
|
|
50
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
/* Lone wildcard */ |
|
701
|
4
|
|
|
|
|
|
ret = JSONSL_PATH_WILDCARD; |
|
702
|
4
|
|
|
|
|
|
goto GT_RET; |
|
703
|
1
|
50
|
|
|
|
|
} else if (isdigit(*in)) { |
|
704
|
|
|
|
|
|
|
/* ASCII Numeric */ |
|
705
|
|
|
|
|
|
|
char *endptr; |
|
706
|
0
|
|
|
|
|
|
component->idx = strtoul(in, &endptr, 10); |
|
707
|
0
|
0
|
|
|
|
|
if (endptr && *endptr == '\0') { |
|
|
|
0
|
|
|
|
|
|
|
708
|
0
|
|
|
|
|
|
ret = JSONSL_PATH_NUMERIC; |
|
709
|
0
|
|
|
|
|
|
goto GT_RET; |
|
710
|
|
|
|
|
|
|
} |
|
711
|
|
|
|
|
|
|
} |
|
712
|
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
/* Default, it's a string */ |
|
714
|
1
|
|
|
|
|
|
ret = JSONSL_PATH_STRING; |
|
715
|
9
|
100
|
|
|
|
|
for (c = outp = in; c < end; c++, outp++) { |
|
716
|
|
|
|
|
|
|
char origc; |
|
717
|
8
|
50
|
|
|
|
|
if (*c != '%') { |
|
718
|
8
|
|
|
|
|
|
goto GT_ASSIGN; |
|
719
|
|
|
|
|
|
|
} |
|
720
|
|
|
|
|
|
|
/* |
|
721
|
|
|
|
|
|
|
* c = { [+0] = '%', [+1] = 'b', [+2] = 'e', [+3] = '\0' } |
|
722
|
|
|
|
|
|
|
*/ |
|
723
|
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
/* Need %XX */ |
|
725
|
0
|
0
|
|
|
|
|
if (c+2 >= end) { |
|
726
|
0
|
|
|
|
|
|
*errp = JSONSL_ERROR_PERCENT_BADHEX; |
|
727
|
0
|
|
|
|
|
|
return JSONSL_PATH_INVALID; |
|
728
|
|
|
|
|
|
|
} |
|
729
|
0
|
0
|
|
|
|
|
if (! (isxdigit(*(c+1)) && isxdigit(*(c+2))) ) { |
|
|
|
0
|
|
|
|
|
|
|
730
|
0
|
|
|
|
|
|
*errp = JSONSL_ERROR_PERCENT_BADHEX; |
|
731
|
0
|
|
|
|
|
|
return JSONSL_PATH_INVALID; |
|
732
|
|
|
|
|
|
|
} |
|
733
|
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
/* Temporarily null-terminate the characters */ |
|
735
|
0
|
|
|
|
|
|
origc = *(c+3); |
|
736
|
0
|
|
|
|
|
|
*(c+3) = '\0'; |
|
737
|
0
|
|
|
|
|
|
pctval = strtoul(c+1, NULL, 16); |
|
738
|
0
|
|
|
|
|
|
*(c+3) = origc; |
|
739
|
|
|
|
|
|
|
|
|
740
|
0
|
|
|
|
|
|
*outp = (char) pctval; |
|
741
|
0
|
|
|
|
|
|
c += 2; |
|
742
|
0
|
|
|
|
|
|
continue; |
|
743
|
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
GT_ASSIGN: |
|
745
|
8
|
|
|
|
|
|
*outp = *c; |
|
746
|
|
|
|
|
|
|
} |
|
747
|
|
|
|
|
|
|
/* Null-terminate the string */ |
|
748
|
1
|
50
|
|
|
|
|
for (; outp < c; outp++) { |
|
749
|
0
|
|
|
|
|
|
*outp = '\0'; |
|
750
|
|
|
|
|
|
|
} |
|
751
|
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
GT_RET: |
|
753
|
5
|
|
|
|
|
|
component->ptype = ret; |
|
754
|
5
|
100
|
|
|
|
|
if (ret != JSONSL_PATH_WILDCARD) { |
|
755
|
1
|
|
|
|
|
|
component->len = strlen(component->pstr); |
|
756
|
|
|
|
|
|
|
} |
|
757
|
5
|
|
|
|
|
|
return ret; |
|
758
|
|
|
|
|
|
|
} |
|
759
|
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
JSONSL_API |
|
761
|
|
|
|
|
|
|
jsonsl_jpr_t |
|
762
|
4
|
|
|
|
|
|
jsonsl_jpr_new(const char *path, jsonsl_error_t *errp) |
|
763
|
|
|
|
|
|
|
{ |
|
764
|
4
|
|
|
|
|
|
char *my_copy = NULL; |
|
765
|
|
|
|
|
|
|
int count, curidx; |
|
766
|
4
|
|
|
|
|
|
struct jsonsl_jpr_st *ret = NULL; |
|
767
|
4
|
|
|
|
|
|
struct jsonsl_jpr_component_st *components = NULL; |
|
768
|
|
|
|
|
|
|
size_t origlen; |
|
769
|
|
|
|
|
|
|
jsonsl_error_t errstacked; |
|
770
|
|
|
|
|
|
|
|
|
771
|
|
|
|
|
|
|
#define JPR_BAIL(err) *errp = err; goto GT_ERROR; |
|
772
|
|
|
|
|
|
|
|
|
773
|
4
|
50
|
|
|
|
|
if (errp == NULL) { |
|
774
|
0
|
|
|
|
|
|
errp = &errstacked; |
|
775
|
|
|
|
|
|
|
} |
|
776
|
|
|
|
|
|
|
|
|
777
|
4
|
50
|
|
|
|
|
if (path == NULL || *path != '/') { |
|
|
|
50
|
|
|
|
|
|
|
778
|
0
|
|
|
|
|
|
JPR_BAIL(JSONSL_ERROR_JPR_NOROOT); |
|
779
|
|
|
|
|
|
|
return NULL; |
|
780
|
|
|
|
|
|
|
} |
|
781
|
|
|
|
|
|
|
|
|
782
|
4
|
|
|
|
|
|
count = 1; |
|
783
|
4
|
|
|
|
|
|
path++; |
|
784
|
|
|
|
|
|
|
{ |
|
785
|
4
|
|
|
|
|
|
const char *c = path; |
|
786
|
16
|
100
|
|
|
|
|
for (; *c; c++) { |
|
787
|
12
|
100
|
|
|
|
|
if (*c == '/') { |
|
788
|
1
|
|
|
|
|
|
count++; |
|
789
|
1
|
50
|
|
|
|
|
if (*(c+1) == '/') { |
|
790
|
0
|
|
|
|
|
|
JPR_BAIL(JSONSL_ERROR_JPR_DUPSLASH); |
|
791
|
|
|
|
|
|
|
} |
|
792
|
|
|
|
|
|
|
} |
|
793
|
|
|
|
|
|
|
} |
|
794
|
|
|
|
|
|
|
} |
|
795
|
4
|
50
|
|
|
|
|
if(*path) { |
|
796
|
4
|
|
|
|
|
|
count++; |
|
797
|
|
|
|
|
|
|
} |
|
798
|
|
|
|
|
|
|
|
|
799
|
4
|
|
|
|
|
|
components = (struct jsonsl_jpr_component_st *) |
|
800
|
4
|
|
|
|
|
|
malloc(sizeof(*components) * count); |
|
801
|
4
|
50
|
|
|
|
|
if (!components) { |
|
802
|
0
|
|
|
|
|
|
JPR_BAIL(JSONSL_ERROR_ENOMEM); |
|
803
|
|
|
|
|
|
|
} |
|
804
|
|
|
|
|
|
|
|
|
805
|
4
|
|
|
|
|
|
my_copy = (char *)malloc(strlen(path) + 1); |
|
806
|
4
|
50
|
|
|
|
|
if (!my_copy) { |
|
807
|
0
|
|
|
|
|
|
JPR_BAIL(JSONSL_ERROR_ENOMEM); |
|
808
|
|
|
|
|
|
|
} |
|
809
|
|
|
|
|
|
|
|
|
810
|
4
|
|
|
|
|
|
strcpy(my_copy, path); |
|
811
|
|
|
|
|
|
|
|
|
812
|
4
|
|
|
|
|
|
components[0].ptype = JSONSL_PATH_ROOT; |
|
813
|
|
|
|
|
|
|
|
|
814
|
4
|
50
|
|
|
|
|
if (*my_copy) { |
|
815
|
4
|
|
|
|
|
|
char *cur = my_copy; |
|
816
|
4
|
|
|
|
|
|
int pathret = JSONSL_PATH_STRING; |
|
817
|
4
|
|
|
|
|
|
curidx = 1; |
|
818
|
9
|
50
|
|
|
|
|
while (pathret > 0 && curidx < count) { |
|
|
|
100
|
|
|
|
|
|
|
819
|
5
|
|
|
|
|
|
pathret = populate_component(cur, components + curidx, &cur, errp); |
|
820
|
5
|
50
|
|
|
|
|
if (pathret > 0) { |
|
821
|
5
|
|
|
|
|
|
curidx++; |
|
822
|
|
|
|
|
|
|
} else { |
|
823
|
0
|
|
|
|
|
|
break; |
|
824
|
|
|
|
|
|
|
} |
|
825
|
|
|
|
|
|
|
} |
|
826
|
|
|
|
|
|
|
|
|
827
|
4
|
50
|
|
|
|
|
if (pathret == JSONSL_PATH_INVALID) { |
|
828
|
4
|
|
|
|
|
|
JPR_BAIL(JSONSL_ERROR_JPR_BADPATH); |
|
829
|
|
|
|
|
|
|
} |
|
830
|
|
|
|
|
|
|
} else { |
|
831
|
0
|
|
|
|
|
|
curidx = 1; |
|
832
|
|
|
|
|
|
|
} |
|
833
|
|
|
|
|
|
|
|
|
834
|
4
|
|
|
|
|
|
path--; /*revert path to leading '/' */ |
|
835
|
4
|
|
|
|
|
|
origlen = strlen(path) + 1; |
|
836
|
4
|
|
|
|
|
|
ret = (struct jsonsl_jpr_st *)malloc(sizeof(*ret)); |
|
837
|
4
|
50
|
|
|
|
|
if (!ret) { |
|
838
|
0
|
|
|
|
|
|
JPR_BAIL(JSONSL_ERROR_ENOMEM); |
|
839
|
|
|
|
|
|
|
} |
|
840
|
4
|
|
|
|
|
|
ret->orig = (char *)malloc(origlen); |
|
841
|
4
|
50
|
|
|
|
|
if (!ret->orig) { |
|
842
|
0
|
|
|
|
|
|
JPR_BAIL(JSONSL_ERROR_ENOMEM); |
|
843
|
|
|
|
|
|
|
} |
|
844
|
4
|
|
|
|
|
|
ret->components = components; |
|
845
|
4
|
|
|
|
|
|
ret->ncomponents = curidx; |
|
846
|
4
|
|
|
|
|
|
ret->basestr = my_copy; |
|
847
|
4
|
|
|
|
|
|
ret->norig = origlen-1; |
|
848
|
4
|
|
|
|
|
|
strcpy(ret->orig, path); |
|
849
|
|
|
|
|
|
|
|
|
850
|
4
|
|
|
|
|
|
return ret; |
|
851
|
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
GT_ERROR: |
|
853
|
0
|
|
|
|
|
|
free(my_copy); |
|
854
|
0
|
|
|
|
|
|
free(components); |
|
855
|
0
|
0
|
|
|
|
|
if (ret) { |
|
856
|
0
|
|
|
|
|
|
free(ret->orig); |
|
857
|
|
|
|
|
|
|
} |
|
858
|
0
|
|
|
|
|
|
free(ret); |
|
859
|
4
|
|
|
|
|
|
return NULL; |
|
860
|
|
|
|
|
|
|
#undef JPR_BAIL |
|
861
|
|
|
|
|
|
|
} |
|
862
|
|
|
|
|
|
|
|
|
863
|
4
|
|
|
|
|
|
void jsonsl_jpr_destroy(jsonsl_jpr_t jpr) |
|
864
|
|
|
|
|
|
|
{ |
|
865
|
4
|
|
|
|
|
|
free(jpr->components); |
|
866
|
4
|
|
|
|
|
|
free(jpr->basestr); |
|
867
|
4
|
|
|
|
|
|
free(jpr->orig); |
|
868
|
4
|
|
|
|
|
|
free(jpr); |
|
869
|
4
|
|
|
|
|
|
} |
|
870
|
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
JSONSL_API |
|
872
|
|
|
|
|
|
|
jsonsl_jpr_match_t |
|
873
|
18
|
|
|
|
|
|
jsonsl_jpr_match(jsonsl_jpr_t jpr, |
|
874
|
|
|
|
|
|
|
unsigned int parent_type, |
|
875
|
|
|
|
|
|
|
unsigned int parent_level, |
|
876
|
|
|
|
|
|
|
const char *key, |
|
877
|
|
|
|
|
|
|
size_t nkey) |
|
878
|
|
|
|
|
|
|
{ |
|
879
|
|
|
|
|
|
|
/* find our current component. This is the child level */ |
|
880
|
|
|
|
|
|
|
int cmpret; |
|
881
|
|
|
|
|
|
|
struct jsonsl_jpr_component_st *p_component; |
|
882
|
18
|
|
|
|
|
|
p_component = jpr->components + parent_level; |
|
883
|
|
|
|
|
|
|
|
|
884
|
18
|
50
|
|
|
|
|
if (parent_level >= jpr->ncomponents) { |
|
885
|
0
|
|
|
|
|
|
return JSONSL_MATCH_NOMATCH; |
|
886
|
|
|
|
|
|
|
} |
|
887
|
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
/* Lone query for 'root' element. Always matches */ |
|
889
|
18
|
100
|
|
|
|
|
if (parent_level == 0) { |
|
890
|
6
|
50
|
|
|
|
|
if (jpr->ncomponents == 1) { |
|
891
|
0
|
|
|
|
|
|
return JSONSL_MATCH_COMPLETE; |
|
892
|
|
|
|
|
|
|
} else { |
|
893
|
6
|
|
|
|
|
|
return JSONSL_MATCH_POSSIBLE; |
|
894
|
|
|
|
|
|
|
} |
|
895
|
|
|
|
|
|
|
} |
|
896
|
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
/* Wildcard, always matches */ |
|
898
|
12
|
100
|
|
|
|
|
if (p_component->ptype == JSONSL_PATH_WILDCARD) { |
|
899
|
9
|
100
|
|
|
|
|
if (parent_level == jpr->ncomponents-1) { |
|
900
|
6
|
|
|
|
|
|
return JSONSL_MATCH_COMPLETE; |
|
901
|
|
|
|
|
|
|
} else { |
|
902
|
3
|
|
|
|
|
|
return JSONSL_MATCH_POSSIBLE; |
|
903
|
|
|
|
|
|
|
} |
|
904
|
|
|
|
|
|
|
} |
|
905
|
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
/* Check numeric array index. This gets its special block so we can avoid |
|
907
|
|
|
|
|
|
|
* string comparisons */ |
|
908
|
3
|
50
|
|
|
|
|
if (p_component->ptype == JSONSL_PATH_NUMERIC) { |
|
909
|
0
|
0
|
|
|
|
|
if (parent_type == JSONSL_T_LIST) { |
|
910
|
0
|
0
|
|
|
|
|
if (p_component->idx != nkey) { |
|
911
|
|
|
|
|
|
|
/* Wrong index */ |
|
912
|
0
|
|
|
|
|
|
return JSONSL_MATCH_NOMATCH; |
|
913
|
|
|
|
|
|
|
} else { |
|
914
|
0
|
0
|
|
|
|
|
if (parent_level == jpr->ncomponents-1) { |
|
915
|
|
|
|
|
|
|
/* This is the last element of the path */ |
|
916
|
0
|
|
|
|
|
|
return JSONSL_MATCH_COMPLETE; |
|
917
|
|
|
|
|
|
|
} else { |
|
918
|
|
|
|
|
|
|
/* Intermediate element */ |
|
919
|
0
|
|
|
|
|
|
return JSONSL_MATCH_POSSIBLE; |
|
920
|
|
|
|
|
|
|
} |
|
921
|
|
|
|
|
|
|
} |
|
922
|
0
|
0
|
|
|
|
|
} else if (p_component->is_arridx) { |
|
923
|
|
|
|
|
|
|
/* Numeric and an array index (set explicitly by user). But not |
|
924
|
|
|
|
|
|
|
* a list for a parent */ |
|
925
|
0
|
|
|
|
|
|
return JSONSL_MATCH_TYPE_MISMATCH; |
|
926
|
|
|
|
|
|
|
} |
|
927
|
3
|
50
|
|
|
|
|
} else if (parent_type == JSONSL_T_LIST) { |
|
928
|
0
|
|
|
|
|
|
return JSONSL_MATCH_TYPE_MISMATCH; |
|
929
|
|
|
|
|
|
|
} |
|
930
|
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
/* Check lengths */ |
|
932
|
3
|
100
|
|
|
|
|
if (p_component->len != nkey) { |
|
933
|
1
|
|
|
|
|
|
return JSONSL_MATCH_NOMATCH; |
|
934
|
|
|
|
|
|
|
} |
|
935
|
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
/* Check string comparison */ |
|
937
|
2
|
|
|
|
|
|
cmpret = strncmp(p_component->pstr, key, nkey); |
|
938
|
2
|
50
|
|
|
|
|
if (cmpret == 0) { |
|
939
|
2
|
50
|
|
|
|
|
if (parent_level == jpr->ncomponents-1) { |
|
940
|
2
|
|
|
|
|
|
return JSONSL_MATCH_COMPLETE; |
|
941
|
|
|
|
|
|
|
} else { |
|
942
|
0
|
|
|
|
|
|
return JSONSL_MATCH_POSSIBLE; |
|
943
|
|
|
|
|
|
|
} |
|
944
|
|
|
|
|
|
|
} |
|
945
|
|
|
|
|
|
|
|
|
946
|
0
|
|
|
|
|
|
return JSONSL_MATCH_NOMATCH; |
|
947
|
|
|
|
|
|
|
} |
|
948
|
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
JSONSL_API |
|
950
|
4
|
|
|
|
|
|
void jsonsl_jpr_match_state_init(jsonsl_t jsn, |
|
951
|
|
|
|
|
|
|
jsonsl_jpr_t *jprs, |
|
952
|
|
|
|
|
|
|
size_t njprs) |
|
953
|
|
|
|
|
|
|
{ |
|
954
|
|
|
|
|
|
|
size_t ii, *firstjmp; |
|
955
|
4
|
50
|
|
|
|
|
if (njprs == 0) { |
|
956
|
0
|
|
|
|
|
|
return; |
|
957
|
|
|
|
|
|
|
} |
|
958
|
4
|
|
|
|
|
|
jsn->jprs = (jsonsl_jpr_t *)malloc(sizeof(jsonsl_jpr_t) * njprs); |
|
959
|
4
|
|
|
|
|
|
jsn->jpr_count = njprs; |
|
960
|
4
|
|
|
|
|
|
jsn->jpr_root = (size_t*)calloc(1, sizeof(size_t) * njprs * jsn->levels_max); |
|
961
|
4
|
|
|
|
|
|
memcpy(jsn->jprs, jprs, sizeof(jsonsl_jpr_t) * njprs); |
|
962
|
|
|
|
|
|
|
/* Set the initial jump table values */ |
|
963
|
|
|
|
|
|
|
|
|
964
|
4
|
|
|
|
|
|
firstjmp = jsn->jpr_root; |
|
965
|
8
|
100
|
|
|
|
|
for (ii = 0; ii < njprs; ii++) { |
|
966
|
4
|
|
|
|
|
|
firstjmp[ii] = ii+1; |
|
967
|
|
|
|
|
|
|
} |
|
968
|
|
|
|
|
|
|
} |
|
969
|
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
JSONSL_API |
|
971
|
24
|
|
|
|
|
|
void jsonsl_jpr_match_state_cleanup(jsonsl_t jsn) |
|
972
|
|
|
|
|
|
|
{ |
|
973
|
24
|
100
|
|
|
|
|
if (jsn->jpr_count == 0) { |
|
974
|
20
|
|
|
|
|
|
return; |
|
975
|
|
|
|
|
|
|
} |
|
976
|
|
|
|
|
|
|
|
|
977
|
4
|
|
|
|
|
|
free(jsn->jpr_root); |
|
978
|
4
|
|
|
|
|
|
free(jsn->jprs); |
|
979
|
4
|
|
|
|
|
|
jsn->jprs = NULL; |
|
980
|
4
|
|
|
|
|
|
jsn->jpr_root = NULL; |
|
981
|
4
|
|
|
|
|
|
jsn->jpr_count = 0; |
|
982
|
|
|
|
|
|
|
} |
|
983
|
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
/** |
|
985
|
|
|
|
|
|
|
* This function should be called exactly once on each element... |
|
986
|
|
|
|
|
|
|
* This should also be called in recursive order, since we rely |
|
987
|
|
|
|
|
|
|
* on the parent having been initalized for a match. |
|
988
|
|
|
|
|
|
|
* |
|
989
|
|
|
|
|
|
|
* Since the parent is checked for a match as well, we maintain a 'serial' counter. |
|
990
|
|
|
|
|
|
|
* Whenever we traverse an element, we expect the serial to be the same as a global |
|
991
|
|
|
|
|
|
|
* integer. If they do not match, we re-initialize the context, and set the serial. |
|
992
|
|
|
|
|
|
|
* |
|
993
|
|
|
|
|
|
|
* This ensures a type of consistency without having a proactive reset by the |
|
994
|
|
|
|
|
|
|
* main lexer itself. |
|
995
|
|
|
|
|
|
|
* |
|
996
|
|
|
|
|
|
|
*/ |
|
997
|
|
|
|
|
|
|
JSONSL_API |
|
998
|
72
|
|
|
|
|
|
jsonsl_jpr_t jsonsl_jpr_match_state(jsonsl_t jsn, |
|
999
|
|
|
|
|
|
|
struct jsonsl_state_st *state, |
|
1000
|
|
|
|
|
|
|
const char *key, |
|
1001
|
|
|
|
|
|
|
size_t nkey, |
|
1002
|
|
|
|
|
|
|
jsonsl_jpr_match_t *out) |
|
1003
|
|
|
|
|
|
|
{ |
|
1004
|
|
|
|
|
|
|
struct jsonsl_state_st *parent_state; |
|
1005
|
72
|
|
|
|
|
|
jsonsl_jpr_t ret = NULL; |
|
1006
|
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
/* Jump and JPR tables for our own state and the parent state */ |
|
1008
|
|
|
|
|
|
|
size_t *jmptable, *pjmptable; |
|
1009
|
|
|
|
|
|
|
size_t jmp_cur, ii, ourjmpidx; |
|
1010
|
|
|
|
|
|
|
|
|
1011
|
72
|
100
|
|
|
|
|
if (!jsn->jpr_root) { |
|
1012
|
54
|
|
|
|
|
|
*out = JSONSL_MATCH_NOMATCH; |
|
1013
|
54
|
|
|
|
|
|
return NULL; |
|
1014
|
|
|
|
|
|
|
} |
|
1015
|
|
|
|
|
|
|
|
|
1016
|
18
|
|
|
|
|
|
pjmptable = jsn->jpr_root + (jsn->jpr_count * (state->level-1)); |
|
1017
|
18
|
|
|
|
|
|
jmptable = pjmptable + jsn->jpr_count; |
|
1018
|
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
/* If the parent cannot match, then invalidate it */ |
|
1020
|
18
|
50
|
|
|
|
|
if (*pjmptable == 0) { |
|
1021
|
0
|
|
|
|
|
|
*jmptable = 0; |
|
1022
|
0
|
|
|
|
|
|
*out = JSONSL_MATCH_NOMATCH; |
|
1023
|
0
|
|
|
|
|
|
return NULL; |
|
1024
|
|
|
|
|
|
|
} |
|
1025
|
|
|
|
|
|
|
|
|
1026
|
18
|
|
|
|
|
|
parent_state = jsn->stack + state->level - 1; |
|
1027
|
|
|
|
|
|
|
|
|
1028
|
18
|
100
|
|
|
|
|
if (parent_state->type == JSONSL_T_LIST) { |
|
1029
|
5
|
|
|
|
|
|
nkey = (size_t) parent_state->nelem; |
|
1030
|
|
|
|
|
|
|
} |
|
1031
|
|
|
|
|
|
|
|
|
1032
|
18
|
|
|
|
|
|
*jmptable = 0; |
|
1033
|
18
|
|
|
|
|
|
ourjmpidx = 0; |
|
1034
|
18
|
|
|
|
|
|
memset(jmptable, 0, sizeof(int) * jsn->jpr_count); |
|
1035
|
|
|
|
|
|
|
|
|
1036
|
28
|
100
|
|
|
|
|
for (ii = 0; ii < jsn->jpr_count; ii++) { |
|
1037
|
18
|
|
|
|
|
|
jmp_cur = pjmptable[ii]; |
|
1038
|
18
|
50
|
|
|
|
|
if (jmp_cur) { |
|
1039
|
18
|
|
|
|
|
|
jsonsl_jpr_t jpr = jsn->jprs[jmp_cur-1]; |
|
1040
|
18
|
|
|
|
|
|
*out = jsonsl_jpr_match(jpr, |
|
1041
|
|
|
|
|
|
|
parent_state->type, |
|
1042
|
|
|
|
|
|
|
parent_state->level, |
|
1043
|
|
|
|
|
|
|
key, nkey); |
|
1044
|
18
|
100
|
|
|
|
|
if (*out == JSONSL_MATCH_COMPLETE) { |
|
1045
|
8
|
|
|
|
|
|
ret = jpr; |
|
1046
|
8
|
|
|
|
|
|
*jmptable = 0; |
|
1047
|
8
|
|
|
|
|
|
return ret; |
|
1048
|
10
|
100
|
|
|
|
|
} else if (*out == JSONSL_MATCH_POSSIBLE) { |
|
1049
|
9
|
|
|
|
|
|
jmptable[ourjmpidx] = ii+1; |
|
1050
|
10
|
|
|
|
|
|
ourjmpidx++; |
|
1051
|
|
|
|
|
|
|
} |
|
1052
|
|
|
|
|
|
|
} else { |
|
1053
|
0
|
|
|
|
|
|
break; |
|
1054
|
|
|
|
|
|
|
} |
|
1055
|
|
|
|
|
|
|
} |
|
1056
|
10
|
100
|
|
|
|
|
if (!*jmptable) { |
|
1057
|
1
|
|
|
|
|
|
*out = JSONSL_MATCH_NOMATCH; |
|
1058
|
|
|
|
|
|
|
} |
|
1059
|
10
|
|
|
|
|
|
return NULL; |
|
1060
|
|
|
|
|
|
|
} |
|
1061
|
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
JSONSL_API |
|
1063
|
0
|
|
|
|
|
|
const char *jsonsl_strmatchtype(jsonsl_jpr_match_t match) |
|
1064
|
|
|
|
|
|
|
{ |
|
1065
|
|
|
|
|
|
|
#define X(T,v) \ |
|
1066
|
|
|
|
|
|
|
if ( match == JSONSL_MATCH_##T ) \ |
|
1067
|
|
|
|
|
|
|
return #T; |
|
1068
|
0
|
0
|
|
|
|
|
JSONSL_XMATCH |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1069
|
|
|
|
|
|
|
#undef X |
|
1070
|
0
|
|
|
|
|
|
return ""; |
|
1071
|
|
|
|
|
|
|
} |
|
1072
|
|
|
|
|
|
|
|
|
1073
|
|
|
|
|
|
|
#endif /* JSONSL_WITH_JPR */ |
|
1074
|
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
/** |
|
1076
|
|
|
|
|
|
|
* Utility function to convert escape sequences |
|
1077
|
|
|
|
|
|
|
*/ |
|
1078
|
|
|
|
|
|
|
JSONSL_API |
|
1079
|
14
|
|
|
|
|
|
size_t jsonsl_util_unescape_ex(const char *in, |
|
1080
|
|
|
|
|
|
|
char *out, |
|
1081
|
|
|
|
|
|
|
size_t len, |
|
1082
|
|
|
|
|
|
|
const int toEscape[128], |
|
1083
|
|
|
|
|
|
|
unsigned *oflags, |
|
1084
|
|
|
|
|
|
|
jsonsl_error_t *err, |
|
1085
|
|
|
|
|
|
|
const char **errat) |
|
1086
|
|
|
|
|
|
|
{ |
|
1087
|
14
|
|
|
|
|
|
const unsigned char *c = (const unsigned char*)in; |
|
1088
|
14
|
|
|
|
|
|
int in_escape = 0; |
|
1089
|
14
|
|
|
|
|
|
size_t origlen = len; |
|
1090
|
|
|
|
|
|
|
/* difference between the length of the input buffer and the output buffer */ |
|
1091
|
14
|
|
|
|
|
|
size_t ndiff = 0; |
|
1092
|
14
|
50
|
|
|
|
|
if (oflags) { |
|
1093
|
14
|
|
|
|
|
|
*oflags = 0; |
|
1094
|
|
|
|
|
|
|
} |
|
1095
|
|
|
|
|
|
|
#define UNESCAPE_BAIL(e,offset) \ |
|
1096
|
|
|
|
|
|
|
*err = JSONSL_ERROR_##e; \ |
|
1097
|
|
|
|
|
|
|
if (errat) { \ |
|
1098
|
|
|
|
|
|
|
*errat = (const char*)(c+ (ptrdiff_t)(offset)); \ |
|
1099
|
|
|
|
|
|
|
} \ |
|
1100
|
|
|
|
|
|
|
return 0; |
|
1101
|
|
|
|
|
|
|
|
|
1102
|
106
|
100
|
|
|
|
|
for (; len; len--, c++, out++) { |
|
1103
|
|
|
|
|
|
|
unsigned int uesc_val[2]; |
|
1104
|
93
|
100
|
|
|
|
|
if (in_escape) { |
|
1105
|
|
|
|
|
|
|
/* inside a previously ignored escape. Ignore */ |
|
1106
|
2
|
|
|
|
|
|
in_escape = 0; |
|
1107
|
2
|
|
|
|
|
|
goto GT_ASSIGN; |
|
1108
|
|
|
|
|
|
|
} |
|
1109
|
|
|
|
|
|
|
|
|
1110
|
91
|
100
|
|
|
|
|
if (*c != '\\') { |
|
1111
|
|
|
|
|
|
|
/* Not an escape, so we don't care about this */ |
|
1112
|
75
|
|
|
|
|
|
goto GT_ASSIGN; |
|
1113
|
|
|
|
|
|
|
} |
|
1114
|
|
|
|
|
|
|
|
|
1115
|
16
|
50
|
|
|
|
|
if (len < 2) { |
|
1116
|
1
|
0
|
|
|
|
|
UNESCAPE_BAIL(ESCAPE_INVALID, 0); |
|
1117
|
|
|
|
|
|
|
} |
|
1118
|
16
|
100
|
|
|
|
|
if (!is_allowed_escape(c[1])) { |
|
1119
|
1
|
50
|
|
|
|
|
UNESCAPE_BAIL(ESCAPE_INVALID, 1) |
|
1120
|
|
|
|
|
|
|
} |
|
1121
|
15
|
100
|
|
|
|
|
if ((toEscape[(unsigned char)c[1] & 0x7f] == 0 && |
|
|
|
50
|
|
|
|
|
|
|
1122
|
2
|
50
|
|
|
|
|
c[1] != '\\' && c[1] != '"')) { |
|
1123
|
|
|
|
|
|
|
/* if we don't want to unescape this string, just continue with |
|
1124
|
|
|
|
|
|
|
* the escape flag set |
|
1125
|
|
|
|
|
|
|
*/ |
|
1126
|
2
|
|
|
|
|
|
in_escape = 1; |
|
1127
|
2
|
|
|
|
|
|
goto GT_ASSIGN; |
|
1128
|
|
|
|
|
|
|
} |
|
1129
|
|
|
|
|
|
|
|
|
1130
|
13
|
100
|
|
|
|
|
if (c[1] != 'u') { |
|
1131
|
|
|
|
|
|
|
/* simple skip-and-replace using pre-defined maps. |
|
1132
|
|
|
|
|
|
|
* TODO: should the maps actually reflect the desired |
|
1133
|
|
|
|
|
|
|
* replacement character in toEscape? |
|
1134
|
|
|
|
|
|
|
*/ |
|
1135
|
7
|
|
|
|
|
|
char esctmp = get_escape_equiv(c[1]); |
|
1136
|
7
|
100
|
|
|
|
|
if (esctmp) { |
|
1137
|
|
|
|
|
|
|
/* Check if there is a corresponding replacement */ |
|
1138
|
5
|
|
|
|
|
|
*out = esctmp; |
|
1139
|
|
|
|
|
|
|
} else { |
|
1140
|
|
|
|
|
|
|
/* Just gobble up the 'reverse-solidus' */ |
|
1141
|
2
|
|
|
|
|
|
*out = c[1]; |
|
1142
|
|
|
|
|
|
|
} |
|
1143
|
7
|
|
|
|
|
|
len--; |
|
1144
|
7
|
|
|
|
|
|
ndiff++; |
|
1145
|
7
|
|
|
|
|
|
c++; |
|
1146
|
|
|
|
|
|
|
/* do not assign, just continue */ |
|
1147
|
13
|
|
|
|
|
|
continue; |
|
1148
|
|
|
|
|
|
|
} |
|
1149
|
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
/* next == 'u' */ |
|
1151
|
6
|
50
|
|
|
|
|
if (len < 6) { |
|
1152
|
|
|
|
|
|
|
/* Need at least six characters: |
|
1153
|
|
|
|
|
|
|
* { [0] = '\\', [1] = 'u', [2] = 'f', [3] = 'f', [4] = 'f', [5] = 'f' } |
|
1154
|
|
|
|
|
|
|
*/ |
|
1155
|
0
|
0
|
|
|
|
|
UNESCAPE_BAIL(UESCAPE_TOOSHORT, -1); |
|
1156
|
|
|
|
|
|
|
} |
|
1157
|
|
|
|
|
|
|
|
|
1158
|
6
|
50
|
|
|
|
|
if (sscanf((const char*)(c+2), "%02x%02x", uesc_val, uesc_val+1) != 2) { |
|
1159
|
|
|
|
|
|
|
/* We treat the sequence as two octets */ |
|
1160
|
0
|
0
|
|
|
|
|
UNESCAPE_BAIL(UESCAPE_TOOSHORT, -1); |
|
1161
|
|
|
|
|
|
|
} |
|
1162
|
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
/* By now, we gobble up all the six bytes (current implied + 5 next |
|
1164
|
|
|
|
|
|
|
* characters), and have at least four missing bytes from the output |
|
1165
|
|
|
|
|
|
|
* buffer. |
|
1166
|
|
|
|
|
|
|
*/ |
|
1167
|
6
|
|
|
|
|
|
len -= 5; |
|
1168
|
6
|
|
|
|
|
|
c += 5; |
|
1169
|
|
|
|
|
|
|
|
|
1170
|
6
|
|
|
|
|
|
ndiff += 4; |
|
1171
|
6
|
100
|
|
|
|
|
if (uesc_val[0] == 0) { |
|
1172
|
|
|
|
|
|
|
/* only one byte is extracted from the two |
|
1173
|
|
|
|
|
|
|
* possible octets. Increment the diff counter by one. |
|
1174
|
|
|
|
|
|
|
*/ |
|
1175
|
5
|
|
|
|
|
|
*out = uesc_val[1]; |
|
1176
|
5
|
50
|
|
|
|
|
if (oflags && *(unsigned char*)out > 0x7f) { |
|
|
|
50
|
|
|
|
|
|
|
1177
|
0
|
|
|
|
|
|
*oflags |= JSONSL_SPECIALf_NONASCII; |
|
1178
|
|
|
|
|
|
|
} |
|
1179
|
5
|
|
|
|
|
|
ndiff++; |
|
1180
|
|
|
|
|
|
|
} else { |
|
1181
|
1
|
|
|
|
|
|
*(out++) = uesc_val[0]; |
|
1182
|
1
|
|
|
|
|
|
*out = uesc_val[1]; |
|
1183
|
1
|
50
|
|
|
|
|
if (oflags && (uesc_val[0] > 0x7f || uesc_val[1] > 0x7f)) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1184
|
1
|
|
|
|
|
|
*oflags |= JSONSL_SPECIALf_NONASCII; |
|
1185
|
|
|
|
|
|
|
} |
|
1186
|
|
|
|
|
|
|
} |
|
1187
|
6
|
|
|
|
|
|
continue; |
|
1188
|
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
/* Only reached by previous branches */ |
|
1190
|
|
|
|
|
|
|
GT_ASSIGN: |
|
1191
|
79
|
|
|
|
|
|
*out = *c; |
|
1192
|
|
|
|
|
|
|
} |
|
1193
|
13
|
|
|
|
|
|
*err = JSONSL_ERROR_SUCCESS; |
|
1194
|
13
|
|
|
|
|
|
return origlen - ndiff; |
|
1195
|
|
|
|
|
|
|
} |
|
1196
|
|
|
|
|
|
|
|
|
1197
|
|
|
|
|
|
|
/** |
|
1198
|
|
|
|
|
|
|
* Character Table definitions. |
|
1199
|
|
|
|
|
|
|
* These were all generated via srcutil/genchartables.pl |
|
1200
|
|
|
|
|
|
|
*/ |
|
1201
|
|
|
|
|
|
|
|
|
1202
|
|
|
|
|
|
|
/** |
|
1203
|
|
|
|
|
|
|
* This table contains the beginnings of non-string |
|
1204
|
|
|
|
|
|
|
* allowable (bareword) values. |
|
1205
|
|
|
|
|
|
|
*/ |
|
1206
|
|
|
|
|
|
|
static unsigned short Special_Table[0x100] = { |
|
1207
|
|
|
|
|
|
|
/* 0x00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x1f */ |
|
1208
|
|
|
|
|
|
|
/* 0x20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x2c */ |
|
1209
|
|
|
|
|
|
|
/* 0x2d */ JSONSL_SPECIALf_DASH /* <-> */, /* 0x2d */ |
|
1210
|
|
|
|
|
|
|
/* 0x2e */ 0,0, /* 0x2f */ |
|
1211
|
|
|
|
|
|
|
/* 0x30 */ JSONSL_SPECIALf_ZERO /* <0> */, /* 0x30 */ |
|
1212
|
|
|
|
|
|
|
/* 0x31 */ JSONSL_SPECIALf_UNSIGNED /* <1> */, /* 0x31 */ |
|
1213
|
|
|
|
|
|
|
/* 0x32 */ JSONSL_SPECIALf_UNSIGNED /* <2> */, /* 0x32 */ |
|
1214
|
|
|
|
|
|
|
/* 0x33 */ JSONSL_SPECIALf_UNSIGNED /* <3> */, /* 0x33 */ |
|
1215
|
|
|
|
|
|
|
/* 0x34 */ JSONSL_SPECIALf_UNSIGNED /* <4> */, /* 0x34 */ |
|
1216
|
|
|
|
|
|
|
/* 0x35 */ JSONSL_SPECIALf_UNSIGNED /* <5> */, /* 0x35 */ |
|
1217
|
|
|
|
|
|
|
/* 0x36 */ JSONSL_SPECIALf_UNSIGNED /* <6> */, /* 0x36 */ |
|
1218
|
|
|
|
|
|
|
/* 0x37 */ JSONSL_SPECIALf_UNSIGNED /* <7> */, /* 0x37 */ |
|
1219
|
|
|
|
|
|
|
/* 0x38 */ JSONSL_SPECIALf_UNSIGNED /* <8> */, /* 0x38 */ |
|
1220
|
|
|
|
|
|
|
/* 0x39 */ JSONSL_SPECIALf_UNSIGNED /* <9> */, /* 0x39 */ |
|
1221
|
|
|
|
|
|
|
/* 0x3a */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x59 */ |
|
1222
|
|
|
|
|
|
|
/* 0x5a */ 0,0,0,0,0,0,0,0,0,0,0,0, /* 0x65 */ |
|
1223
|
|
|
|
|
|
|
/* 0x66 */ JSONSL_SPECIALf_FALSE /* */, /* 0x66 */ |
|
1224
|
|
|
|
|
|
|
/* 0x67 */ 0,0,0,0,0,0,0, /* 0x6d */ |
|
1225
|
|
|
|
|
|
|
/* 0x6e */ JSONSL_SPECIALf_NULL /* */, /* 0x6e */ |
|
1226
|
|
|
|
|
|
|
/* 0x6f */ 0,0,0,0,0, /* 0x73 */ |
|
1227
|
|
|
|
|
|
|
/* 0x74 */ JSONSL_SPECIALf_TRUE /* */, /* 0x74 */ |
|
1228
|
|
|
|
|
|
|
/* 0x75 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x94 */ |
|
1229
|
|
|
|
|
|
|
/* 0x95 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb4 */ |
|
1230
|
|
|
|
|
|
|
/* 0xb5 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xd4 */ |
|
1231
|
|
|
|
|
|
|
/* 0xd5 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xf4 */ |
|
1232
|
|
|
|
|
|
|
/* 0xf5 */ 0,0,0,0,0,0,0,0,0,0, /* 0xfe */ |
|
1233
|
|
|
|
|
|
|
}; |
|
1234
|
|
|
|
|
|
|
|
|
1235
|
|
|
|
|
|
|
/** |
|
1236
|
|
|
|
|
|
|
* Contains characters which signal the termination of any of the 'special' bareword |
|
1237
|
|
|
|
|
|
|
* values. |
|
1238
|
|
|
|
|
|
|
*/ |
|
1239
|
|
|
|
|
|
|
static int Special_Endings[0x100] = { |
|
1240
|
|
|
|
|
|
|
/* 0x00 */ 0,0,0,0,0,0,0,0,0, /* 0x08 */ |
|
1241
|
|
|
|
|
|
|
/* 0x09 */ 1 /* */, /* 0x09 */ |
|
1242
|
|
|
|
|
|
|
/* 0x0a */ 1 /* */, /* 0x0a */ |
|
1243
|
|
|
|
|
|
|
/* 0x0b */ 0,0, /* 0x0c */ |
|
1244
|
|
|
|
|
|
|
/* 0x0d */ 1 /* */, /* 0x0d */ |
|
1245
|
|
|
|
|
|
|
/* 0x0e */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x1f */ |
|
1246
|
|
|
|
|
|
|
/* 0x20 */ 1 /* */, /* 0x20 */ |
|
1247
|
|
|
|
|
|
|
/* 0x21 */ 0, /* 0x21 */ |
|
1248
|
|
|
|
|
|
|
/* 0x22 */ 1 /* " */, /* 0x22 */ |
|
1249
|
|
|
|
|
|
|
/* 0x23 */ 0,0,0,0,0,0,0,0,0, /* 0x2b */ |
|
1250
|
|
|
|
|
|
|
/* 0x2c */ 1 /* , */, /* 0x2c */ |
|
1251
|
|
|
|
|
|
|
/* 0x2d */ 0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x39 */ |
|
1252
|
|
|
|
|
|
|
/* 0x3a */ 1 /* : */, /* 0x3a */ |
|
1253
|
|
|
|
|
|
|
/* 0x3b */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x5a */ |
|
1254
|
|
|
|
|
|
|
/* 0x5b */ 1 /* [ */, /* 0x5b */ |
|
1255
|
|
|
|
|
|
|
/* 0x5c */ 1 /* \ */, /* 0x5c */ |
|
1256
|
|
|
|
|
|
|
/* 0x5d */ 1 /* ] */, /* 0x5d */ |
|
1257
|
|
|
|
|
|
|
/* 0x5e */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x7a */ |
|
1258
|
|
|
|
|
|
|
/* 0x7b */ 1 /* { */, /* 0x7b */ |
|
1259
|
|
|
|
|
|
|
/* 0x7c */ 0, /* 0x7c */ |
|
1260
|
|
|
|
|
|
|
/* 0x7d */ 1 /* } */, /* 0x7d */ |
|
1261
|
|
|
|
|
|
|
/* 0x7e */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x9d */ |
|
1262
|
|
|
|
|
|
|
/* 0x9e */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xbd */ |
|
1263
|
|
|
|
|
|
|
/* 0xbe */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xdd */ |
|
1264
|
|
|
|
|
|
|
/* 0xde */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xfd */ |
|
1265
|
|
|
|
|
|
|
/* 0xfe */ 0 /* 0xfe */ |
|
1266
|
|
|
|
|
|
|
}; |
|
1267
|
|
|
|
|
|
|
|
|
1268
|
|
|
|
|
|
|
/** |
|
1269
|
|
|
|
|
|
|
* This table contains entries for the allowed whitespace as per RFC 4627 |
|
1270
|
|
|
|
|
|
|
*/ |
|
1271
|
|
|
|
|
|
|
static int Allowed_Whitespace[0x100] = { |
|
1272
|
|
|
|
|
|
|
/* 0x00 */ 0,0,0,0,0,0,0,0,0, /* 0x08 */ |
|
1273
|
|
|
|
|
|
|
/* 0x09 */ 1 /* */, /* 0x09 */ |
|
1274
|
|
|
|
|
|
|
/* 0x0a */ 1 /* */, /* 0x0a */ |
|
1275
|
|
|
|
|
|
|
/* 0x0b */ 0,0, /* 0x0c */ |
|
1276
|
|
|
|
|
|
|
/* 0x0d */ 1 /* */, /* 0x0d */ |
|
1277
|
|
|
|
|
|
|
/* 0x0e */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x1f */ |
|
1278
|
|
|
|
|
|
|
/* 0x20 */ 1 /* */, /* 0x20 */ |
|
1279
|
|
|
|
|
|
|
/* 0x21 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x40 */ |
|
1280
|
|
|
|
|
|
|
/* 0x41 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x60 */ |
|
1281
|
|
|
|
|
|
|
/* 0x61 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80 */ |
|
1282
|
|
|
|
|
|
|
/* 0x81 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0 */ |
|
1283
|
|
|
|
|
|
|
/* 0xa1 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xc0 */ |
|
1284
|
|
|
|
|
|
|
/* 0xc1 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xe0 */ |
|
1285
|
|
|
|
|
|
|
/* 0xe1 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0xfe */ |
|
1286
|
|
|
|
|
|
|
}; |
|
1287
|
|
|
|
|
|
|
|
|
1288
|
|
|
|
|
|
|
/** |
|
1289
|
|
|
|
|
|
|
* Allowable two-character 'common' escapes: |
|
1290
|
|
|
|
|
|
|
*/ |
|
1291
|
|
|
|
|
|
|
static int Allowed_Escapes[0x100] = { |
|
1292
|
|
|
|
|
|
|
/* 0x00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x1f */ |
|
1293
|
|
|
|
|
|
|
/* 0x20 */ 0,0, /* 0x21 */ |
|
1294
|
|
|
|
|
|
|
/* 0x22 */ 1 /* <"> */, /* 0x22 */ |
|
1295
|
|
|
|
|
|
|
/* 0x23 */ 0,0,0,0,0,0,0,0,0,0,0,0, /* 0x2e */ |
|
1296
|
|
|
|
|
|
|
/* 0x2f */ 1 /* > */, /* 0x2f */ |
|
1297
|
|
|
|
|
|
|
/* 0x30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x4f */ |
|
1298
|
|
|
|
|
|
|
/* 0x50 */ 0,0,0,0,0,0,0,0,0,0,0,0, /* 0x5b */ |
|
1299
|
|
|
|
|
|
|
/* 0x5c */ 1 /* <\> */, /* 0x5c */ |
|
1300
|
|
|
|
|
|
|
/* 0x5d */ 0,0,0,0,0, /* 0x61 */ |
|
1301
|
|
|
|
|
|
|
/* 0x62 */ 1 /* */, /* 0x62 */ |
|
1302
|
|
|
|
|
|
|
/* 0x63 */ 0,0,0, /* 0x65 */ |
|
1303
|
|
|
|
|
|
|
/* 0x66 */ 1 /* */, /* 0x66 */ |
|
1304
|
|
|
|
|
|
|
/* 0x67 */ 0,0,0,0,0,0,0, /* 0x6d */ |
|
1305
|
|
|
|
|
|
|
/* 0x6e */ 1 /* */, /* 0x6e */ |
|
1306
|
|
|
|
|
|
|
/* 0x6f */ 0,0,0, /* 0x71 */ |
|
1307
|
|
|
|
|
|
|
/* 0x72 */ 1 /* */, /* 0x72 */ |
|
1308
|
|
|
|
|
|
|
/* 0x73 */ 0, /* 0x73 */ |
|
1309
|
|
|
|
|
|
|
/* 0x74 */ 1 /* */, /* 0x74 */ |
|
1310
|
|
|
|
|
|
|
/* 0x75 */ 1 /* */, /* 0x75 */ |
|
1311
|
|
|
|
|
|
|
/* 0x76 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x95 */ |
|
1312
|
|
|
|
|
|
|
/* 0x96 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb5 */ |
|
1313
|
|
|
|
|
|
|
/* 0xb6 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xd5 */ |
|
1314
|
|
|
|
|
|
|
/* 0xd6 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xf5 */ |
|
1315
|
|
|
|
|
|
|
/* 0xf6 */ 0,0,0,0,0,0,0,0,0, /* 0xfe */ |
|
1316
|
|
|
|
|
|
|
}; |
|
1317
|
|
|
|
|
|
|
|
|
1318
|
|
|
|
|
|
|
/** |
|
1319
|
|
|
|
|
|
|
* This table contains the _values_ for a given (single) escaped character. |
|
1320
|
|
|
|
|
|
|
*/ |
|
1321
|
|
|
|
|
|
|
static unsigned char Escape_Equivs[0x100] = { |
|
1322
|
|
|
|
|
|
|
/* 0x00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x1f */ |
|
1323
|
|
|
|
|
|
|
/* 0x20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x3f */ |
|
1324
|
|
|
|
|
|
|
/* 0x40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x5f */ |
|
1325
|
|
|
|
|
|
|
/* 0x60 */ 0,0, /* 0x61 */ |
|
1326
|
|
|
|
|
|
|
/* 0x62 */ 8 /* */, /* 0x62 */ |
|
1327
|
|
|
|
|
|
|
/* 0x63 */ 0,0,0, /* 0x65 */ |
|
1328
|
|
|
|
|
|
|
/* 0x66 */ 12 /* */, /* 0x66 */ |
|
1329
|
|
|
|
|
|
|
/* 0x67 */ 0,0,0,0,0,0,0, /* 0x6d */ |
|
1330
|
|
|
|
|
|
|
/* 0x6e */ 10 /* */, /* 0x6e */ |
|
1331
|
|
|
|
|
|
|
/* 0x6f */ 0,0,0, /* 0x71 */ |
|
1332
|
|
|
|
|
|
|
/* 0x72 */ 13 /* */, /* 0x72 */ |
|
1333
|
|
|
|
|
|
|
/* 0x73 */ 0, /* 0x73 */ |
|
1334
|
|
|
|
|
|
|
/* 0x74 */ 9 /* */, /* 0x74 */ |
|
1335
|
|
|
|
|
|
|
/* 0x75 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x94 */ |
|
1336
|
|
|
|
|
|
|
/* 0x95 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb4 */ |
|
1337
|
|
|
|
|
|
|
/* 0xb5 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xd4 */ |
|
1338
|
|
|
|
|
|
|
/* 0xd5 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xf4 */ |
|
1339
|
|
|
|
|
|
|
/* 0xf5 */ 0,0,0,0,0,0,0,0,0,0 /* 0xfe */ |
|
1340
|
|
|
|
|
|
|
}; |
|
1341
|
|
|
|
|
|
|
|
|
1342
|
|
|
|
|
|
|
/* Definitions of above-declared static functions */ |
|
1343
|
7
|
|
|
|
|
|
static char get_escape_equiv(unsigned c) { |
|
1344
|
7
|
|
|
|
|
|
return Escape_Equivs[c & 0xff]; |
|
1345
|
|
|
|
|
|
|
} |
|
1346
|
5550
|
|
|
|
|
|
static unsigned extract_special(unsigned c) { |
|
1347
|
5550
|
|
|
|
|
|
return Special_Table[c & 0xff]; |
|
1348
|
|
|
|
|
|
|
} |
|
1349
|
62
|
|
|
|
|
|
static int is_special_end(unsigned c) { |
|
1350
|
62
|
|
|
|
|
|
return Special_Endings[c & 0xff]; |
|
1351
|
|
|
|
|
|
|
} |
|
1352
|
5786
|
|
|
|
|
|
static int is_allowed_whitespace(unsigned c) { |
|
1353
|
5786
|
100
|
|
|
|
|
return c == ' ' || Allowed_Whitespace[c & 0xff]; |
|
|
|
100
|
|
|
|
|
|
|
1354
|
|
|
|
|
|
|
} |
|
1355
|
29
|
|
|
|
|
|
static int is_allowed_escape(unsigned c) { |
|
1356
|
29
|
|
|
|
|
|
return Allowed_Escapes[c & 0xff]; |
|
1357
|
|
|
|
|
|
|
} |
|
1358
|
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
/* Clean up all our macros! */ |
|
1360
|
|
|
|
|
|
|
#undef INCR_METRIC |
|
1361
|
|
|
|
|
|
|
#undef INCR_GENERIC |
|
1362
|
|
|
|
|
|
|
#undef INCR_STRINGY_CATCH |
|
1363
|
|
|
|
|
|
|
#undef CASE_DIGITS |
|
1364
|
|
|
|
|
|
|
#undef INVOKE_ERROR |
|
1365
|
|
|
|
|
|
|
#undef STACK_PUSH |
|
1366
|
|
|
|
|
|
|
#undef STACK_POP_NOPOS |
|
1367
|
|
|
|
|
|
|
#undef STACK_POP |
|
1368
|
|
|
|
|
|
|
#undef CALLBACK_AND_POP_NOPOS |
|
1369
|
|
|
|
|
|
|
#undef CALLBACK_AND_POP |
|
1370
|
|
|
|
|
|
|
#undef SPECIAL_POP |
|
1371
|
|
|
|
|
|
|
#undef CUR_CHAR |
|
1372
|
|
|
|
|
|
|
#undef DO_CALLBACK |
|
1373
|
|
|
|
|
|
|
#undef ENSURE_HVAL |
|
1374
|
|
|
|
|
|
|
#undef VERIFY_SPECIAL |
|
1375
|
|
|
|
|
|
|
#undef STATE_SPECIAL_LENGTH |
|
1376
|
|
|
|
|
|
|
#undef IS_NORMAL_NUMBER |
|
1377
|
|
|
|
|
|
|
#undef STATE_NUM_LAST |