agoo 2.5.4 → 2.5.5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of agoo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/bin/agoo +3 -1
- data/ext/agoo/base64.h +3 -3
- data/ext/agoo/bind.c +1 -1
- data/ext/agoo/bind.h +3 -3
- data/ext/agoo/con.c +4 -2
- data/ext/agoo/con.h +3 -3
- data/ext/agoo/debug.c +7 -0
- data/ext/agoo/debug.h +13 -6
- data/ext/agoo/doc.c +159 -0
- data/ext/agoo/doc.h +34 -0
- data/ext/agoo/dtime.h +3 -3
- data/ext/agoo/err.h +3 -3
- data/ext/agoo/error_stream.h +3 -3
- data/ext/agoo/extconf.rb +1 -1
- data/ext/agoo/gqlintro.c +333 -0
- data/ext/agoo/gqlintro.h +10 -0
- data/ext/agoo/gqlvalue.c +1035 -0
- data/ext/agoo/gqlvalue.h +88 -0
- data/ext/agoo/graphql.c +1078 -0
- data/ext/agoo/graphql.h +198 -0
- data/ext/agoo/hook.c +2 -0
- data/ext/agoo/hook.h +4 -3
- data/ext/agoo/http.c +2 -1
- data/ext/agoo/http.h +3 -3
- data/ext/agoo/kinds.h +3 -3
- data/ext/agoo/log.h +3 -3
- data/ext/agoo/log_queue.h +3 -3
- data/ext/agoo/method.h +3 -3
- data/ext/agoo/page.h +3 -3
- data/ext/agoo/pub.h +3 -3
- data/ext/agoo/queue.h +3 -3
- data/ext/agoo/rack_logger.h +3 -3
- data/ext/agoo/req.c +2 -2
- data/ext/agoo/req.h +3 -3
- data/ext/agoo/request.h +3 -3
- data/ext/agoo/res.h +3 -3
- data/ext/agoo/response.h +3 -3
- data/ext/agoo/rhook.c +2 -2
- data/ext/agoo/rhook.h +4 -3
- data/ext/agoo/rlog.h +3 -3
- data/ext/agoo/rresponse.h +3 -3
- data/ext/agoo/rserver.c +64 -0
- data/ext/agoo/rserver.h +3 -3
- data/ext/agoo/rupgraded.c +1 -1
- data/ext/agoo/rupgraded.h +3 -3
- data/ext/agoo/sdl.c +334 -0
- data/ext/agoo/sdl.h +10 -0
- data/ext/agoo/seg.h +3 -3
- data/ext/agoo/server.c +3 -1
- data/ext/agoo/server.h +5 -4
- data/ext/agoo/sha1.h +3 -3
- data/ext/agoo/sse.h +3 -3
- data/ext/agoo/sub.h +3 -3
- data/ext/agoo/subject.h +3 -3
- data/ext/agoo/text.h +3 -3
- data/ext/agoo/upgraded.h +3 -3
- data/ext/agoo/websocket.h +3 -3
- data/lib/agoo/version.rb +1 -1
- data/lib/rack/handler/agoo.rb +3 -1
- metadata +12 -12
- data/ext/agoo/foo/agoo.c +0 -109
- data/ext/agoo/foo/con.c +0 -1220
- data/ext/agoo/foo/con.h +0 -65
- data/ext/agoo/foo/page.c +0 -699
- data/ext/agoo/foo/pub.c +0 -131
- data/ext/agoo/foo/pub.h +0 -40
- data/ext/agoo/foo/rserver.c +0 -1016
- data/ext/agoo/foo/server.c +0 -303
- data/ext/agoo/foo/server.h +0 -67
- data/ext/agoo/foo/upgraded.c +0 -182
data/ext/agoo/response.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_RESPONSE_H
|
4
|
+
#define AGOO_RESPONSE_H
|
5
5
|
|
6
6
|
#include <stdatomic.h>
|
7
7
|
#include <stdbool.h>
|
@@ -25,4 +25,4 @@ typedef struct _Response {
|
|
25
25
|
extern int response_len(Response res);
|
26
26
|
extern void response_fill(Response res, char *buf);
|
27
27
|
|
28
|
-
#endif //
|
28
|
+
#endif // AGOO_RESPONSE_H
|
data/ext/agoo/rhook.c
CHANGED
@@ -22,7 +22,7 @@ resolve_classname(VALUE mod, const char *classname) {
|
|
22
22
|
return clas;
|
23
23
|
}
|
24
24
|
|
25
|
-
|
25
|
+
VALUE
|
26
26
|
resolve_classpath(const char *name, size_t len) {
|
27
27
|
char class_name[1024];
|
28
28
|
VALUE clas;
|
@@ -55,7 +55,7 @@ resolve_classpath(const char *name, size_t len) {
|
|
55
55
|
|
56
56
|
Hook
|
57
57
|
rhook_create(Method method, const char *pattern, VALUE handler, Queue q) {
|
58
|
-
Hook hook = hook_create(method,pattern, NULL, RACK_HOOK, q);
|
58
|
+
Hook hook = hook_create(method, pattern, NULL, RACK_HOOK, q);
|
59
59
|
|
60
60
|
if (NULL != hook) {
|
61
61
|
if (T_STRING == rb_type(handler)) {
|
data/ext/agoo/rhook.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_RHOOK_H
|
4
|
+
#define AGOO_RHOOK_H
|
5
5
|
|
6
6
|
#include <ruby.h>
|
7
7
|
|
@@ -9,5 +9,6 @@
|
|
9
9
|
#include "method.h"
|
10
10
|
|
11
11
|
extern Hook rhook_create(Method method, const char *pattern, VALUE handler, Queue q);
|
12
|
+
extern VALUE resolve_classpath(const char *name, size_t len);
|
12
13
|
|
13
|
-
#endif //
|
14
|
+
#endif // AGOO_RHOOK_H
|
data/ext/agoo/rlog.h
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
// Copyright 2018 by Peter Ohler, All Rights Reserved
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_RLOG_H
|
4
|
+
#define AGOO_RLOG_H
|
5
5
|
|
6
6
|
#include <ruby.h>
|
7
7
|
#include "log.h"
|
8
8
|
|
9
9
|
extern void rlog_init(VALUE mod);
|
10
10
|
|
11
|
-
#endif /*
|
11
|
+
#endif /* AGOO_RLOG_H */
|
data/ext/agoo/rresponse.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_RRESPONSE_H
|
4
|
+
#define AGOO_RRESPONSE_H
|
5
5
|
|
6
6
|
#include <ruby.h>
|
7
7
|
|
@@ -11,4 +11,4 @@ extern void response_init(VALUE mod);
|
|
11
11
|
extern VALUE response_new();
|
12
12
|
extern Text response_text(VALUE self);
|
13
13
|
|
14
|
-
#endif //
|
14
|
+
#endif // AGOO_RRESPONSE_H
|
data/ext/agoo/rserver.c
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
#include "debug.h"
|
16
16
|
#include "dtime.h"
|
17
17
|
#include "err.h"
|
18
|
+
#include "graphql.h"
|
18
19
|
#include "http.h"
|
19
20
|
#include "log.h"
|
20
21
|
#include "page.h"
|
@@ -173,6 +174,32 @@ configure(Err err, int port, const char *root, VALUE options) {
|
|
173
174
|
break;
|
174
175
|
}
|
175
176
|
}
|
177
|
+
if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("graphql"))))) {
|
178
|
+
const char *path;
|
179
|
+
Hook hook;
|
180
|
+
char schema_path[256];
|
181
|
+
long plen;
|
182
|
+
|
183
|
+
rb_check_type(v, T_STRING);
|
184
|
+
if (ERR_OK != gql_init(err)) {
|
185
|
+
return err->code;
|
186
|
+
}
|
187
|
+
path = StringValuePtr(v);
|
188
|
+
plen = (long)RSTRING_LEN(v);
|
189
|
+
if ((int)sizeof(schema_path) - 8 < plen) {
|
190
|
+
rb_raise(rb_eArgError, "A graphql schema path is limited to %d characters.", (int)(sizeof(schema_path) - 8));
|
191
|
+
}
|
192
|
+
memcpy(schema_path, path, plen);
|
193
|
+
memcpy(schema_path + plen, "/schema", 8);
|
194
|
+
|
195
|
+
hook = hook_func_create(GET, schema_path, gql_dump_hook, &the_server.eval_queue);
|
196
|
+
hook->next = the_server.hooks;
|
197
|
+
the_server.hooks = hook;
|
198
|
+
|
199
|
+
hook = hook_func_create(GET, path, gql_eval_hook, &the_server.eval_queue);
|
200
|
+
hook->next = the_server.hooks;
|
201
|
+
the_server.hooks = hook;
|
202
|
+
}
|
176
203
|
if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("quiet"))))) {
|
177
204
|
if (Qtrue == v) {
|
178
205
|
info_cat.on = false;
|
@@ -838,6 +865,7 @@ handle(VALUE self, VALUE method, VALUE pattern, VALUE handler) {
|
|
838
865
|
Hook hook;
|
839
866
|
Method meth = ALL;
|
840
867
|
const char *pat;
|
868
|
+
ID static_id = rb_intern("static?");
|
841
869
|
|
842
870
|
rb_check_type(pattern, T_STRING);
|
843
871
|
pat = StringValuePtr(pattern);
|
@@ -861,6 +889,42 @@ handle(VALUE self, VALUE method, VALUE pattern, VALUE handler) {
|
|
861
889
|
} else {
|
862
890
|
rb_raise(rb_eArgError, "invalid method");
|
863
891
|
}
|
892
|
+
if (T_STRING == rb_type(handler)) {
|
893
|
+
handler = resolve_classpath(StringValuePtr(handler), RSTRING_LEN(handler));
|
894
|
+
}
|
895
|
+
if (rb_respond_to(handler, static_id)) {
|
896
|
+
if (Qtrue == rb_funcall(handler, static_id, 0, Qnil)) {
|
897
|
+
VALUE res = rb_funcall(handler, call_id, 1, Qnil);
|
898
|
+
VALUE bv;
|
899
|
+
|
900
|
+
rb_check_type(res, T_ARRAY);
|
901
|
+
if (3 != RARRAY_LEN(res)) {
|
902
|
+
rb_raise(rb_eArgError, "a rack call() response must be an array of 3 members.");
|
903
|
+
}
|
904
|
+
bv = rb_ary_entry(res, 2);
|
905
|
+
if (T_ARRAY == rb_type(bv)) {
|
906
|
+
int i;
|
907
|
+
int bcnt = (int)RARRAY_LEN(bv);
|
908
|
+
Text t = text_allocate(1024);
|
909
|
+
struct _Err err = ERR_INIT;
|
910
|
+
VALUE v;
|
911
|
+
|
912
|
+
if (NULL == t) {
|
913
|
+
rb_raise(rb_eArgError, "failed to allocate response.");
|
914
|
+
}
|
915
|
+
for (i = 0; i < bcnt; i++) {
|
916
|
+
v = rb_ary_entry(bv, i);
|
917
|
+
t = text_append(t, StringValuePtr(v), (int)RSTRING_LEN(v));
|
918
|
+
}
|
919
|
+
if (NULL == page_immutable(&err, pat, t->text, t->len)) {
|
920
|
+
rb_raise(rb_eArgError, "%s", err.msg);
|
921
|
+
}
|
922
|
+
text_release(t);
|
923
|
+
|
924
|
+
return Qnil;
|
925
|
+
}
|
926
|
+
}
|
927
|
+
}
|
864
928
|
if (NULL == (hook = rhook_create(meth, pat, handler, &the_server.eval_queue))) {
|
865
929
|
rb_raise(rb_eStandardError, "out of memory.");
|
866
930
|
} else {
|
data/ext/agoo/rserver.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_RSERVER_H
|
4
|
+
#define AGOO_RSERVER_H
|
5
5
|
|
6
6
|
#include <ruby.h>
|
7
7
|
|
@@ -18,4 +18,4 @@ extern struct _RServer the_rserver;
|
|
18
18
|
extern void server_init(VALUE mod);
|
19
19
|
extern VALUE rserver_shutdown(VALUE self);
|
20
20
|
|
21
|
-
#endif //
|
21
|
+
#endif // AGOO_RSERVER_H
|
data/ext/agoo/rupgraded.c
CHANGED
data/ext/agoo/rupgraded.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
2
|
|
3
|
-
#ifndef
|
4
|
-
#define
|
3
|
+
#ifndef AGOO_RUPGRADED_H
|
4
|
+
#define AGOO_RUPGRADED_H
|
5
5
|
|
6
6
|
#include <ruby.h>
|
7
7
|
|
@@ -14,4 +14,4 @@ extern Upgraded rupgraded_create(struct _Con *c, VALUE obj, VALUE env);
|
|
14
14
|
|
15
15
|
extern const char* extract_subject(VALUE subject, int *slen);
|
16
16
|
|
17
|
-
#endif //
|
17
|
+
#endif // AGOO_RUPGRADED_H
|
data/ext/agoo/sdl.c
ADDED
@@ -0,0 +1,334 @@
|
|
1
|
+
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include <stdio.h>
|
4
|
+
#include <string.h>
|
5
|
+
|
6
|
+
#include "doc.h"
|
7
|
+
#include "gqlvalue.h"
|
8
|
+
#include "graphql.h"
|
9
|
+
#include "sdl.h"
|
10
|
+
|
11
|
+
static int
|
12
|
+
extract_name(Err err, Doc doc, const char *key, int klen, char *name, size_t max) {
|
13
|
+
const char *start;
|
14
|
+
size_t nlen;
|
15
|
+
|
16
|
+
if (0 != strncmp(doc->cur, key, klen)) {
|
17
|
+
return doc_err(doc, err, "Expected %s key word", key);
|
18
|
+
}
|
19
|
+
doc->cur += klen;
|
20
|
+
if (0 == doc_skip_white(doc)) {
|
21
|
+
return doc_err(doc, err, "Expected %s key word", key);
|
22
|
+
}
|
23
|
+
start = doc->cur;
|
24
|
+
doc_read_token(doc);
|
25
|
+
if (doc->cur == start) {
|
26
|
+
return doc_err(doc, err, "Name not provided");
|
27
|
+
}
|
28
|
+
nlen = doc->cur - start;
|
29
|
+
if (max <= nlen) {
|
30
|
+
return doc_err(doc, err, "Name too long");
|
31
|
+
}
|
32
|
+
strncpy(name, start, nlen);
|
33
|
+
name[nlen] = '\0';
|
34
|
+
|
35
|
+
return ERR_OK;
|
36
|
+
}
|
37
|
+
|
38
|
+
static int
|
39
|
+
make_scalar(Err err, Doc doc, const char *desc, int len) {
|
40
|
+
char name[256];
|
41
|
+
|
42
|
+
if (ERR_OK != extract_name(err, doc, "scalar", 6, name, sizeof(name))) {
|
43
|
+
return err->code;
|
44
|
+
}
|
45
|
+
gql_scalar_create(err, name, desc, len, false);
|
46
|
+
|
47
|
+
return ERR_OK;
|
48
|
+
}
|
49
|
+
|
50
|
+
static int
|
51
|
+
make_enum(Err err, Doc doc, const char *desc, int len) {
|
52
|
+
char name[256];
|
53
|
+
const char *start;
|
54
|
+
gqlType type;
|
55
|
+
|
56
|
+
if (ERR_OK != extract_name(err, doc, "enum", 4, name, sizeof(name))) {
|
57
|
+
return err->code;
|
58
|
+
}
|
59
|
+
doc_skip_white(doc);
|
60
|
+
if ('{' != *doc->cur) {
|
61
|
+
return doc_err(doc, err, "Expected '{'");
|
62
|
+
}
|
63
|
+
doc->cur++;
|
64
|
+
|
65
|
+
if (NULL == (type = gql_enum_create(err, name, desc, len, false))) {
|
66
|
+
return err->code;
|
67
|
+
}
|
68
|
+
while (doc->cur < doc->end) {
|
69
|
+
doc_skip_white(doc);
|
70
|
+
start = doc->cur;
|
71
|
+
doc_read_token(doc);
|
72
|
+
if (doc->cur == start) {
|
73
|
+
if ('}' == *doc->cur) {
|
74
|
+
doc->cur++;
|
75
|
+
break;
|
76
|
+
}
|
77
|
+
return doc_err(doc, err, "Invalid Enum value");
|
78
|
+
}
|
79
|
+
if (ERR_OK != gql_enum_add(err, type, start, (int)(doc->cur - start))) {
|
80
|
+
return err->code;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
return ERR_OK;
|
84
|
+
}
|
85
|
+
|
86
|
+
static int
|
87
|
+
make_union(Err err, Doc doc, const char *desc, int len) {
|
88
|
+
char name[256];
|
89
|
+
const char *start;
|
90
|
+
gqlType type;
|
91
|
+
|
92
|
+
if (ERR_OK != extract_name(err, doc, "union", 5, name, sizeof(name))) {
|
93
|
+
return err->code;
|
94
|
+
}
|
95
|
+
doc_skip_white(doc);
|
96
|
+
if ('=' != *doc->cur) {
|
97
|
+
return doc_err(doc, err, "Expected '='");
|
98
|
+
}
|
99
|
+
doc->cur++;
|
100
|
+
doc_skip_white(doc);
|
101
|
+
|
102
|
+
if (NULL == (type = gql_union_create(err, name, desc, len, false))) {
|
103
|
+
return err->code;
|
104
|
+
}
|
105
|
+
while (doc->cur < doc->end) {
|
106
|
+
doc_skip_white(doc);
|
107
|
+
start = doc->cur;
|
108
|
+
doc_read_token(doc);
|
109
|
+
if (ERR_OK != gql_union_add(err, type, start, (int)(doc->cur - start))) {
|
110
|
+
return err->code;
|
111
|
+
}
|
112
|
+
doc_skip_white(doc);
|
113
|
+
if ('|' != *doc->cur) {
|
114
|
+
break;
|
115
|
+
}
|
116
|
+
doc->cur++; // skip |
|
117
|
+
}
|
118
|
+
return ERR_OK;
|
119
|
+
}
|
120
|
+
|
121
|
+
static int
|
122
|
+
make_arg(Err err, Doc doc, gqlDir dir) {
|
123
|
+
char name[256];
|
124
|
+
char type_name[256];
|
125
|
+
const char *start;
|
126
|
+
const char *desc = NULL;
|
127
|
+
const char *desc_end = NULL;
|
128
|
+
size_t nlen;
|
129
|
+
bool required = false;
|
130
|
+
gqlValue dv = NULL;
|
131
|
+
|
132
|
+
doc_skip_white(doc);
|
133
|
+
if ('"' == *doc->cur) {
|
134
|
+
desc = doc->cur + 1;
|
135
|
+
if (ERR_OK != doc_read_string(err, doc)) {
|
136
|
+
return err->code;
|
137
|
+
}
|
138
|
+
if ('"' == *desc) { // must be a """
|
139
|
+
desc += 2;
|
140
|
+
desc_end = doc->cur - 3;
|
141
|
+
} else {
|
142
|
+
desc_end = doc->cur - 1;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
doc_skip_white(doc);
|
146
|
+
start = doc->cur;
|
147
|
+
doc_read_token(doc);
|
148
|
+
if (doc->cur == start) {
|
149
|
+
return doc_err(doc, err, "Argument name not provided");
|
150
|
+
}
|
151
|
+
if (':' != *doc->cur) {
|
152
|
+
return doc_err(doc, err, "Expected ':'");
|
153
|
+
}
|
154
|
+
nlen = doc->cur - start;
|
155
|
+
if (sizeof(name) <= nlen) {
|
156
|
+
return doc_err(doc, err, "Name too long");
|
157
|
+
}
|
158
|
+
strncpy(name, start, nlen);
|
159
|
+
name[nlen] = '\0';
|
160
|
+
doc->cur++;
|
161
|
+
|
162
|
+
// read type
|
163
|
+
doc_skip_white(doc);
|
164
|
+
start = doc->cur;
|
165
|
+
doc_read_token(doc);
|
166
|
+
if (doc->cur == start) {
|
167
|
+
return doc_err(doc, err, "Argument type not provided");
|
168
|
+
}
|
169
|
+
nlen = doc->cur - start;
|
170
|
+
if (sizeof(type_name) <= nlen) {
|
171
|
+
return doc_err(doc, err, "Type name too long");
|
172
|
+
}
|
173
|
+
strncpy(type_name, start, nlen);
|
174
|
+
type_name[nlen] = '\0';
|
175
|
+
|
176
|
+
doc_skip_white(doc);
|
177
|
+
if ('!' == *doc->cur) {
|
178
|
+
required = true;
|
179
|
+
} else if ('=' == *doc->cur) {
|
180
|
+
if (NULL == (dv = doc_read_value(err, doc))) {
|
181
|
+
return err->code;
|
182
|
+
}
|
183
|
+
}
|
184
|
+
doc_skip_white(doc);
|
185
|
+
if ('@' == *doc->cur) {
|
186
|
+
// TBD directive
|
187
|
+
}
|
188
|
+
if (NULL == gql_dir_arg(err, dir, name, type_name, desc, (int)(desc_end - desc), dv, required)) {
|
189
|
+
return err->code;
|
190
|
+
}
|
191
|
+
return ERR_OK;
|
192
|
+
}
|
193
|
+
|
194
|
+
static int
|
195
|
+
make_directive(Err err, Doc doc, const char *desc, int len) {
|
196
|
+
char name[256];
|
197
|
+
const char *start;
|
198
|
+
gqlDir dir;
|
199
|
+
size_t nlen;
|
200
|
+
|
201
|
+
if (0 != strncmp(doc->cur, "directive", 9)) {
|
202
|
+
return doc_err(doc, err, "Expected directive key word");
|
203
|
+
}
|
204
|
+
doc->cur += 9;
|
205
|
+
if (0 == doc_skip_white(doc)) {
|
206
|
+
return doc_err(doc, err, "Expected directive key word");
|
207
|
+
}
|
208
|
+
if ('@' != *doc->cur) {
|
209
|
+
return doc_err(doc, err, "Expected '@'");
|
210
|
+
}
|
211
|
+
doc->cur++;
|
212
|
+
start = doc->cur;
|
213
|
+
doc_read_token(doc);
|
214
|
+
if (doc->cur == start) {
|
215
|
+
return doc_err(doc, err, "Name not provided");
|
216
|
+
}
|
217
|
+
nlen = doc->cur - start;
|
218
|
+
if (sizeof(name) <= nlen) {
|
219
|
+
return doc_err(doc, err, "Name too long");
|
220
|
+
}
|
221
|
+
strncpy(name, start, nlen);
|
222
|
+
name[nlen] = '\0';
|
223
|
+
if (NULL == (dir = gql_directive_create(err, name, desc, len, false))) {
|
224
|
+
return err->code;
|
225
|
+
}
|
226
|
+
if ('(' == *doc->cur) {
|
227
|
+
while (doc->cur < doc->end) {
|
228
|
+
if (ERR_OK != make_arg(err, doc, dir)) {
|
229
|
+
return err->code;
|
230
|
+
}
|
231
|
+
doc_skip_white(doc);
|
232
|
+
if (')' == *doc->cur) {
|
233
|
+
doc->cur++;
|
234
|
+
break;
|
235
|
+
}
|
236
|
+
}
|
237
|
+
}
|
238
|
+
doc_skip_white(doc);
|
239
|
+
start = doc->cur;
|
240
|
+
doc_read_token(doc);
|
241
|
+
|
242
|
+
if (2 != doc->cur - start || 0 != strncmp(start, "on", 2)) {
|
243
|
+
return doc_err(doc, err, "Expected 'on'");
|
244
|
+
}
|
245
|
+
while (doc->cur < doc->end) {
|
246
|
+
doc_skip_white(doc);
|
247
|
+
start = doc->cur;
|
248
|
+
doc_read_token(doc);
|
249
|
+
if (ERR_OK != gql_directive_on(err, dir, start, (int)(doc->cur - start))) {
|
250
|
+
return err->code;
|
251
|
+
}
|
252
|
+
doc_skip_white(doc);
|
253
|
+
if ('|' != *doc->cur) {
|
254
|
+
break;
|
255
|
+
}
|
256
|
+
doc->cur++; // skip |
|
257
|
+
}
|
258
|
+
return ERR_OK;
|
259
|
+
}
|
260
|
+
|
261
|
+
int
|
262
|
+
sdl_parse(Err err, const char *str, int len) {
|
263
|
+
struct _Doc doc;
|
264
|
+
const char *desc = NULL;
|
265
|
+
const char *desc_end = NULL;
|
266
|
+
|
267
|
+
doc_init(&doc, str, len);
|
268
|
+
|
269
|
+
while (doc.cur < doc.end) {
|
270
|
+
doc_next_token(&doc);
|
271
|
+
switch (*doc.cur) {
|
272
|
+
case '"':
|
273
|
+
desc = doc.cur + 1;
|
274
|
+
if (ERR_OK != doc_read_string(err, &doc)) {
|
275
|
+
return err->code;
|
276
|
+
}
|
277
|
+
if ('"' == *desc) { // must be a """
|
278
|
+
desc += 2;
|
279
|
+
desc_end = doc.cur - 3;
|
280
|
+
} else {
|
281
|
+
desc_end = doc.cur - 1;
|
282
|
+
}
|
283
|
+
break;
|
284
|
+
case 's': // scalar
|
285
|
+
if (ERR_OK != make_scalar(err, &doc, desc, (int)(desc_end - desc))) {
|
286
|
+
return err->code;
|
287
|
+
}
|
288
|
+
break;
|
289
|
+
case 'e': // enum, and extend interface or type
|
290
|
+
if (4 < (doc.end - doc.cur)) {
|
291
|
+
if ('n' == doc.cur[1]) {
|
292
|
+
if (ERR_OK != make_enum(err, &doc, desc, (int)(desc_end - desc))) {
|
293
|
+
return err->code;
|
294
|
+
}
|
295
|
+
break;
|
296
|
+
} else {
|
297
|
+
// TBD extend
|
298
|
+
break;
|
299
|
+
}
|
300
|
+
}
|
301
|
+
return doc_err(&doc, err, "Unknown directive");
|
302
|
+
case 'u': // union
|
303
|
+
if (ERR_OK != make_union(err, &doc, desc, (int)(desc_end - desc))) {
|
304
|
+
return err->code;
|
305
|
+
}
|
306
|
+
break;
|
307
|
+
case 'd': // directive
|
308
|
+
if (ERR_OK != make_directive(err, &doc, desc, (int)(desc_end - desc))) {
|
309
|
+
return err->code;
|
310
|
+
}
|
311
|
+
break;
|
312
|
+
case 't': // type
|
313
|
+
break;
|
314
|
+
case 'i': // interface, input
|
315
|
+
if (5 < (doc.end - doc.cur) && 'n' == doc.cur[1]) {
|
316
|
+
if ('p' == doc.cur[2]) {
|
317
|
+
// input
|
318
|
+
break;
|
319
|
+
} else {
|
320
|
+
// TBD interface
|
321
|
+
break;
|
322
|
+
}
|
323
|
+
}
|
324
|
+
return doc_err(&doc, err, "Unknown directive");
|
325
|
+
case 'f': // fragment
|
326
|
+
break;
|
327
|
+
case '\0':
|
328
|
+
return ERR_OK;
|
329
|
+
default:
|
330
|
+
return doc_err(&doc, err, "Unknown directive");
|
331
|
+
}
|
332
|
+
}
|
333
|
+
return ERR_OK;
|
334
|
+
}
|