Xonotic
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()   int __i = STRING_ITERATOR_SAVE(_json)
 
#define JSON_END()
 
#define JSON_FAIL(reason)   goto fail
 

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 More...
 
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

◆ JSON_FAIL

Function Documentation

◆ _json_parse_array()

ERASEABLE bool _json_parse_array ( )

Definition at line 73 of file json.qc.

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

Referenced by _json_parse_value().

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) == ',') {
90  STRING_ITERATOR_NEXT(_json);
91  required = true;
92  continue;
93  }
94  break;
95  }
96  if (STRING_ITERATOR_GET(_json) != ']') JSON_FAIL("expected ']'");
97  JSON_END();
98 }
#define JSON_BEGIN()
Definition: json.qc:23
bool _json_parse_value()
Definition: json.qc:101
string _json_ns
Definition: json.qc:31
#define STRING_ITERATOR_NEXT(this)
Definition: iter.qh:57
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
#define JSON_END()
Definition: json.qc:25
#define STRING_ITERATOR_GET(this)
Definition: iter.qh:55
int _json_buffer
Definition: json.qc:5
#define JSON_FAIL(reason)
Definition: json.qc:24
#define WITH(type, name, value, block)
Definition: misc.qh:40
#define STRING_ITERATOR_PEEK(this)
Definition: iter.qh:56
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _json_parse_false()

ERASEABLE bool _json_parse_false ( )

Definition at line 126 of file json.qc.

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

Referenced by _json_parse_value().

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  }
#define JSON_BEGIN()
Definition: json.qc:23
#define JSON_END()
Definition: json.qc:25
#define STRING_ITERATOR_GET(this)
Definition: iter.qh:55
int _json_buffer
Definition: json.qc:5
#define JSON_FAIL(reason)
Definition: json.qc:24
+ Here is the caller graph for this function:

◆ _json_parse_float()

ERASEABLE bool _json_parse_float ( )

Definition at line 190 of file json.qc.

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

Referenced by _json_parse_number().

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 {
200  STRING_ITERATOR_UNGET(_json);
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 JSON_BEGIN()
Definition: json.qc:23
#define STRING_ITERATOR_UNGET(this)
Definition: iter.qh:58
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
#define JSON_END()
Definition: json.qc:25
#define STRING_ITERATOR_GET(this)
Definition: iter.qh:55
int _json_buffer
Definition: json.qc:5
#define JSON_FAIL(reason)
Definition: json.qc:24
#define chr2str
Definition: dpextensions.qh:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _json_parse_int()

ERASEABLE bool _json_parse_int ( )

Definition at line 212 of file json.qc.

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

Referenced by _json_parse_number().

212  {
213  JSON_BEGIN();
214  string s = "";
215  for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
216  if (!(c >= '0' && c <= '9')) {
217  STRING_ITERATOR_UNGET(_json);
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  }
#define JSON_BEGIN()
Definition: json.qc:23
#define STRING_ITERATOR_UNGET(this)
Definition: iter.qh:58
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
#define JSON_END()
Definition: json.qc:25
#define STRING_ITERATOR_GET(this)
Definition: iter.qh:55
int _json_buffer
Definition: json.qc:5
#define JSON_FAIL(reason)
Definition: json.qc:24
#define chr2str
Definition: dpextensions.qh:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _json_parse_members()

ERASEABLE bool _json_parse_members ( )

Definition at line 45 of file json.qc.

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

Referenced by _json_parse_object().

45  {
46  JSON_BEGIN();
47  for (;;) {
48  if (!_json_parse_pair()) JSON_FAIL("expected pair");
49  if (STRING_ITERATOR_PEEK(_json) == ',') {
50  STRING_ITERATOR_NEXT(_json);
51  continue;
52  }
53  break;
54  }
55  JSON_END();
56  }
#define JSON_BEGIN()
Definition: json.qc:23
#define STRING_ITERATOR_NEXT(this)
Definition: iter.qh:57
#define JSON_END()
Definition: json.qc:25
#define JSON_FAIL(reason)
Definition: json.qc:24
bool _json_parse_pair()
Definition: json.qc:59
#define STRING_ITERATOR_PEEK(this)
Definition: iter.qh:56
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _json_parse_null()

ERASEABLE bool _json_parse_null ( )

Definition at line 139 of file json.qc.

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

Referenced by _json_parse_value().

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  }
#define JSON_BEGIN()
Definition: json.qc:23
#define JSON_END()
Definition: json.qc:25
#define STRING_ITERATOR_GET(this)
Definition: iter.qh:55
int _json_buffer
Definition: json.qc:5
#define JSON_FAIL(reason)
Definition: json.qc:24
+ Here is the caller graph for this function:

◆ _json_parse_number()

ERASEABLE bool _json_parse_number ( )

Definition at line 183 of file json.qc.

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

Referenced by _json_parse_value().

183  {
184  JSON_BEGIN();
185  if (!(_json_parse_float() || _json_parse_int())) JSON_FAIL("expected number");
186  JSON_END();
187 }
#define JSON_BEGIN()
Definition: json.qc:23
#define JSON_END()
Definition: json.qc:25
bool _json_parse_int()
Definition: json.qc:212
#define JSON_FAIL(reason)
Definition: json.qc:24
bool _json_parse_float()
Definition: json.qc:190
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _json_parse_object()

ERASEABLE bool _json_parse_object ( )

parse a json object

Definition at line 36 of file json.qc.

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

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

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 }
#define JSON_BEGIN()
Definition: json.qc:23
bool _json_parse_members()
Definition: json.qc:45
#define JSON_END()
Definition: json.qc:25
int _json_keys
Definition: json.qc:33
#define STRING_ITERATOR_GET(this)
Definition: iter.qh:55
int _json_buffer
Definition: json.qc:5
#define JSON_FAIL(reason)
Definition: json.qc:24
#define WITH(type, name, value, block)
Definition: misc.qh:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _json_parse_pair()

