3 STRING_ITERATOR(_json, string_null, 0);
4 // Store interleaved keys/values in a string buffer
9 /** parse a json object */
10 bool _json_parse_object();
11 bool _json_parse_members();
12 bool _json_parse_pair();
13 bool _json_parse_array();
14 bool _json_parse_value();
15 bool _json_parse_true();
16 bool _json_parse_false();
17 bool _json_parse_null();
18 bool _json_parse_string(bool add);
19 bool _json_parse_number();
20 bool _json_parse_int();
22 #define JSON_BEGIN() int __i = STRING_ITERATOR_SAVE(_json)
23 #define JSON_FAIL(reason) goto fail
27 STRING_ITERATOR_LOAD(_json, __i); \
34 bool _json_parse_object() {
36 if (STRING_ITERATOR_GET(_json) != '{') JSON_FAIL("expected '{'");
37 WITH(int, _json_keys, bufstr_add(_json_buffer, "", 0), _json_parse_members());
38 if (STRING_ITERATOR_GET(_json) != '}') JSON_FAIL("expected '}'");
42 bool _json_parse_members() {
45 if (!_json_parse_pair()) JSON_FAIL("expected pair");
46 if (STRING_ITERATOR_PEEK(_json) == ',') {
47 STRING_ITERATOR_NEXT(_json);
55 bool _json_parse_pair() {
57 if (!_json_parse_string(false)) JSON_FAIL("expected string");
58 string key = _json_temp;
59 bufstr_set(_json_buffer, _json_keys, cons(bufstr_get(_json_buffer, _json_keys), key));
60 key = _json_ns ? strcat(_json_ns, ".", key) : key;
61 bufstr_add(_json_buffer, key, 0);
62 if (STRING_ITERATOR_GET(_json) != ':') JSON_FAIL("expected ':'");
63 bool ret = false; WITH(string, _json_ns, key, ret = _json_parse_value());
64 if (!ret) JSON_FAIL("expected value");
68 bool _json_parse_array() {
70 if (STRING_ITERATOR_GET(_json) != '[') JSON_FAIL("expected '['");
71 int len = bufstr_add(_json_buffer, "0", 0);
72 bufstr_set(_json_buffer, len - 1, strcat(bufstr_get(_json_buffer, len - 1), ".length"));
74 bool required = false;
76 bufstr_set(_json_buffer, len, ftos(++n));
77 if (!_json_parse_value()) if (required) JSON_FAIL("expected value"); else break;
78 bufstr_add(_json_buffer, strcat(_json_ns, ".", ftos(n)), 0);
79 if (STRING_ITERATOR_PEEK(_json) == ',') {
80 STRING_ITERATOR_NEXT(_json);
86 if (STRING_ITERATOR_GET(_json) != ']') JSON_FAIL("expected ']'");
90 bool _json_parse_value() {
92 if (!(_json_parse_string(true)
93 || _json_parse_number()
94 || _json_parse_object()
95 || _json_parse_array()
97 || _json_parse_false()
98 || _json_parse_null())) JSON_FAIL("expected value");
102 bool _json_parse_true() {
104 if (!(STRING_ITERATOR_GET(_json) == 't'
105 && STRING_ITERATOR_GET(_json) == 'r'
106 && STRING_ITERATOR_GET(_json) == 'u'
107 && STRING_ITERATOR_GET(_json) == 'e'))
108 JSON_FAIL("expected 'true'");
109 bufstr_add(_json_buffer, "1", 0);
113 bool _json_parse_false() {
115 if (!(STRING_ITERATOR_GET(_json) == 'f'
116 && STRING_ITERATOR_GET(_json) == 'a'
117 && STRING_ITERATOR_GET(_json) == 'l'
118 && STRING_ITERATOR_GET(_json) == 's'
119 && STRING_ITERATOR_GET(_json) == 'e'))
120 JSON_FAIL("expected 'false'");
121 bufstr_add(_json_buffer, "0", 0);
125 bool _json_parse_null() {
127 if (!(STRING_ITERATOR_GET(_json) == 'n'
128 && STRING_ITERATOR_GET(_json) == 'u'
129 && STRING_ITERATOR_GET(_json) == 'l'
130 && STRING_ITERATOR_GET(_json) == 'l'))
131 JSON_FAIL("expected 'null'");
132 bufstr_add(_json_buffer, "", 0);
136 bool _json_parse_string(bool add) {
138 if (STRING_ITERATOR_GET(_json) != '"') JSON_FAIL("expected opening '\"'");
140 for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
142 STRING_ITERATOR_UNGET(_json);
144 } else if (c == '\\') {
146 switch (STRING_ITERATOR_GET(_json)) {
148 JSON_FAIL("expected ( '\"' | '\\' | 'n' | 't' )");
149 case '"': esc = "\""; break;
150 case '\\': esc = "\\"; break;
151 case 'n': esc = "\n"; break;
152 case 't': esc = "\t"; break;
156 s = strcat(s, chr2str(c));
159 if (STRING_ITERATOR_GET(_json) != '"') JSON_FAIL("expected closing '\"'");
160 if (add) bufstr_add(_json_buffer, s, 0);
165 bool _json_parse_number() {
167 if (!_json_parse_int()) JSON_FAIL("expected number");
171 bool _json_parse_int() {
174 for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
175 if (!(c >= '0' && c <= '9')) {
176 STRING_ITERATOR_UNGET(_json);
179 if (s == "" && c == '0') JSON_FAIL("expected [1-9]");
180 s = strcat(s, chr2str(c));
182 if (s == "") JSON_FAIL("expected int");
183 if (ftos(stof(s)) != s) JSON_FAIL("expected int");
184 bufstr_add(_json_buffer, s, 0);
188 int json_parse(string in) {
189 // TODO: remove insignificant whitespace
190 STRING_ITERATOR_SET(_json, in, 0);
191 _json_buffer = buf_create();
192 bool ret = _json_parse_object();
194 buf_del(_json_buffer);
206 string s = "{\"m_string\":\"string\",\"m_int\":123,\"m_bool\":true,\"m_null\":null,\"m_obj\":{},\"m_arr\":[]}";
208 int buf = json_parse(s);
210 for (int i = 0, n = buf_getsize(buf); i < n; ++i) {
211 print(bufstr_get(buf, i), "\n");