3 STRING_ITERATOR(_json, string_null, 0);
5 /** parse a json object */
6 bool _json_parse_object();
7 bool _json_parse_members();
8 bool _json_parse_pair();
9 bool _json_parse_array();
10 bool _json_parse_elements();
11 bool _json_parse_value();
12 bool _json_parse_true();
13 bool _json_parse_false();
14 bool _json_parse_null();
15 bool _json_parse_string();
16 bool _json_parse_number();
17 bool _json_parse_int();
19 #define JSON_BEGIN() int __i = STRING_ITERATOR_SAVE(_json)
20 #define JSON_FAIL(reason) goto fail
24 STRING_ITERATOR_LOAD(_json, __i); \
27 bool _json_parse_object() {
29 if (STRING_ITERATOR_GET(_json) != '{') JSON_FAIL("expected '{'");
30 LOG_INFO(">> object\n");
31 _json_parse_members();
32 if (STRING_ITERATOR_GET(_json) != '}') JSON_FAIL("expected '}'");
33 LOG_INFO("<< object\n");
37 bool _json_parse_members() {
39 if (!_json_parse_pair()) JSON_FAIL("expected pair");
40 if (STRING_ITERATOR_PEEK(_json) == ',') {
41 STRING_ITERATOR_NEXT(_json);
42 if (!_json_parse_members()) JSON_FAIL("expected pair");
47 bool _json_parse_pair() {
49 if (!_json_parse_string()) JSON_FAIL("expected string");
50 if (STRING_ITERATOR_GET(_json) != ':') JSON_FAIL("expected ':'");
51 if (!_json_parse_value()) JSON_FAIL("expected value");
55 bool _json_parse_array() {
57 if (STRING_ITERATOR_GET(_json) != '[') JSON_FAIL("expected '['");
58 LOG_INFO(">> array\n");
59 _json_parse_elements();
60 if (STRING_ITERATOR_GET(_json) != ']') JSON_FAIL("expected ']'");
61 LOG_INFO("<< array\n");
65 bool _json_parse_elements() {
67 if (!_json_parse_value()) JSON_FAIL("expected value");
68 if (STRING_ITERATOR_PEEK(_json) == ',') {
69 STRING_ITERATOR_NEXT(_json);
70 if (!_json_parse_elements()) JSON_FAIL("expected value");
75 bool _json_parse_value() {
77 if (!(_json_parse_string()
78 || _json_parse_number()
79 || _json_parse_object()
80 || _json_parse_array()
82 || _json_parse_false()
83 || _json_parse_null())) JSON_FAIL("expected value");
87 bool _json_parse_true() {
89 if (!(STRING_ITERATOR_GET(_json) == 't'
90 && STRING_ITERATOR_GET(_json) == 'r'
91 && STRING_ITERATOR_GET(_json) == 'u'
92 && STRING_ITERATOR_GET(_json) == 'e'))
93 JSON_FAIL("expected 'true'");
94 LOG_INFO(">> bool (true)\n");
98 bool _json_parse_false() {
100 if (!(STRING_ITERATOR_GET(_json) == 'f'
101 && STRING_ITERATOR_GET(_json) == 'a'
102 && STRING_ITERATOR_GET(_json) == 'l'
103 && STRING_ITERATOR_GET(_json) == 's'
104 && STRING_ITERATOR_GET(_json) == 'e'))
105 JSON_FAIL("expected 'false'");
106 LOG_INFO(">> bool (false)\n");
110 bool _json_parse_null() {
112 if (!(STRING_ITERATOR_GET(_json) == 'n'
113 && STRING_ITERATOR_GET(_json) == 'u'
114 && STRING_ITERATOR_GET(_json) == 'l'
115 && STRING_ITERATOR_GET(_json) == 'l'))
116 JSON_FAIL("expected 'null'");
117 LOG_INFO(">> null\n");
121 bool _json_parse_string() {
123 if (STRING_ITERATOR_GET(_json) != '"') JSON_FAIL("expected opening '\"'");
125 for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
127 STRING_ITERATOR_UNGET(_json);
129 } else if (c == '\\') {
131 switch (STRING_ITERATOR_GET(_json)) {
133 JSON_FAIL("expected ( '\"' | '\\' | 'n' | 't' )");
134 case '"': esc = "\""; break;
135 case '\\': esc = "\\"; break;
136 case 'n': esc = "\n"; break;
137 case 't': esc = "\t"; break;
141 s = strcat(s, chr2str(c));
144 if (STRING_ITERATOR_GET(_json) != '"') JSON_FAIL("expected closing '\"'");
145 LOG_INFOF(">> string ('%s')\n", s);
149 bool _json_parse_number() {
151 if (!_json_parse_int()) JSON_FAIL("expected int");
155 bool _json_parse_int() {
158 for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
159 if (!(c >= '0' && c <= '9')) {
160 STRING_ITERATOR_UNGET(_json);
163 if (s == "" && c == '0') JSON_FAIL("expected [1-9]");
164 s = strcat(s, chr2str(c));
166 if (s == "") JSON_FAIL("expected int");
168 LOG_INFOF(">> int (%d)\n", i);
172 bool json_parse(string in) {
173 // TODO: remove insignificant whitespace
174 STRING_ITERATOR_SET(_json, in, 0);
175 return _json_parse_object();
184 EXPECT_EQ(true, json_parse("{\"string\":\"string\",\"int\":123,\"bool\":true,\"null\":null,\"obj\":{\"arr\":[1,2,3]}}"));