Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
json.qc File Reference
#include "json.qh"
#include "test.qh"
Include dependency graph for json.qc:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define JSON_BEGIN()
#define JSON_END()
#define JSON_FAIL(reason)

Functions

ERASEABLE bool _json_parse_array ()
ERASEABLE bool _json_parse_false ()
ERASEABLE bool _json_parse_float ()
ERASEABLE bool _json_parse_int ()
ERASEABLE bool _json_parse_members ()
ERASEABLE bool _json_parse_null ()
ERASEABLE bool _json_parse_number ()
ERASEABLE bool _json_parse_object ()
 Parse a json object.
ERASEABLE bool _json_parse_pair ()
ERASEABLE bool _json_parse_string (bool add)
ERASEABLE bool _json_parse_true ()
ERASEABLE bool _json_parse_value ()
ERASEABLE void json_del (int buf)
ERASEABLE void json_dump (int buf)
ERASEABLE string json_get (int buf, string key)
ERASEABLE int json_parse (string in, bool() func)
 STRING_ITERATOR (_json, string_null, 0)
 TEST (json, Parse)

Variables

int _json_buffer
 Store interleaved keys/values in a string buffer.
int _json_keys
 Current keys.
string _json_ns
 Current namespace.
string _json_temp
 Last read string.

Macro Definition Documentation

◆ JSON_BEGIN

◆ JSON_END

#define JSON_END ( )
Value:
return true; \
LABEL(fail) \
STRING_ITERATOR_LOAD(_json, __i); \
return false;

Definition at line 14 of file json.qc.

14#define JSON_END() \
15 return true; \
16LABEL(fail) \
17 STRING_ITERATOR_LOAD(_json, __i); \
18 return false;

Referenced by _json_parse_array(), _json_parse_false(), _json_parse_float(), _json_parse_int(), _json_parse_members(), _json_parse_null(), _json_parse_number(), _json_parse_object(), _json_parse_pair(), _json_parse_string(), _json_parse_true(), and _json_parse_value().

◆ JSON_FAIL

Function Documentation

◆ _json_parse_array()

ERASEABLE bool _json_parse_array ( )

Definition at line 71 of file json.qc.

72{
73 JSON_BEGIN();
74 if (STRING_ITERATOR_GET(_json) != '[')
75 JSON_FAIL("expected '['");
76 int len = bufstr_add(_json_buffer, "0", 0);
77 if (len)
78 bufstr_set(_json_buffer, len - 1, strcat(bufstr_get(_json_buffer, len - 1), ".length"));
79 bool required = false;
80 for (int n = 0; ; ++n)
81 {
82 string key = ftos(n);
83 if (_json_ns)
84 key = strcat(_json_ns, ".", key);
85 int it = bufstr_add(_json_buffer, key, 0);
86 bool ret = false;
87 WITH(string, _json_ns, key, ret = _json_parse_value());
88 if (!ret)
89 {
90 bufstr_free(_json_buffer, it);
91 if (required)
92 JSON_FAIL("expected value");
93 else
94 break;
95 }
96 bufstr_set(_json_buffer, len, ftos(n + 1));
97 if (STRING_ITERATOR_PEEK(_json) == ',')
98 {
100 required = true;
101 continue;
102 }
103 break;
104 }
105 if (STRING_ITERATOR_GET(_json) != ']')
106 JSON_FAIL("expected ']'");
107 JSON_END();
108}
#define STRING_ITERATOR_NEXT(this)
Definition iter.qh:56
#define STRING_ITERATOR_GET(this)
Definition iter.qh:54
#define STRING_ITERATOR_PEEK(this)
Definition iter.qh:55
#define JSON_FAIL(reason)
Definition json.qc:13
#define JSON_BEGIN()
Definition json.qc:12
int _json_buffer
Store interleaved keys/values in a string buffer.
Definition json.qc:7
#define JSON_END()
Definition json.qc:14
string _json_ns
Current namespace.
Definition json.qc:9
ERASEABLE bool _json_parse_value()
Definition json.qc:111
string ftos(float f)
#define WITH(type, name, value, block)
Definition misc.qh:37
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))