ERASEABLE bool _json_parse_pair ( )

Definition at line 59 of file json.qc.

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

Referenced by _json_parse_members().

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  }
#define JSON_BEGIN()
Definition: json.qc:23
bool _json_parse_value()
Definition: json.qc:101
string _json_temp
Definition: json.qc:7
string _json_ns
Definition: json.qc:31
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
#define JSON_END()
Definition: json.qc:25
int _json_keys
Definition: json.qc:33
bool _json_parse_string(bool add)
Definition: json.qc:151
#define STRING_ITERATOR_GET(this)
Definition: iter.qh:55
int _json_buffer
Definition: json.qc:5
#define JSON_FAIL(reason)
Definition: json.qc:24
#define WITH(type, name, value, block)
Definition: misc.qh:40
ERASEABLE string cons(string a, string b)
Definition: string.qh:257
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _json_parse_string()

ERASEABLE bool _json_parse_string ( bool  add)

Definition at line 151 of file json.qc.

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

Referenced by _json_parse_pair(), and _json_parse_value().

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 == '"') {
157  STRING_ITERATOR_UNGET(_json);
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 }
#define JSON_BEGIN()
Definition: json.qc:23
string _json_temp
Definition: json.qc:7
#define STRING_ITERATOR_UNGET(this)
Definition: iter.qh:58
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
#define JSON_END()
Definition: json.qc:25
#define STRING_ITERATOR_GET(this)
Definition: iter.qh:55
int _json_buffer
Definition: json.qc:5
#define JSON_FAIL(reason)
Definition: json.qc:24
#define chr2str
Definition: dpextensions.qh:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _json_parse_true()

ERASEABLE bool _json_parse_true ( )

Definition at line 114 of file json.qc.

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

Referenced by _json_parse_value().

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  }
#define JSON_BEGIN()
Definition: json.qc:23
#define JSON_END()
Definition: json.qc:25
#define STRING_ITERATOR_GET(this)
Definition: iter.qh:55
int _json_buffer
Definition: json.qc:5
#define JSON_FAIL(reason)
Definition: json.qc:24
+ Here is the caller graph for this function:

◆ _json_parse_value()

ERASEABLE bool _json_parse_value ( )

Definition at line 101 of file json.qc.

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

Referenced by _json_parse_array(), and _json_parse_pair().

101  {
102  JSON_BEGIN();
103  if (!(_json_parse_string(true)
104  || _json_parse_number()
105  || _json_parse_object()
106  || _json_parse_array()
107  || _json_parse_true()
108  || _json_parse_false()
109  || _json_parse_null())) JSON_FAIL("expected value");
110  JSON_END();
111 }
#define JSON_BEGIN()
Definition: json.qc:23
bool _json_parse_array()
Definition: json.qc:73
bool _json_parse_number()
Definition: json.qc:183
bool _json_parse_false()
Definition: json.qc:126
#define JSON_END()
Definition: json.qc:25
bool _json_parse_true()
Definition: json.qc:114
bool _json_parse_string(bool add)
Definition: json.qc:151
bool _json_parse_object()
parse a json object
Definition: json.qc:36
#define JSON_FAIL(reason)
Definition: json.qc:24
bool _json_parse_null()
Definition: json.qc:139
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ json_del()

ERASEABLE void json_del ( int  buf)

Definition at line 285 of file json.qc.

References ERASEABLE.

286 {
287  buf_del(buf);
288 }

◆ json_dump()

ERASEABLE void json_dump ( int  buf)

Definition at line 291 of file json.qc.

References print().

Referenced by TEST().

292 {
293  for (int i = 0, n = buf_getsize(buf); i < n; ++i) {
294  print(bufstr_get(buf, i), "\n");
295  }
296 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ json_get()

ERASEABLE string json_get ( int  buf,
string  key 
)

Definition at line 276 of file json.qc.

References ERASEABLE, and string_null.

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

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
+ Here is the caller graph for this function:

◆ json_parse()

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

Definition at line 230 of file json.qc.

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

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

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 buf_create
Definition: dpextensions.qh:63
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
#define strstrofs
Definition: dpextensions.qh:42
int _json_buffer
Definition: json.qc:5
#define LABEL(id)
Definition: compiler.qh:36
#define STRING_ITERATOR_SET(this, s, i)
Definition: iter.qh:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ STRING_ITERATOR()

STRING_ITERATOR ( _json  ,
string_null  ,
 
)

Referenced by STATIC_INIT(), and TEST().

+ Here is the caller graph for this function:

◆ TEST()

TEST ( json  ,
Parse   
)

Definition at line 302 of file json.qc.

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

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
#define EXPECT_NE(val1, val2)
Definition: test.qh:52
#define SUCCEED()
Must be present at the end of a test.
Definition: test.qh:15
ERASEABLE void json_dump(int buf)
Definition: json.qc:291
bool _json_parse_object()
parse a json object
Definition: json.qc:36
+ Here is the call graph for this function:

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().