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 |