References _json_buffer, _json_ns, _json_parse_value(), ftos(), JSON_BEGIN, JSON_END, JSON_FAIL, strcat(), STRING_ITERATOR_GET, STRING_ITERATOR_NEXT, STRING_ITERATOR_PEEK, and WITH.

Referenced by _json_parse_value(), and PlayerStats_PlayerBasic_Handler().

◆ _json_parse_false()

ERASEABLE bool _json_parse_false ( )

Definition at line 139 of file json.qc.

140 {
141 JSON_BEGIN();
142 if (!(STRING_ITERATOR_GET(_json) == 'f'
143 && STRING_ITERATOR_GET(_json) == 'a'
144 && STRING_ITERATOR_GET(_json) == 'l'
145 && STRING_ITERATOR_GET(_json) == 's'
146 && STRING_ITERATOR_GET(_json) == 'e'))
147 JSON_FAIL("expected 'false'");
148 bufstr_add(_json_buffer, "0", 0);
149 JSON_END();
150 }

References _json_buffer, JSON_BEGIN, JSON_END, JSON_FAIL, and STRING_ITERATOR_GET.

Referenced by _json_parse_value().

◆ _json_parse_float()

ERASEABLE bool _json_parse_float ( )

Definition at line 216 of file json.qc.

217 {
218 JSON_BEGIN();
219 string s = "";
220 bool needdot = true;
221 for (int c; (c = STRING_ITERATOR_GET(_json)); )
222 {
223 if (c < '0' || c > '9')
224 {
225 if (c == '.' && needdot) // fine
226 needdot = false;
227 else
228 {
230 break;
231 }
232 }
233 s = strcat(s, chr2str(c));
234 }
235 if (s == "")
236 JSON_FAIL("expected float");
237 bufstr_add(_json_buffer, s, 0);
238 JSON_END();
239 }
#define chr2str
#define STRING_ITERATOR_UNGET(this)
Definition iter.qh:57

References _json_buffer, chr2str, JSON_BEGIN, JSON_END, JSON_FAIL, strcat(), STRING_ITERATOR_GET, and STRING_ITERATOR_UNGET.

Referenced by _json_parse_number().

◆ _json_parse_int()

ERASEABLE bool _json_parse_int ( )

Definition at line 242 of file json.qc.

243 {
244 JSON_BEGIN();
245 string s = "";
246 for (int c; (c = STRING_ITERATOR_GET(_json)); )
247 {
248 if (c < '0' || c > '9')
249 {
251 break;
252 }
253 if (s == "" && c == '0')
254 JSON_FAIL("expected [1-9]");
255 s = strcat(s, chr2str(c));
256 }
257 if (s == "")
258 JSON_FAIL("expected int");
259 if (ftos(stof(s)) != s)
260 JSON_FAIL("expected int");
261 bufstr_add(_json_buffer, s, 0);
262 JSON_END();
263 }
float stof(string val,...)

References _json_buffer, chr2str, ftos(), JSON_BEGIN, JSON_END, JSON_FAIL, stof(), strcat(), STRING_ITERATOR_GET, and STRING_ITERATOR_UNGET.

Referenced by _json_parse_number().

◆ _json_parse_members()

ERASEABLE bool _json_parse_members ( )

Definition at line 33 of file json.qc.

34 {
35 JSON_BEGIN();
36 for (;;)
37 {
38 if (!_json_parse_pair())
39 JSON_FAIL("expected pair");
40 if (STRING_ITERATOR_PEEK(_json) == ',')
41 {
43 continue;
44 }
45 break;
46 }
47 JSON_END();
48 }
ERASEABLE bool _json_parse_pair()
Definition json.qc:51

