CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/ext/gason/gason.cpp
Views: 1401
1
#include "gason.h"
2
#include <stdlib.h>
3
4
#define JSON_ZONE_SIZE 4096
5
#define JSON_STACK_SIZE 32
6
7
const char *jsonStrError(int err) {
8
switch (err) {
9
#define XX(no, str) \
10
case JSON_##no: \
11
return str;
12
JSON_ERRNO_MAP(XX)
13
#undef XX
14
default:
15
return "unknown";
16
}
17
}
18
19
void *JsonAllocator::allocate(size_t size) {
20
size = (size + 7) & ~7;
21
22
if (head && head->used + size <= JSON_ZONE_SIZE) {
23
char *p = (char *)head + head->used;
24
head->used += size;
25
return p;
26
}
27
28
size_t allocSize = sizeof(Zone) + size;
29
Zone *zone = (Zone *)malloc(allocSize <= JSON_ZONE_SIZE ? JSON_ZONE_SIZE : allocSize);
30
if (zone == nullptr)
31
return nullptr;
32
zone->used = allocSize;
33
if (allocSize <= JSON_ZONE_SIZE || head == nullptr) {
34
zone->next = head;
35
head = zone;
36
} else {
37
zone->next = head->next;
38
head->next = zone;
39
}
40
return (char *)zone + sizeof(Zone);
41
}
42
43
void JsonAllocator::deallocate() {
44
while (head) {
45
Zone *next = head->next;
46
free(head);
47
head = next;
48
}
49
}
50
51
static inline bool isspace(char c) {
52
return c == ' ' || (c >= '\t' && c <= '\r');
53
}
54
55
static inline bool isdelim(char c) {
56
return c == ',' || c == ':' || c == ']' || c == '}' || isspace(c) || !c;
57
}
58
59
static inline bool isdigit(char c) {
60
return c >= '0' && c <= '9';
61
}
62
63
static inline bool isxdigit(char c) {
64
return (c >= '0' && c <= '9') || ((c & ~' ') >= 'A' && (c & ~' ') <= 'F');
65
}
66
67
static inline int char2int(char c) {
68
if (c <= '9')
69
return c - '0';
70
return (c & ~' ') - 'A' + 10;
71
}
72
73
static double string2double(char *s, char **endptr) {
74
char ch = *s;
75
if (ch == '-')
76
++s;
77
78
double result = 0;
79
while (isdigit(*s))
80
result = (result * 10) + (*s++ - '0');
81
82
if (*s == '.') {
83
++s;
84
85
double fraction = 1;
86
while (isdigit(*s)) {
87
fraction *= 0.1;
88
result += (*s++ - '0') * fraction;
89
}
90
}
91
92
if (*s == 'e' || *s == 'E') {
93
++s;
94
95
double base = 10;
96
if (*s == '+')
97
++s;
98
else if (*s == '-') {
99
++s;
100
base = 0.1;
101
}
102
103
unsigned int exponent = 0;
104
while (isdigit(*s))
105
exponent = (exponent * 10) + (*s++ - '0');
106
107
double power = 1;
108
for (; exponent; exponent >>= 1, base *= base)
109
if (exponent & 1)
110
power *= base;
111
112
result *= power;
113
}
114
115
*endptr = s;
116
return ch == '-' ? -result : result;
117
}
118
119
static inline JsonNode *insertAfter(JsonNode *tail, JsonNode *node) {
120
if (!tail)
121
return node->next = node;
122
node->next = tail->next;
123
tail->next = node;
124
return node;
125
}
126
127
static inline JsonValue listToValue(JsonTag tag, JsonNode *tail) {
128
if (tail) {
129
auto head = tail->next;
130
tail->next = nullptr;
131
return JsonValue(tag, head);
132
}
133
return JsonValue(tag, nullptr);
134
}
135
136
int jsonParse(char *s, char **endptr, JsonValue *value, JsonAllocator &allocator) {
137
JsonNode *tails[JSON_STACK_SIZE];
138
JsonTag tags[JSON_STACK_SIZE];
139
char *keys[JSON_STACK_SIZE];
140
JsonValue o;
141
int pos = -1;
142
bool separator = true;
143
JsonNode *node;
144
*endptr = s;
145
146
while (*s) {
147
while (isspace(*s)) {
148
++s;
149
if (!*s) break;
150
}
151
*endptr = s++;
152
switch (**endptr) {
153
case '-':
154
if (!isdigit(*s) && *s != '.') {
155
*endptr = s;
156
return JSON_BAD_NUMBER;
157
}
158
case '0':
159
case '1':
160
case '2':
161
case '3':
162
case '4':
163
case '5':
164
case '6':
165
case '7':
166
case '8':
167
case '9':
168
o = JsonValue(string2double(*endptr, &s));
169
if (!isdelim(*s)) {
170
*endptr = s;
171
return JSON_BAD_NUMBER;
172
}
173
break;
174
case '"':
175
o = JsonValue(JSON_STRING, s);
176
for (char *it = s; *s; ++it, ++s) {
177
int c = *it = *s;
178
if (c == '\\') {
179
c = *++s;
180
switch (c) {
181
case '\\':
182
case '"':
183
case '/':
184
*it = c;
185
break;
186
case 'b':
187
*it = '\b';
188
break;
189
case 'f':
190
*it = '\f';
191
break;
192
case 'n':
193
*it = '\n';
194
break;
195
case 'r':
196
*it = '\r';
197
break;
198
case 't':
199
*it = '\t';
200
break;
201
case 'u':
202
c = 0;
203
for (int i = 0; i < 4; ++i) {
204
if (isxdigit(*++s)) {
205
c = c * 16 + char2int(*s);
206
} else {
207
*endptr = s;
208
return JSON_BAD_STRING;
209
}
210
}
211
if (c < 0x80) {
212
*it = c;
213
} else if (c < 0x800) {
214
*it++ = 0xC0 | (c >> 6);
215
*it = 0x80 | (c & 0x3F);
216
} else {
217
*it++ = 0xE0 | (c >> 12);
218
*it++ = 0x80 | ((c >> 6) & 0x3F);
219
*it = 0x80 | (c & 0x3F);
220
}
221
break;
222
default:
223
*endptr = s;
224
return JSON_BAD_STRING;
225
}
226
} else if ((unsigned int)c < ' ' || c == '\x7F') {
227
*endptr = s;
228
return JSON_BAD_STRING;
229
} else if (c == '"') {
230
*it = 0;
231
++s;
232
break;
233
}
234
}
235
if (!isdelim(*s)) {
236
*endptr = s;
237
return JSON_BAD_STRING;
238
}
239
break;
240
case 't':
241
if (!(s[0] == 'r' && s[1] == 'u' && s[2] == 'e' && isdelim(s[3])))
242
return JSON_BAD_IDENTIFIER;
243
o = JsonValue(JSON_TRUE);
244
s += 3;
245
break;
246
case 'f':
247
if (!(s[0] == 'a' && s[1] == 'l' && s[2] == 's' && s[3] == 'e' && isdelim(s[4])))
248
return JSON_BAD_IDENTIFIER;
249
o = JsonValue(JSON_FALSE);
250
s += 4;
251
break;
252
case 'n':
253
if (!(s[0] == 'u' && s[1] == 'l' && s[2] == 'l' && isdelim(s[3])))
254
return JSON_BAD_IDENTIFIER;
255
o = JsonValue(JSON_NULL);
256
s += 3;
257
break;
258
case ']':
259
if (pos == -1)
260
return JSON_STACK_UNDERFLOW;
261
if (tags[pos] != JSON_ARRAY)
262
return JSON_MISMATCH_BRACKET;
263
o = listToValue(JSON_ARRAY, tails[pos--]);
264
break;
265
case '}':
266
if (pos == -1)
267
return JSON_STACK_UNDERFLOW;
268
if (tags[pos] != JSON_OBJECT)
269
return JSON_MISMATCH_BRACKET;
270
if (keys[pos] != nullptr)
271
return JSON_UNEXPECTED_CHARACTER;
272
o = listToValue(JSON_OBJECT, tails[pos--]);
273
break;
274
case '[':
275
if (++pos == JSON_STACK_SIZE)
276
return JSON_STACK_OVERFLOW;
277
tails[pos] = nullptr;
278
tags[pos] = JSON_ARRAY;
279
keys[pos] = nullptr;
280
separator = true;
281
continue;
282
case '{':
283
if (++pos == JSON_STACK_SIZE)
284
return JSON_STACK_OVERFLOW;
285
tails[pos] = nullptr;
286
tags[pos] = JSON_OBJECT;
287
keys[pos] = nullptr;
288
separator = true;
289
continue;
290
case ':':
291
if (separator || keys[pos] == nullptr)
292
return JSON_UNEXPECTED_CHARACTER;
293
separator = true;
294
continue;
295
case ',':
296
if (separator || keys[pos] != nullptr)
297
return JSON_UNEXPECTED_CHARACTER;
298
separator = true;
299
continue;
300
case '\0':
301
continue;
302
default:
303
return JSON_UNEXPECTED_CHARACTER;
304
}
305
306
separator = false;
307
308
if (pos == -1) {
309
*endptr = s;
310
*value = o;
311
return JSON_OK;
312
}
313
314
if (tags[pos] == JSON_OBJECT) {
315
if (!keys[pos]) {
316
if (o.getTag() != JSON_STRING)
317
return JSON_UNQUOTED_KEY;
318
keys[pos] = o.toString();
319
continue;
320
}
321
if ((node = (JsonNode *) allocator.allocate(sizeof(JsonNode))) == nullptr)
322
return JSON_ALLOCATION_FAILURE;
323
tails[pos] = insertAfter(tails[pos], node);
324
tails[pos]->key = keys[pos];
325
keys[pos] = nullptr;
326
} else {
327
if ((node = (JsonNode *) allocator.allocate(sizeof(JsonNode) - sizeof(char *))) == nullptr)
328
return JSON_ALLOCATION_FAILURE;
329
tails[pos] = insertAfter(tails[pos], node);
330
}
331
tails[pos]->value = o;
332
}
333
return JSON_BREAKING_BAD;
334
}
335
336