Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
json.qc File Reference
#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

bool _json_parse_array ()
bool _json_parse_false ()
bool _json_parse_float ()
bool _json_parse_int ()
bool _json_parse_members ()
bool _json_parse_null ()
bool _json_parse_number ()
bool _json_parse_object ()
 parse a json object
bool _json_parse_pair ()
bool _json_parse_string (bool add)
bool _json_parse_true ()
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
int _json_keys
string _json_ns
string _json_temp

Macro Definition Documentation

◆ JSON_BEGIN

◆ JSON_END

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

Definition at line 25 of file json.qc.

25#define JSON_END() \
26 return true; \
27:fail \
28 STRING_ITERATOR_LOAD(_json, __i); \
29 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 73 of file json.qc.

73 {
74 JSON_BEGIN();
75 if (STRING_ITERATOR_GET(_json) != '[') JSON_FAIL("expected '['");
76 int len = bufstr_add(_json_buffer, "0", 0);
77 if (len) bufstr_set(_json_buffer, len - 1, strcat(bufstr_get(_json_buffer, len - 1), ".length"));
78 bool required = false;
79 for (int n = 0; ; ++n) {
80 string key = ftos(n);
81 key = _json_ns ? strcat(_json_ns, ".", key) : key;
82 int it = bufstr_add(_json_buffer, key, 0);
83 bool ret = false; WITH(string, _json_ns, key, ret = _json_parse_value());
84 if (!ret) {
85 bufstr_free(_json_buffer, it);
86 if (required) JSON_FAIL("expected value"); else break;
87 }
88 bufstr_set(_json_buffer, len, ftos(n + 1));
89 if (STRING_ITERATOR_PEEK(_json) == ',') {
91 required = true;
92 continue;
93 }
94 break;
95 }
96 if (STRING_ITERATOR_GET(_json) != ']') JSON_FAIL("expected ']'");
97 JSON_END();
98}
#define STRING_ITERATOR_NEXT(this)
Definition iter.qh:57
#define STRING_ITERATOR_GET(this)
Definition iter.qh:55
#define STRING_ITERATOR_PEEK(this)
Definition iter.qh:56
#define JSON_FAIL(reason)
Definition json.qc:24
#define JSON_BEGIN()
Definition json.qc:23
int _json_buffer
Definition json.qc:5
#define JSON_END()
Definition json.qc:25
string _json_ns
Definition json.qc:31
bool _json_parse_value()
Definition json.qc:101
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 126 of file json.qc.

126 {
127 JSON_BEGIN();
128 if (!(STRING_ITERATOR_GET(_json) == 'f'
129 && STRING_ITERATOR_GET(_json) == 'a'
130 && STRING_ITERATOR_GET(_json) == 'l'
131 && STRING_ITERATOR_GET(_json) == 's'
132 && STRING_ITERATOR_GET(_json) == 'e'))
133 JSON_FAIL("expected 'false'");
134 bufstr_add(_json_buffer, "0", 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_float()

ERASEABLE bool _json_parse_float ( )

Definition at line 190 of file json.qc.

190 {
191 JSON_BEGIN();
192 string s = "";
193 bool needdot = true;
194 for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
195 if (!(c >= '0' && c <= '9')) {
196 if (c == '.' && needdot) {
197 // fine
198 needdot = false;
199 } else {
201 break;
202 }
203 }
204 s = strcat(s, chr2str(c));
205 }
206 if (s == "") JSON_FAIL("expected float");
207 bufstr_add(_json_buffer, s, 0);
208 JSON_END();
209 }
#define chr2str
#define STRING_ITERATOR_UNGET(this)
Definition iter.qh:58

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 212 of file json.qc.

212 {
213 JSON_BEGIN();
214 string s = "";
215 for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
216 if (!(c >= '0' && c <= '9')) {
218 break;
219 }
220 if (s == "" && c == '0') JSON_FAIL("expected [1-9]");
221 s = strcat(s, chr2str(c));
222 }
223 if (s == "") JSON_FAIL("expected int");
224 if (ftos(stof(s)) != s) JSON_FAIL("expected int");
225 bufstr_add(_json_buffer, s, 0);
226 JSON_END();
227 }
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 45 of file json.qc.