References _json_parse_pair(), JSON_BEGIN, JSON_END, JSON_FAIL, STRING_ITERATOR_NEXT, and STRING_ITERATOR_PEEK.

Referenced by _json_parse_object().

◆ _json_parse_null()

ERASEABLE bool _json_parse_null ( )

Definition at line 153 of file json.qc.

154 {
155 JSON_BEGIN();
156 if (!(STRING_ITERATOR_GET(_json) == 'n'
157 && STRING_ITERATOR_GET(_json) == 'u'
158 && STRING_ITERATOR_GET(_json) == 'l'
159 && STRING_ITERATOR_GET(_json) == 'l'))
160 JSON_FAIL("expected 'null'");
161 bufstr_add(_json_buffer, "", 0);
162 JSON_END();
163 }

References _json_buffer, JSON_BEGIN, JSON_END, JSON_FAIL, and STRING_ITERATOR_GET.

Referenced by _json_parse_value().

◆ _json_parse_number()

ERASEABLE bool _json_parse_number ( )

Definition at line 207 of file json.qc.

208{
209 JSON_BEGIN();
211 JSON_FAIL("expected number");
212 JSON_END();
213}
ERASEABLE bool _json_parse_float()
Definition json.qc:216
ERASEABLE bool _json_parse_int()
Definition json.qc:242

References _json_parse_float(), _json_parse_int(), JSON_BEGIN, JSON_END, and JSON_FAIL.

Referenced by _json_parse_value().

◆ _json_parse_object()

ERASEABLE bool _json_parse_object ( )

Parse a json object.

Definition at line 21 of file json.qc.

22{
23 JSON_BEGIN();
24 if (STRING_ITERATOR_GET(_json) != '{')
25 JSON_FAIL("expected '{'");
26 WITH(int, _json_keys, bufstr_add(_json_buffer, "", 0), _json_parse_members());
27 if (STRING_ITERATOR_GET(_json) != '}')
28 JSON_FAIL("expected '}'");
29 JSON_END();
30}
int _json_keys
Current keys.
Definition json.qc:10
ERASEABLE bool _json_parse_members()
Definition json.qc:33

References _json_buffer, _json_keys, _json_parse_members(), JSON_BEGIN, JSON_END, JSON_FAIL, STRING_ITERATOR_GET, and WITH.

Referenced by _json_parse_value(), MX_Messages_(), MX_Sync_(), and TEST().

◆ _json_parse_pair()

ERASEABLE bool _json_parse_pair ( )

Definition at line 51 of file json.qc.

52 {
53 JSON_BEGIN();
54 if (!_json_parse_string(false))
55 JSON_FAIL("expected string");
56 string key = _json_temp;
57 bufstr_set(_json_buffer, _json_keys, cons(bufstr_get(_json_buffer, _json_keys), key));
58 if (_json_ns)
59 key = strcat(_json_ns, ".", key);
60 bufstr_add(_json_buffer, key, 0);
61 if (STRING_ITERATOR_GET(_json) != ':')
62 JSON_FAIL("expected ':'");
63 bool ret = false;
64 WITH(string, _json_ns, key, ret = _json_parse_value());
65 if (!ret)
66 JSON_FAIL("expected value");
67 JSON_END();
68 }
string _json_temp
Last read string.
Definition json.qc:8
ERASEABLE bool _json_parse_string(bool add)
Definition json.qc:166
ERASEABLE string cons(string a, string b)
Definition string.qh:277

References _json_buffer, _json_keys, _json_ns, _json_parse_string(), _json_parse_value(), _json_temp, cons(), JSON_BEGIN, JSON_END, JSON_FAIL, strcat(), STRING_ITERATOR_GET, and WITH.

Referenced by _json_parse_members().

◆ _json_parse_string()

ERASEABLE bool _json_parse_string ( bool add)

Definition at line 166 of file json.qc.

