agoo 2.5.7 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of agoo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +38 -0
- data/ext/agoo/agoo.c +11 -2
- data/ext/agoo/bind.c +15 -20
- data/ext/agoo/con.c +32 -25
- data/ext/agoo/debug.c +225 -162
- data/ext/agoo/debug.h +31 -51
- data/ext/agoo/doc.c +278 -5
- data/ext/agoo/doc.h +6 -1
- data/ext/agoo/err.c +1 -0
- data/ext/agoo/err.h +1 -0
- data/ext/agoo/error_stream.c +3 -6
- data/ext/agoo/gqlcobj.c +12 -0
- data/ext/agoo/gqlcobj.h +25 -0
- data/ext/agoo/gqleval.c +520 -0
- data/ext/agoo/gqleval.h +49 -0
- data/ext/agoo/gqlintro.c +1237 -97
- data/ext/agoo/gqlintro.h +8 -0
- data/ext/agoo/gqljson.c +460 -0
- data/ext/agoo/gqljson.h +15 -0
- data/ext/agoo/gqlvalue.c +679 -136
- data/ext/agoo/gqlvalue.h +29 -7
- data/ext/agoo/graphql.c +841 -362
- data/ext/agoo/graphql.h +180 -90
- data/ext/agoo/hook.c +8 -16
- data/ext/agoo/http.c +3 -4
- data/ext/agoo/log.c +22 -25
- data/ext/agoo/log.h +1 -0
- data/ext/agoo/page.c +24 -40
- data/ext/agoo/pub.c +23 -21
- data/ext/agoo/queue.c +2 -4
- data/ext/agoo/ready.c +9 -9
- data/ext/agoo/req.c +80 -5
- data/ext/agoo/req.h +2 -0
- data/ext/agoo/res.c +1 -3
- data/ext/agoo/rgraphql.c +753 -0
- data/ext/agoo/rresponse.c +9 -15
- data/ext/agoo/rserver.c +18 -17
- data/ext/agoo/sdl.c +1264 -120
- data/ext/agoo/sdl.h +8 -1
- data/ext/agoo/sectime.c +136 -0
- data/ext/agoo/sectime.h +19 -0
- data/ext/agoo/server.c +1 -3
- data/ext/agoo/subject.c +2 -4
- data/ext/agoo/text.c +124 -18
- data/ext/agoo/text.h +5 -1
- data/ext/agoo/upgraded.c +2 -4
- data/lib/agoo/version.rb +1 -1
- data/test/base_handler_test.rb +43 -40
- data/test/bind_test.rb +49 -48
- data/test/graphql_test.rb +1019 -0
- data/test/hijack_test.rb +1 -1
- data/test/rack_handler_test.rb +40 -34
- data/test/static_test.rb +33 -32
- metadata +17 -6
data/ext/agoo/gqlintro.h
CHANGED
@@ -4,7 +4,15 @@
|
|
4
4
|
#define AGOO_GQLINTRO_H
|
5
5
|
|
6
6
|
#include "err.h"
|
7
|
+
#include "gqlcobj.h"
|
8
|
+
|
9
|
+
struct _gqlField;
|
10
|
+
struct _gqlSel;
|
11
|
+
struct _gqlType;
|
12
|
+
struct _gqlValue;
|
7
13
|
|
8
14
|
extern int gql_intro_init(agooErr err);
|
9
15
|
|
16
|
+
extern int gql_intro_eval(agooErr err, struct _gqlDoc *doc, struct _gqlSel *sel, struct _gqlValue *result, int depth);
|
17
|
+
|
10
18
|
#endif // AGOO_GQLINTRO_H
|
data/ext/agoo/gqljson.c
ADDED
@@ -0,0 +1,460 @@
|
|
1
|
+
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include <math.h>
|
4
|
+
#include <stdint.h>
|
5
|
+
#include <stdio.h>
|
6
|
+
#include <stdlib.h>
|
7
|
+
#include <string.h>
|
8
|
+
|
9
|
+
#include "doc.h"
|
10
|
+
#include "err.h"
|
11
|
+
#include "gqljson.h"
|
12
|
+
#include "gqlvalue.h"
|
13
|
+
#include "graphql.h"
|
14
|
+
|
15
|
+
#define EXP_MAX 1023
|
16
|
+
#define DEC_MAX 14
|
17
|
+
#define DIV_MAX 100000000000000000LL
|
18
|
+
#define BIGGISH 922337203685477580LL
|
19
|
+
#ifndef INT32_MAX
|
20
|
+
#define INT32_MAX 2147483647LL
|
21
|
+
#endif
|
22
|
+
#ifndef INT64_MAX
|
23
|
+
#define INT64_MAX 9223372036854775807LL
|
24
|
+
#endif
|
25
|
+
|
26
|
+
static gqlValue parse_value(agooErr err, agooDoc doc);
|
27
|
+
|
28
|
+
static gqlValue
|
29
|
+
parse_num(agooErr err, agooDoc doc) {
|
30
|
+
gqlValue value = NULL;
|
31
|
+
int zero_cnt = 0;
|
32
|
+
int64_t i = 0;
|
33
|
+
int64_t num = 0;
|
34
|
+
int64_t div = 1;
|
35
|
+
long exp = 0;
|
36
|
+
int dec_cnt = 0;
|
37
|
+
bool big = false;
|
38
|
+
bool neg = false;
|
39
|
+
char c;
|
40
|
+
const char *start = doc->cur;
|
41
|
+
|
42
|
+
c = *doc->cur;
|
43
|
+
if ('-' == c) {
|
44
|
+
doc->cur++;
|
45
|
+
c = *doc->cur;
|
46
|
+
neg = true;
|
47
|
+
} else if ('+' == c) {
|
48
|
+
doc->cur++;
|
49
|
+
c = *doc->cur;
|
50
|
+
}
|
51
|
+
for (; doc->cur < doc->end && '0' <= c && c <= '9'; c = *++doc->cur) {
|
52
|
+
dec_cnt++;
|
53
|
+
if (!big) {
|
54
|
+
int d = (c - '0');
|
55
|
+
|
56
|
+
if (0 == d) {
|
57
|
+
zero_cnt++;
|
58
|
+
} else {
|
59
|
+
zero_cnt = 0;
|
60
|
+
}
|
61
|
+
if (BIGGISH <= i && (INT64_MAX - i * 10LL) < (int64_t)d) {
|
62
|
+
big = true;
|
63
|
+
} else {
|
64
|
+
i = i * 10 + d;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
if ('.' == c) {
|
69
|
+
c = *++doc->cur;
|
70
|
+
for (; doc->cur < doc->end && '0' <= c && c <= '9'; c = *++doc->cur) {
|
71
|
+
int d = (c - '0');
|
72
|
+
|
73
|
+
if (0 == d) {
|
74
|
+
zero_cnt++;
|
75
|
+
} else {
|
76
|
+
zero_cnt = 0;
|
77
|
+
}
|
78
|
+
dec_cnt++;
|
79
|
+
if ((BIGGISH < num && (INT64_MAX - (int64_t)d) / 10LL <= num) ||
|
80
|
+
DIV_MAX <= div || DEC_MAX < dec_cnt - zero_cnt) {
|
81
|
+
big = true;
|
82
|
+
} else {
|
83
|
+
num = num * 10 + d;
|
84
|
+
div *= 10;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
if ('e' == c || 'E' == c) {
|
89
|
+
int eneg = 0;
|
90
|
+
|
91
|
+
c = *++doc->cur;
|
92
|
+
if ('-' == c) {
|
93
|
+
c = *++doc->cur;
|
94
|
+
eneg = 1;
|
95
|
+
} else if ('+' == c) {
|
96
|
+
c = *++doc->cur;
|
97
|
+
}
|
98
|
+
for (; doc->cur < doc->end && '0' <= c && c <= '9'; c = *++doc->cur) {
|
99
|
+
exp = exp * 10 + (c - '0');
|
100
|
+
if (EXP_MAX <= exp) {
|
101
|
+
big = true;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
if (eneg) {
|
105
|
+
exp = -exp;
|
106
|
+
}
|
107
|
+
}
|
108
|
+
dec_cnt -= zero_cnt;
|
109
|
+
if (big) {
|
110
|
+
value = gql_string_create(err, start, (int)(doc->cur - start));
|
111
|
+
} else if (1 == div && 0 == exp) {
|
112
|
+
int64_t si = i;
|
113
|
+
if (neg) {
|
114
|
+
si = -si;
|
115
|
+
}
|
116
|
+
if (INT32_MAX < i) {
|
117
|
+
value = gql_i64_create(err, si);
|
118
|
+
} else {
|
119
|
+
value = gql_int_create(err, si);
|
120
|
+
}
|
121
|
+
} else { // decimal
|
122
|
+
double d = (double)i + (double)num / (double)div;
|
123
|
+
|
124
|
+
if (neg) {
|
125
|
+
d = -d;
|
126
|
+
}
|
127
|
+
if (0 != exp) {
|
128
|
+
d *= pow(10.0, exp);
|
129
|
+
}
|
130
|
+
value = gql_float_create(err, d);
|
131
|
+
}
|
132
|
+
return value;
|
133
|
+
}
|
134
|
+
|
135
|
+
static uint32_t
|
136
|
+
read_hex(agooErr err, agooDoc doc) {
|
137
|
+
uint32_t hex = 0;
|
138
|
+
const char *end = doc->cur + 4;
|
139
|
+
char c;
|
140
|
+
|
141
|
+
if (doc->end < end) {
|
142
|
+
agoo_doc_err(doc, err, "invalid escaped character");
|
143
|
+
return 0;
|
144
|
+
}
|
145
|
+
for (; doc->cur < end; doc->cur++) {
|
146
|
+
c = *doc->cur;
|
147
|
+
hex = hex << 4;
|
148
|
+
if ('0' <= c && c <= '9') {
|
149
|
+
hex += c - '0';
|
150
|
+
} else if ('A' <= c && c <= 'F') {
|
151
|
+
hex += c - 'A' + 10;
|
152
|
+
} else if ('a' <= c && c <= 'f') {
|
153
|
+
hex += c - 'a' + 10;
|
154
|
+
} else {
|
155
|
+
agoo_doc_err(doc, err, "invalid unicode character");
|
156
|
+
return 0;
|
157
|
+
}
|
158
|
+
}
|
159
|
+
return hex;
|
160
|
+
}
|
161
|
+
|
162
|
+
static agooText
|
163
|
+
unicode_to_chars(agooErr err, agooText t, uint32_t code, agooDoc doc) {
|
164
|
+
if (0x0000007F >= code) {
|
165
|
+
agoo_text_append_char(t, (char)code);
|
166
|
+
} else if (0x000007FF >= code) {
|
167
|
+
agoo_text_append_char(t, 0xC0 | (code >> 6));
|
168
|
+
agoo_text_append_char(t, 0x80 | (0x3F & code));
|
169
|
+
} else if (0x0000FFFF >= code) {
|
170
|
+
agoo_text_append_char(t, 0xE0 | (code >> 12));
|
171
|
+
agoo_text_append_char(t, 0x80 | ((code >> 6) & 0x3F));
|
172
|
+
agoo_text_append_char(t, 0x80 | (0x3F & code));
|
173
|
+
} else if (0x001FFFFF >= code) {
|
174
|
+
agoo_text_append_char(t, 0xF0 | (code >> 18));
|
175
|
+
agoo_text_append_char(t, 0x80 | ((code >> 12) & 0x3F));
|
176
|
+
agoo_text_append_char(t, 0x80 | ((code >> 6) & 0x3F));
|
177
|
+
agoo_text_append_char(t, 0x80 | (0x3F & code));
|
178
|
+
} else if (0x03FFFFFF >= code) {
|
179
|
+
agoo_text_append_char(t, 0xF8 | (code >> 24));
|
180
|
+
agoo_text_append_char(t, 0x80 | ((code >> 18) & 0x3F));
|
181
|
+
agoo_text_append_char(t, 0x80 | ((code >> 12) & 0x3F));
|
182
|
+
agoo_text_append_char(t, 0x80 | ((code >> 6) & 0x3F));
|
183
|
+
agoo_text_append_char(t, 0x80 | (0x3F & code));
|
184
|
+
} else if (0x7FFFFFFF >= code) {
|
185
|
+
agoo_text_append_char(t, 0xFC | (code >> 30));
|
186
|
+
agoo_text_append_char(t, 0x80 | ((code >> 24) & 0x3F));
|
187
|
+
agoo_text_append_char(t, 0x80 | ((code >> 18) & 0x3F));
|
188
|
+
agoo_text_append_char(t, 0x80 | ((code >> 12) & 0x3F));
|
189
|
+
agoo_text_append_char(t, 0x80 | ((code >> 6) & 0x3F));
|
190
|
+
agoo_text_append_char(t, 0x80 | (0x3F & code));
|
191
|
+
} else {
|
192
|
+
agoo_doc_err(doc, err, "invalid unicode character");
|
193
|
+
}
|
194
|
+
return t;
|
195
|
+
}
|
196
|
+
|
197
|
+
static gqlValue
|
198
|
+
parse_escaped(agooErr err, agooDoc doc) {
|
199
|
+
agooText t = agoo_text_allocate(4096);
|
200
|
+
gqlValue value = NULL;
|
201
|
+
|
202
|
+
if (NULL == t) {
|
203
|
+
return NULL;
|
204
|
+
}
|
205
|
+
for (; doc->cur < doc->end && '"' != *doc->cur; doc->cur++) {
|
206
|
+
if ('\\' == *doc->cur) {
|
207
|
+
doc->cur++;
|
208
|
+
switch (*doc->cur) {
|
209
|
+
case 'n': t = agoo_text_append_char(t, '\n'); break;
|
210
|
+
case 'r': t = agoo_text_append_char(t, '\r'); break;
|
211
|
+
case 't': t = agoo_text_append_char(t, '\t'); break;
|
212
|
+
case 'f': t = agoo_text_append_char(t, '\f'); break;
|
213
|
+
case 'b': t = agoo_text_append_char(t, '\b'); break;
|
214
|
+
case '"': t = agoo_text_append_char(t, '\"'); break;
|
215
|
+
case '/': t = agoo_text_append_char(t, '/'); break;
|
216
|
+
case '\\': t = agoo_text_append_char(t, '\\'); break;
|
217
|
+
case 'u': {
|
218
|
+
uint32_t code;
|
219
|
+
|
220
|
+
doc->cur++;
|
221
|
+
if (0 == (code = read_hex(err, doc)) && AGOO_ERR_OK != err->code) {
|
222
|
+
goto DONE;
|
223
|
+
}
|
224
|
+
if (0x0000D800 <= code && code <= 0x0000DFFF) {
|
225
|
+
uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
|
226
|
+
uint32_t c2;
|
227
|
+
|
228
|
+
if ('\\' != *doc->cur || 'u' != doc->cur[1]) {
|
229
|
+
agoo_doc_err(doc, err, "invalid unicode character");
|
230
|
+
goto DONE;
|
231
|
+
}
|
232
|
+
doc->cur += 2;
|
233
|
+
if (0 == (c2 = read_hex(err, doc)) && AGOO_ERR_OK != err->code) {
|
234
|
+
goto DONE;
|
235
|
+
}
|
236
|
+
c2 = (c2 - 0x0000DC00) & 0x000003FF;
|
237
|
+
code = ((c1 << 10) | c2) + 0x00010000;
|
238
|
+
}
|
239
|
+
unicode_to_chars(err, t, code, doc);
|
240
|
+
if (AGOO_ERR_OK != err->code) {
|
241
|
+
goto DONE;
|
242
|
+
}
|
243
|
+
doc->cur--;
|
244
|
+
break;
|
245
|
+
}
|
246
|
+
default:
|
247
|
+
agoo_doc_err(doc, err, "invalid escaped character");
|
248
|
+
agoo_text_release(t);
|
249
|
+
return NULL;
|
250
|
+
}
|
251
|
+
} else {
|
252
|
+
t = agoo_text_append(t, doc->cur, 1);
|
253
|
+
}
|
254
|
+
}
|
255
|
+
value = gql_string_create(err, t->text, t->len);
|
256
|
+
doc->cur++; // past trailing "
|
257
|
+
DONE:
|
258
|
+
agoo_text_release(t);
|
259
|
+
|
260
|
+
return value;
|
261
|
+
}
|
262
|
+
|
263
|
+
static gqlValue
|
264
|
+
parse_string(agooErr err, agooDoc doc) {
|
265
|
+
const char *start;
|
266
|
+
|
267
|
+
if ('"' != *doc->cur) {
|
268
|
+
agoo_doc_err(doc, err, "invalid string");
|
269
|
+
return NULL;
|
270
|
+
}
|
271
|
+
doc->cur++;
|
272
|
+
start = doc->cur;
|
273
|
+
for (; doc->cur < doc->end && '"' != *doc->cur; doc->cur++) {
|
274
|
+
if ('\\' == *doc->cur) {
|
275
|
+
doc->cur = start;
|
276
|
+
return parse_escaped(err, doc);
|
277
|
+
}
|
278
|
+
}
|
279
|
+
doc->cur++;
|
280
|
+
|
281
|
+
return gql_string_create(err, start, (int)(doc->cur - start - 1));
|
282
|
+
}
|
283
|
+
|
284
|
+
static gqlValue
|
285
|
+
return_parse_err(agooErr err, agooDoc doc, const char *msg, gqlValue value) {
|
286
|
+
agoo_doc_err(doc, err, msg);
|
287
|
+
gql_value_destroy(value);
|
288
|
+
|
289
|
+
return NULL;
|
290
|
+
}
|
291
|
+
|
292
|
+
static gqlValue
|
293
|
+
parse_object(agooErr err, agooDoc doc) {
|
294
|
+
char key[256];
|
295
|
+
gqlValue value = gql_object_create(err);
|
296
|
+
gqlValue member;
|
297
|
+
const char *start;
|
298
|
+
|
299
|
+
if (NULL == value) {
|
300
|
+
return NULL;
|
301
|
+
}
|
302
|
+
doc->cur++; // past the {
|
303
|
+
agoo_doc_skip_jwhite(doc);
|
304
|
+
if ('}' != *doc->cur) {
|
305
|
+
for (; doc->cur < doc->end; doc->cur++) {
|
306
|
+
if ('"' != *doc->cur) {
|
307
|
+
return return_parse_err(err, doc, "expected an object key as a string", value);
|
308
|
+
}
|
309
|
+
doc->cur++; // past "
|
310
|
+
|
311
|
+
// TBD support unicode and escaped characters in key
|
312
|
+
|
313
|
+
start = doc->cur;
|
314
|
+
for (; doc->cur < doc->end && '"' != *doc->cur; doc->cur++) {
|
315
|
+
}
|
316
|
+
if ((int)sizeof(key) <= (int)(doc->cur - start)) {
|
317
|
+
return return_parse_err(err, doc, "object key too long", value);
|
318
|
+
}
|
319
|
+
memcpy(key, start, doc->cur - start);
|
320
|
+
key[doc->cur - start] = '\0';
|
321
|
+
doc->cur++; // past "
|
322
|
+
agoo_doc_skip_jwhite(doc);
|
323
|
+
if (':' != *doc->cur) {
|
324
|
+
return return_parse_err(err, doc, "expected a colon", value);
|
325
|
+
}
|
326
|
+
doc->cur++;
|
327
|
+
agoo_doc_skip_jwhite(doc);
|
328
|
+
if (NULL == (member = parse_value(err, doc)) ||
|
329
|
+
AGOO_ERR_OK != gql_object_set(err, value, key, member)) {
|
330
|
+
gql_value_destroy(value);
|
331
|
+
return NULL;
|
332
|
+
}
|
333
|
+
agoo_doc_skip_jwhite(doc);
|
334
|
+
if ('}' == *doc->cur) {
|
335
|
+
break;
|
336
|
+
}
|
337
|
+
if (',' != *doc->cur) {
|
338
|
+
return return_parse_err(err, doc, "expected a comma", value);
|
339
|
+
}
|
340
|
+
}
|
341
|
+
}
|
342
|
+
if ('}' != *doc->cur) {
|
343
|
+
agoo_doc_err(doc, err, "object not terminated");
|
344
|
+
gql_value_destroy(value);
|
345
|
+
return NULL;
|
346
|
+
}
|
347
|
+
doc->cur++;
|
348
|
+
|
349
|
+
return value;
|
350
|
+
}
|
351
|
+
|
352
|
+
static gqlValue
|
353
|
+
parse_array(agooErr err, agooDoc doc) {
|
354
|
+
gqlValue value = gql_list_create(err, NULL);
|
355
|
+
gqlValue member;
|
356
|
+
|
357
|
+
if (NULL == value) {
|
358
|
+
return NULL;
|
359
|
+
}
|
360
|
+
doc->cur++; // past the [
|
361
|
+
agoo_doc_skip_jwhite(doc);
|
362
|
+
if (']' != *doc->cur) {
|
363
|
+
for (; doc->cur < doc->end; doc->cur++) {
|
364
|
+
if (NULL == (member = parse_value(err, doc)) ||
|
365
|
+
AGOO_ERR_OK != gql_list_append(err, value, member)) {
|
366
|
+
gql_value_destroy(value);
|
367
|
+
return NULL;
|
368
|
+
}
|
369
|
+
agoo_doc_skip_jwhite(doc);
|
370
|
+
if (']' == *doc->cur) {
|
371
|
+
break;
|
372
|
+
}
|
373
|
+
if (',' != *doc->cur) {
|
374
|
+
agoo_doc_err(doc, err, "expected a comma");
|
375
|
+
gql_value_destroy(value);
|
376
|
+
return NULL;
|
377
|
+
}
|
378
|
+
}
|
379
|
+
}
|
380
|
+
if (']' != *doc->cur) {
|
381
|
+
agoo_doc_err(doc, err, "array not terminated");
|
382
|
+
gql_value_destroy(value);
|
383
|
+
return NULL;
|
384
|
+
}
|
385
|
+
doc->cur++;
|
386
|
+
|
387
|
+
return value;
|
388
|
+
}
|
389
|
+
|
390
|
+
static gqlValue
|
391
|
+
parse_value(agooErr err, agooDoc doc) {
|
392
|
+
gqlValue value = NULL;
|
393
|
+
|
394
|
+
agoo_doc_skip_jwhite(doc);
|
395
|
+
switch (*doc->cur) {
|
396
|
+
case '{':
|
397
|
+
value = parse_object(err, doc);
|
398
|
+
break;
|
399
|
+
case '[':
|
400
|
+
value = parse_array(err, doc);
|
401
|
+
break;
|
402
|
+
case '"':
|
403
|
+
value = parse_string(err, doc);
|
404
|
+
break;
|
405
|
+
case '+':
|
406
|
+
case '-':
|
407
|
+
case '0':
|
408
|
+
case '1':
|
409
|
+
case '2':
|
410
|
+
case '3':
|
411
|
+
case '4':
|
412
|
+
case '5':
|
413
|
+
case '6':
|
414
|
+
case '7':
|
415
|
+
case '8':
|
416
|
+
case '9':
|
417
|
+
value = parse_num(err, doc);
|
418
|
+
break;
|
419
|
+
case 't':
|
420
|
+
if (4 <= doc->end - doc->cur &&
|
421
|
+
'r' == doc->cur[1] && 'u' == doc->cur[2] && 'e' == doc->cur[3]) {
|
422
|
+
value = gql_bool_create(err, true);
|
423
|
+
} else {
|
424
|
+
agoo_doc_err(doc, err, "invalid token");
|
425
|
+
}
|
426
|
+
break;
|
427
|
+
case 'f':
|
428
|
+
if (5 <= doc->end - doc->cur &&
|
429
|
+
'a' == doc->cur[1] && 'l' == doc->cur[2] && 's' == doc->cur[3] && 'e' == doc->cur[4]) {
|
430
|
+
value = gql_bool_create(err, false);
|
431
|
+
} else {
|
432
|
+
agoo_doc_err(doc, err, "invalid token");
|
433
|
+
}
|
434
|
+
break;
|
435
|
+
case 'n':
|
436
|
+
if (4 <= doc->end - doc->cur &&
|
437
|
+
'u' == doc->cur[1] && 'l' == doc->cur[2] && 'l' == doc->cur[3]) {
|
438
|
+
value = gql_null_create(err);
|
439
|
+
} else {
|
440
|
+
agoo_doc_err(doc, err, "invalid token");
|
441
|
+
}
|
442
|
+
break;
|
443
|
+
case '\0':
|
444
|
+
agoo_doc_err(doc, err, "embedded null character");
|
445
|
+
break;
|
446
|
+
default:
|
447
|
+
agoo_doc_err(doc, err, "invalid token character");
|
448
|
+
break;
|
449
|
+
}
|
450
|
+
return value;
|
451
|
+
}
|
452
|
+
|
453
|
+
gqlValue
|
454
|
+
gql_json_parse(agooErr err, const char *json, size_t len) {
|
455
|
+
struct _agooDoc doc;
|
456
|
+
|
457
|
+
agoo_doc_init(&doc, json, len);
|
458
|
+
|
459
|
+
return parse_value(err, &doc);
|
460
|
+
}
|