45 {
46 JSON_BEGIN();
47 for (;;) {
48 if (!_json_parse_pair()) JSON_FAIL("expected pair");
49 if (STRING_ITERATOR_PEEK(_json) == ',') {
51 continue;
52 }
53 break;
54 }
55 JSON_END();
56 }
bool _json_parse_pair()
Definition json.qc:59

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 139 of file json.qc.

139 {
140 JSON_BEGIN();
141 if (!(STRING_ITERATOR_GET(_json) == 'n'
142 && STRING_ITERATOR_GET(_json) == 'u'
143 && STRING_ITERATOR_GET(_json) == 'l'
144 && STRING_ITERATOR_GET(_json) == 'l'))
145 JSON_FAIL("expected 'null'");
146 bufstr_add(_json_buffer, "", 0);
147 JSON_END();
148 }

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 183 of file json.qc.

183 {
184 JSON_BEGIN();
185 if (!(_json_parse_float() || _json_parse_int())) JSON_FAIL("expected number");
186 JSON_END();
187}
bool _json_parse_float()
Definition json.qc:190
bool _json_parse_int()
Definition json.qc:212

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 36 of file json.qc.

36 {
37 JSON_BEGIN();
38 if (STRING_ITERATOR_GET(_json) != '{') JSON_FAIL("expected '{'");
39 WITH(int, _json_keys, bufstr_add(_json_buffer, "", 0), _json_parse_members());
40 if (STRING_ITERATOR_GET(_json) != '}') JSON_FAIL("expected '}'");
41 JSON_END();
42}
int _json_keys
Definition json.qc:33
bool _json_parse_members()
Definition json.qc:45

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 59 of file json.qc.

59 {
60 JSON_BEGIN();
61 if (!_json_parse_string(false)) JSON_FAIL("expected string");
62 string key = _json_temp;
63 bufstr_set(_json_buffer, _json_keys, cons(bufstr_get(_json_buffer, _json_keys), key));
64 key = _json_ns ? strcat(_json_ns, ".", key) : key;
65 bufstr_add(_json_buffer, key, 0);
66 if (STRING_ITERATOR_GET(_json) != ':') JSON_FAIL("expected ':'");
67 bool ret = false; WITH(string, _json_ns, key, ret = _json_parse_value());
68 if (!ret) JSON_FAIL("expected value");
69 JSON_END();
70 }
string _json_temp
Definition json.qc:7
bool _json_parse_string(bool add)
Definition json.qc:151
ERASEABLE string cons(string a, string b)
Definition string.qh:276

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 151 of file json.qc.

151 {
152 JSON_BEGIN();
153 if (STRING_ITERATOR_GET(_json) != '"') JSON_FAIL("expected opening '\"'");
154 string s = "";
155 for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
156 if (c == '"') {
158 break;
159 } else if (c == '\\') {
160 string esc;
161 switch (STRING_ITERATOR_GET(_json)) {
162 default:
163 JSON_FAIL("expected ( '\"' | '\\' | 'n' | 't' )");
164 case '"': esc = "\""; break;
165 case '\\': esc = "\\"; break;
166 case 'n': esc = "\n"; break;
167 case 't': esc = "\t"; break;
168 case 'u': esc = "\\u"; break; // TODO
169 case '/': esc = "/"; break;
170 }
171 s = strcat(s, esc);
172 } else {
173 s = strcat(s, chr2str(c));
174 }
175 }
176 if (STRING_ITERATOR_GET(_json) != '"') JSON_FAIL("expected closing '\"'");
177 if (add) bufstr_add(_json_buffer, s, 0);
178 _json_temp = s;
179 JSON_END();
180}

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 114 of file json.qc.

114 {
115 JSON_BEGIN();
116 if (!(STRING_ITERATOR_GET(_json) == 't'
117 && STRING_ITERATOR_GET(_json) == 'r'
118 && STRING_ITERATOR_GET(_json) == 'u'
119 && STRING_ITERATOR_GET(_json) == 'e'))
120 JSON_FAIL("expected 'true'");
121 bufstr_add(_json_buffer, "1", 0);
122 JSON_END();
123 }

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 101 of file json.qc.