167{
168 JSON_BEGIN();
169 if (STRING_ITERATOR_GET(_json) != '"')
170 JSON_FAIL("expected opening '\"'");
171 string s = "";
172 for (int c; (c = STRING_ITERATOR_GET(_json)); )
173 {
174 if (c == '"')
175 {
177 break;
178 }
179 else if (c == '\\')
180 {
181 string esc;
182 switch (STRING_ITERATOR_GET(_json))
183 {
184 default:
185 JSON_FAIL("expected ( '\"' | '\\' | 'n' | 't' )");
186 case '"': esc = "\""; break;
187 case '\\': esc = "\\"; break;
188 case 'n': esc = "\n"; break;
189 case 't': esc = "\t"; break;
190 case 'u': esc = "\\u"; break; // TODO
191 case '/': esc = "/"; break;
192 }
193 s = strcat(s, esc);
194 }
195 else
196 s = strcat(s, chr2str(c));
197 }
198 if (STRING_ITERATOR_GET(_json) != '"')
199 JSON_FAIL("expected closing '\"'");
200 if (add)
201 bufstr_add(_json_buffer, s, 0);
202 _json_temp = s;
203 JSON_END();
204}

References _json_buffer, _json_temp, chr2str, JSON_BEGIN, JSON_END, JSON_FAIL, strcat(), STRING_ITERATOR_GET, and STRING_ITERATOR_UNGET.

Referenced by _json_parse_pair(), and _json_parse_value().

◆ _json_parse_true()

ERASEABLE bool _json_parse_true ( )

Definition at line 126 of file json.qc.

127 {
128 JSON_BEGIN();
129 if (!(STRING_ITERATOR_GET(_json) == 't'
130 && STRING_ITERATOR_GET(_json) == 'r'
131 && STRING_ITERATOR_GET(_json) == 'u'
132 && STRING_ITERATOR_GET(_json) == 'e'))
133 JSON_FAIL("expected 'true'");
134 bufstr_add(_json_buffer, "1", 0);
135 JSON_END();
136 }

References _json_buffer, JSON_BEGIN, JSON_END, JSON_FAIL, and STRING_ITERATOR_GET.

Referenced by _json_parse_value().

◆ _json_parse_value()

ERASEABLE bool _json_parse_value ( )

Definition at line 111 of file json.qc.

112{
113 JSON_BEGIN();
114 if (!(_json_parse_string(true)
120 || _json_parse_null()))
121 JSON_FAIL("expected value");
122 JSON_END();
123}
ERASEABLE bool _json_parse_number()
Definition json.qc:207
ERASEABLE bool _json_parse_true()
Definition json.qc:126
ERASEABLE bool _json_parse_array()
Definition json.qc:71
ERASEABLE bool _json_parse_false()
Definition json.qc:139
ERASEABLE bool _json_parse_null()
Definition json.qc:153
ERASEABLE bool _json_parse_object()
Parse a json object.
Definition json.qc:21

References _json_parse_array(), _json_parse_false(), _json_parse_null(), _json_parse_number(), _json_parse_object(), _json_parse_string(), _json_parse_true(), JSON_BEGIN, JSON_END, and JSON_FAIL.

Referenced by _json_parse_array(), and _json_parse_pair().

◆ json_del()

ERASEABLE void json_del ( int buf)

Definition at line 332 of file json.qc.

333{
334 buf_del(buf);
335}

◆ json_dump()

ERASEABLE void json_dump ( int buf)

Definition at line 338 of file json.qc.

339{
340 for (int i = 0, n = buf_getsize(buf); i < n; ++i)
341 print(bufstr_get(buf, i), "\n");
342}
void print(string text,...)

References print().

Referenced by TEST().

◆ json_get()

ERASEABLE string json_get ( int buf,
string key )

Definition at line 323 of file json.qc.

324{
325 for (int i = 1, n = buf_getsize(buf); i < n; i += 2)
326 if (bufstr_get(buf, i) == key)
327 return bufstr_get(buf, i + 1);
328 return string_null;
329}
string string_null
Definition nil.qh:9

References string_null.