101 {
102 JSON_BEGIN();
103 if (!(_json_parse_string(true)
109 || _json_parse_null())) JSON_FAIL("expected value");
110 JSON_END();
111}
bool _json_parse_number()
Definition json.qc:183
bool _json_parse_true()
Definition json.qc:114
bool _json_parse_array()
Definition json.qc:73
bool _json_parse_false()
Definition json.qc:126
bool _json_parse_null()
Definition json.qc:139
bool _json_parse_object()
parse a json object
Definition json.qc:36

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 285 of file json.qc.

286{
287 buf_del(buf);
288}

◆ json_dump()

ERASEABLE void json_dump ( int buf)

Definition at line 291 of file json.qc.

292{
293 for (int i = 0, n = buf_getsize(buf); i < n; ++i) {
294 print(bufstr_get(buf, i), "\n");
295 }
296}
void print(string text,...)

References print().

Referenced by TEST().

◆ json_get()

ERASEABLE string json_get ( int buf,
string key )

Definition at line 276 of file json.qc.

277{
278 for (int i = 1, n = buf_getsize(buf); i < n; i += 2) {
279 if (bufstr_get(buf, i) == key) return bufstr_get(buf, i + 1);
280 }
281 return string_null;
282}
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 230 of file json.qc.

230 {
231 string trimmed = "";
232 LABEL(trim) {
233 int o = strstrofs(in, "\"", 0);
234 if (o >= 0) {
235 string part = substring(in, 0, o + 1); in = substring(in, o + 1, -1);
236 part = strreplace(" ", "", part);
237 part = strreplace("\n", "", part);
238 trimmed = strcat(trimmed, part);
239 goto trim_str;
240 } else {
241 string part = in;
242 part = strreplace(" ", "", part);
243 part = strreplace("\n", "", part);
244 trimmed = strcat(trimmed, part);
245 goto done;
246 }
247 }
248 LABEL(trim_str) {
249 int o = strstrofs(in, "\"", 0);
250 int esc = strstrofs(in, "\\\"", 0);
251 if (o < esc || esc < 0) {
252 // simple string
253 string part = substring(in, 0, o + 1); in = substring(in, o + 1, -1);
254 trimmed = strcat(trimmed, part);
255 goto trim;
256 } else {
257 // has escape
258 string part = substring(in, 0, esc + 2); in = substring(in, esc + 2, -1);
259 trimmed = strcat(trimmed, part);
260 goto trim_str;
261 }
262 }
263 LABEL(done);
264
265 STRING_ITERATOR_SET(_json, trimmed, 0);
267 bool ret = func();
268 if (!ret) {
269 buf_del(_json_buffer);
270 _json_buffer = -1;
271 }
272 return _json_buffer;
273}
#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 302 of file json.qc.

303{
304 string s = "{\n\
305 \"m_string\": \"\\\"string\\\"\",\n\
306 \"m_int\": 123,\n\
307 \"m_bool\": true,\n\
308 \"m_null\": null,\n\
309 \"m_obj\": { },\n\
310 \"m_arr\": [ ]\n}"; // "
311 print(s, "\n");
312 int buf = json_parse(s, _json_parse_object);
313 EXPECT_NE(-1, buf);
314 json_dump(buf);
315 SUCCEED();
316}
ERASEABLE int json_parse(string in, bool() func)
Definition json.qc:230
ERASEABLE void json_dump(int buf)
Definition json.qc:291
#define EXPECT_NE(val1, val2)
Definition test.qh:52
#define SUCCEED()
Must be present at the end of a test.
Definition test.qh:15

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

Variable Documentation

◆ _json_buffer

◆ _json_keys

int _json_keys

Definition at line 33 of file json.qc.

Referenced by _json_parse_object(), and _json_parse_pair().

◆ _json_ns

string _json_ns

Definition at line 31 of file json.qc.

Referenced by _json_parse_array(), and _json_parse_pair().

◆ _json_temp

string _json_temp

Definition at line 7 of file json.qc.

Referenced by _json_parse_pair(), and _json_parse_string().