Referenced by MX_Handle(), MX_Messages_(), MX_Sync_(), and PlayerStats_PlayerBasic_Handler().

◆ json_parse()

ERASEABLE int json_parse ( string in,
bool() func )

Definition at line 266 of file json.qc.

267{
268 string trimmed = "";
269 LABEL(trim)
270 {
271 int o = strstrofs(in, "\"", 0);
272 if (o >= 0)
273 {
274 string part = substring(in, 0, o + 1);
275 in = substring(in, o + 1, -1);
276 part = strreplace(" ", "", part);
277 part = strreplace("\n", "", part);
278 trimmed = strcat(trimmed, part);
279 goto trim_str;
280 }
281 else
282 {
283 string part = in;
284 part = strreplace(" ", "", part);
285 part = strreplace("\n", "", part);
286 trimmed = strcat(trimmed, part);
287 goto done;
288 }
289 }
290 LABEL(trim_str)
291 {
292 int o = strstrofs(in, "\"", 0);
293 int esc = strstrofs(in, "\\\"", 0);
294 if (o < esc || esc < 0) // simple string
295 {
296 string part = substring(in, 0, o + 1);
297 in = substring(in, o + 1, -1);
298 trimmed = strcat(trimmed, part);
299 goto trim;
300 }
301 else // has escape
302 {
303 string part = substring(in, 0, esc + 2);
304 in = substring(in, esc + 2, -1);
305 trimmed = strcat(trimmed, part);
306 goto trim_str;
307 }
308 }
309 LABEL(done);
310
311 STRING_ITERATOR_SET(_json, trimmed, 0);
313 bool ret = func();
314 if (!ret)
315 {
316 buf_del(_json_buffer);
317 _json_buffer = -1;
318 }
319 return _json_buffer;
320}
#define LABEL(id)
Definition compiler.qh:34
#define strstrofs
#define buf_create
#define STRING_ITERATOR_SET(this, s, i)
Definition iter.qh:49
string substring(string s, float start, float length)

References _json_buffer, buf_create, LABEL, strcat(), STRING_ITERATOR_SET, strstrofs, and substring().

Referenced by MX_Messages_(), MX_Sync_(), PlayerStats_PlayerBasic_Handler(), and TEST().

◆ STRING_ITERATOR()

STRING_ITERATOR ( _json ,
string_null ,
0  )

References string_null.

◆ TEST()

TEST ( json ,
Parse  )

Definition at line 348 of file json.qc.

349{
350 string s = "{\n"
351 " \"m_string\": \"\\\"string\\\"\",\n"
352 " \"m_int\": 123,\n"
353 " \"m_bool\": true,\n"
354 " \"m_null\": null,\n"
355 " \"m_obj\": { },\n"
356 " \"m_arr\": [ ]\n"
357 "}";
358 print(s, "\n");
359 int buf = json_parse(s, _json_parse_object);
360 EXPECT_NE(-1, buf);
361 json_dump(buf);
362 SUCCEED();
363}
ERASEABLE int json_parse(string in, bool() func)
Definition json.qc:266
ERASEABLE void json_dump(int buf)
Definition json.qc:338
#define EXPECT_NE(val1, val2)
Definition test.qh:53
#define SUCCEED()
Must be present at the end of a test.
Definition test.qh:17

References _json_parse_object(), EXPECT_NE, json_dump(), json_parse(), print(), and SUCCEED.

Variable Documentation

◆ _json_buffer

int _json_buffer

◆ _json_keys

int _json_keys

Current keys.

Definition at line 10 of file json.qc.

Referenced by _json_parse_object(), and _json_parse_pair().

◆ _json_ns

string _json_ns

Current namespace.

Definition at line 9 of file json.qc.

Referenced by _json_parse_array(), and _json_parse_pair().

◆ _json_temp

string _json_temp

Last read string.

Definition at line 8 of file json.qc.

Referenced by _json_parse_pair(), and _json_parse_string().