]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/lib/json.qc
take3: format 903 files
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / json.qc
index 241b537aaa329a70d544e0a8d7a367462ba9e0cc..a1a9c4ec70928a202556102cbad7a51a50362aec 100644 (file)
@@ -8,291 +8,320 @@ string _json_temp;
 
 /** parse a json object */
 bool _json_parse_object();
-    bool _json_parse_members();
-        bool _json_parse_pair();
+bool _json_parse_members();
+bool _json_parse_pair();
 bool _json_parse_array();
 bool _json_parse_value();
-    bool _json_parse_true();
-    bool _json_parse_false();
-    bool _json_parse_null();
+bool _json_parse_true();
+bool _json_parse_false();
+bool _json_parse_null();
 bool _json_parse_string(bool add);
 bool _json_parse_number();
-    bool _json_parse_float();
-    bool _json_parse_int();
+bool _json_parse_float();
+bool _json_parse_int();
 
 #define JSON_BEGIN() int __i = STRING_ITERATOR_SAVE(_json)
 #define JSON_FAIL(reason) goto fail
 #define JSON_END() \
-   return true; \
-LABEL(fail) \
-   STRING_ITERATOR_LOAD(_json, __i); \
-   return false;
+       return true; \
+       LABEL(fail) \
+       STRING_ITERATOR_LOAD(_json, __i); \
+       return false;
 // Current namespace
 string _json_ns;
 // Current keys
 int _json_keys;
 
 ERASEABLE
-bool _json_parse_object() {
-    JSON_BEGIN();
-    if (STRING_ITERATOR_GET(_json) != '{') JSON_FAIL("expected '{'");
-    WITH(int, _json_keys, bufstr_add(_json_buffer, "", 0), _json_parse_members());
-    if (STRING_ITERATOR_GET(_json) != '}') JSON_FAIL("expected '}'");
-    JSON_END();
+bool _json_parse_object()
+{
+       JSON_BEGIN();
+       if (STRING_ITERATOR_GET(_json) != '{') { JSON_FAIL("expected '{'"); }
+       WITH(int, _json_keys, bufstr_add(_json_buffer, "", 0), _json_parse_members());
+       if (STRING_ITERATOR_GET(_json) != '}') { JSON_FAIL("expected '}'"); }
+       JSON_END();
 }
 
-    ERASEABLE
-    bool _json_parse_members() {
-        JSON_BEGIN();
-        for (;;) {
-            if (!_json_parse_pair()) JSON_FAIL("expected pair");
-            if (STRING_ITERATOR_PEEK(_json) == ',') {
-                STRING_ITERATOR_NEXT(_json);
-                continue;
-            }
-            break;
-        }
-        JSON_END();
-    }
+ERASEABLE
+bool _json_parse_members()
+{
+       JSON_BEGIN();
+       for ( ; ; ) {
+               if (!_json_parse_pair()) { JSON_FAIL("expected pair"); }
+               if (STRING_ITERATOR_PEEK(_json) == ',') {
+                       STRING_ITERATOR_NEXT(_json);
+                       continue;
+               }
+               break;
+       }
+       JSON_END();
+}
 
-        ERASEABLE
-        bool _json_parse_pair() {
-            JSON_BEGIN();
-            if (!_json_parse_string(false)) JSON_FAIL("expected string");
-            string key = _json_temp;
-            bufstr_set(_json_buffer, _json_keys, cons(bufstr_get(_json_buffer, _json_keys), key));
-            key = _json_ns ? strcat(_json_ns, ".", key) : key;
-            bufstr_add(_json_buffer, key, 0);
-            if (STRING_ITERATOR_GET(_json) != ':') JSON_FAIL("expected ':'");
-            bool ret = false; WITH(string, _json_ns, key, ret = _json_parse_value());
-            if (!ret) JSON_FAIL("expected value");
-            JSON_END();
-        }
+ERASEABLE
+bool _json_parse_pair()
+{
+       JSON_BEGIN();
+       if (!_json_parse_string(false)) { JSON_FAIL("expected string"); }
+       string key = _json_temp;
+       bufstr_set(_json_buffer, _json_keys, cons(bufstr_get(_json_buffer, _json_keys), key));
+       key = _json_ns ? strcat(_json_ns, ".", key) : key;
+       bufstr_add(_json_buffer, key, 0);
+       if (STRING_ITERATOR_GET(_json) != ':') { JSON_FAIL("expected ':'"); }
+       bool ret = false;
+       WITH(string, _json_ns, key, ret = _json_parse_value());
+       if (!ret) { JSON_FAIL("expected value"); }
+       JSON_END();
+}
 
 ERASEABLE
-bool _json_parse_array() {
-    JSON_BEGIN();
-    if (STRING_ITERATOR_GET(_json) != '[') JSON_FAIL("expected '['");
-    int len = bufstr_add(_json_buffer, "0", 0);
-    if (len) bufstr_set(_json_buffer, len - 1, strcat(bufstr_get(_json_buffer, len - 1), ".length"));
-    bool required = false;
-    for (int n = 0; ; n++) {
-        string key = ftos(n);
-        key = _json_ns ? strcat(_json_ns, ".", key) : key;
-        int it = bufstr_add(_json_buffer, key, 0);
-        bool ret = false; WITH(string, _json_ns, key, ret = _json_parse_value());
-        if (!ret) {
-            bufstr_free(_json_buffer, it);
-            if (required) JSON_FAIL("expected value"); else break;
-        }
-        bufstr_set(_json_buffer, len, ftos(n + 1));
-        if (STRING_ITERATOR_PEEK(_json) == ',') {
-            STRING_ITERATOR_NEXT(_json);
-            required = true;
-            continue;
-        }
-        break;
-    }
-    if (STRING_ITERATOR_GET(_json) != ']') JSON_FAIL("expected ']'");
-    JSON_END();
+bool _json_parse_array()
+{
+       JSON_BEGIN();
+       if (STRING_ITERATOR_GET(_json) != '[') { JSON_FAIL("expected '['"); }
+       int len = bufstr_add(_json_buffer, "0", 0);
+       if (len) { bufstr_set(_json_buffer, len - 1, strcat(bufstr_get(_json_buffer, len - 1), ".length")); }
+       bool required = false;
+       for (int n = 0; ; n++) {
+               string key = ftos(n);
+               key = _json_ns ? strcat(_json_ns, ".", key) : key;
+               int it = bufstr_add(_json_buffer, key, 0);
+               bool ret = false;
+               WITH(string, _json_ns, key, ret = _json_parse_value());
+               if (!ret) {
+                       bufstr_free(_json_buffer, it);
+                       if (required) { JSON_FAIL("expected value"); } else { break; }
+               }
+               bufstr_set(_json_buffer, len, ftos(n + 1));
+               if (STRING_ITERATOR_PEEK(_json) == ',') {
+                       STRING_ITERATOR_NEXT(_json);
+                       required = true;
+                       continue;
+               }
+               break;
+       }
+       if (STRING_ITERATOR_GET(_json) != ']') { JSON_FAIL("expected ']'"); }
+       JSON_END();
 }
 
 ERASEABLE
-bool _json_parse_value() {
-    JSON_BEGIN();
-    if (!(_json_parse_string(true)
-        || _json_parse_number()
-        || _json_parse_object()
-        || _json_parse_array()
-        || _json_parse_true()
-        || _json_parse_false()
-        || _json_parse_null())) JSON_FAIL("expected value");
-    JSON_END();
+bool _json_parse_value()
+{
+       JSON_BEGIN();
+       if (!(_json_parse_string(true)
+               || _json_parse_number()
+               || _json_parse_object()
+               || _json_parse_array()
+               || _json_parse_true()
+               || _json_parse_false()
+               || _json_parse_null())) { JSON_FAIL("expected value"); }
+       JSON_END();
 }
 
-    ERASEABLE
-    bool _json_parse_true() {
-        JSON_BEGIN();
-        if (!(STRING_ITERATOR_GET(_json) == 't'
-            && STRING_ITERATOR_GET(_json) == 'r'
-            && STRING_ITERATOR_GET(_json) == 'u'
-            && STRING_ITERATOR_GET(_json) == 'e'))
-            JSON_FAIL("expected 'true'");
-        bufstr_add(_json_buffer, "1", 0);
-        JSON_END();
-    }
+ERASEABLE
+bool _json_parse_true()
+{
+       JSON_BEGIN();
+       if (!(STRING_ITERATOR_GET(_json) == 't'
+               && STRING_ITERATOR_GET(_json) == 'r'
+               && STRING_ITERATOR_GET(_json) == 'u'
+               && STRING_ITERATOR_GET(_json) == 'e')) {
+               JSON_FAIL("expected 'true'");
+       }
+       bufstr_add(_json_buffer, "1", 0);
+       JSON_END();
+}
 
-    ERASEABLE
-    bool _json_parse_false() {
-        JSON_BEGIN();
-        if (!(STRING_ITERATOR_GET(_json) == 'f'
-            && STRING_ITERATOR_GET(_json) == 'a'
-            && STRING_ITERATOR_GET(_json) == 'l'
-            && STRING_ITERATOR_GET(_json) == 's'
-            && STRING_ITERATOR_GET(_json) == 'e'))
-            JSON_FAIL("expected 'false'");
-        bufstr_add(_json_buffer, "0", 0);
-        JSON_END();
-    }
+ERASEABLE
+bool _json_parse_false()
+{
+       JSON_BEGIN();
+       if (!(STRING_ITERATOR_GET(_json) == 'f'
+               && STRING_ITERATOR_GET(_json) == 'a'
+               && STRING_ITERATOR_GET(_json) == 'l'
+               && STRING_ITERATOR_GET(_json) == 's'
+               && STRING_ITERATOR_GET(_json) == 'e')) {
+               JSON_FAIL("expected 'false'");
+       }
+       bufstr_add(_json_buffer, "0", 0);
+       JSON_END();
+}
 
-    ERASEABLE
-    bool _json_parse_null() {
-        JSON_BEGIN();
-        if (!(STRING_ITERATOR_GET(_json) == 'n'
-            && STRING_ITERATOR_GET(_json) == 'u'
-            && STRING_ITERATOR_GET(_json) == 'l'
-            && STRING_ITERATOR_GET(_json) == 'l'))
-            JSON_FAIL("expected 'null'");
-        bufstr_add(_json_buffer, "", 0);
-        JSON_END();
-    }
+ERASEABLE
+bool _json_parse_null()
+{
+       JSON_BEGIN();
+       if (!(STRING_ITERATOR_GET(_json) == 'n'
+               && STRING_ITERATOR_GET(_json) == 'u'
+               && STRING_ITERATOR_GET(_json) == 'l'
+               && STRING_ITERATOR_GET(_json) == 'l')) {
+               JSON_FAIL("expected 'null'");
+       }
+       bufstr_add(_json_buffer, "", 0);
+       JSON_END();
+}
 
 ERASEABLE
-bool _json_parse_string(bool add) {
-    JSON_BEGIN();
-    if (STRING_ITERATOR_GET(_json) != '"') JSON_FAIL("expected opening '\"'");
-    string s = "";
-    for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
-        if (c == '"') {
-            STRING_ITERATOR_UNGET(_json);
-            break;
-        } else if (c == '\\') {
-            string esc;
-            switch (STRING_ITERATOR_GET(_json)) {
-                default:
-                    JSON_FAIL("expected ( '\"' | '\\' | 'n' | 't' )");
-                case '"': esc = "\""; break;
-                case '\\': esc = "\\"; break;
-                case 'n': esc = "\n"; break;
-                case 't': esc = "\t"; break;
-                case 'u': esc = "\\u"; break; // TODO
-                case '/': esc = "/"; break;
-            }
-            s = strcat(s, esc);
-        } else {
-            s = strcat(s, chr2str(c));
-        }
-    }
-    if (STRING_ITERATOR_GET(_json) != '"') JSON_FAIL("expected closing '\"'");
-    if (add) bufstr_add(_json_buffer, s, 0);
-    _json_temp = s;
-    JSON_END();
+bool _json_parse_string(bool add)
+{
+       JSON_BEGIN();
+       if (STRING_ITERATOR_GET(_json) != '"') { JSON_FAIL("expected opening '\"'"); }
+       string s = "";
+       for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
+               if (c == '"') {
+                       STRING_ITERATOR_UNGET(_json);
+                       break;
+               } else if (c == '\\') {
+                       string esc;
+                       switch (STRING_ITERATOR_GET(_json)) {
+                               default:
+                                       JSON_FAIL("expected ( '\"' | '\\' | 'n' | 't' )");
+                               case '"': esc = "\"";
+                                       break;
+                               case '\\': esc = "\\";
+                                       break;
+                               case 'n': esc = "\n";
+                                       break;
+                               case 't': esc = "\t";
+                                       break;
+                               case 'u': esc = "\\u";
+                                       break; // TODO
+                               case '/': esc = "/";
+                                       break;
+                       }
+                       s = strcat(s, esc);
+               } else {
+                       s = strcat(s, chr2str(c));
+               }
+       }
+       if (STRING_ITERATOR_GET(_json) != '"') { JSON_FAIL("expected closing '\"'"); }
+       if (add) { bufstr_add(_json_buffer, s, 0); }
+       _json_temp = s;
+       JSON_END();
 }
 
 ERASEABLE
-bool _json_parse_number() {
-    JSON_BEGIN();
-    if (!(_json_parse_float() || _json_parse_int())) JSON_FAIL("expected number");
-    JSON_END();
+bool _json_parse_number()
+{
+       JSON_BEGIN();
+       if (!(_json_parse_float() || _json_parse_int())) { JSON_FAIL("expected number"); }
+       JSON_END();
 }
 
-    ERASEABLE
-    bool _json_parse_float() {
-        JSON_BEGIN();
-        string s = "";
-        bool needdot = true;
-        for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
-            if (!(c >= '0' && c <= '9')) {
-                if (c == '.' && needdot) {
-                    // fine
-                    needdot = false;
-                } else {
-                    STRING_ITERATOR_UNGET(_json);
-                    break;
-                }
-            }
-            s = strcat(s, chr2str(c));
-        }
-        if (s == "") JSON_FAIL("expected float");
-        bufstr_add(_json_buffer, s, 0);
-        JSON_END();
-    }
+ERASEABLE
+bool _json_parse_float()
+{
+       JSON_BEGIN();
+       string s = "";
+       bool needdot = true;
+       for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
+               if (!(c >= '0' && c <= '9')) {
+                       if (c == '.' && needdot) {
+                               // fine
+                               needdot = false;
+                       } else {
+                               STRING_ITERATOR_UNGET(_json);
+                               break;
+                       }
+               }
+               s = strcat(s, chr2str(c));
+       }
+       if (s == "") { JSON_FAIL("expected float"); }
+       bufstr_add(_json_buffer, s, 0);
+       JSON_END();
+}
 
-    ERASEABLE
-    bool _json_parse_int() {
-        JSON_BEGIN();
-        string s = "";
-        for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
-            if (!(c >= '0' && c <= '9')) {
-                STRING_ITERATOR_UNGET(_json);
-                break;
-            }
-            if (s == "" && c == '0') JSON_FAIL("expected [1-9]");
-            s = strcat(s, chr2str(c));
-        }
-        if (s == "") JSON_FAIL("expected int");
-        if (ftos(stof(s)) != s) JSON_FAIL("expected int");
-        bufstr_add(_json_buffer, s, 0);
-        JSON_END();
-    }
+ERASEABLE
+bool _json_parse_int()
+{
+       JSON_BEGIN();
+       string s = "";
+       for (int c; (c = STRING_ITERATOR_GET(_json)); ) {
+               if (!(c >= '0' && c <= '9')) {
+                       STRING_ITERATOR_UNGET(_json);
+                       break;
+               }
+               if (s == "" && c == '0') { JSON_FAIL("expected [1-9]"); }
+               s = strcat(s, chr2str(c));
+       }
+       if (s == "") { JSON_FAIL("expected int"); }
+       if (ftos(stof(s)) != s) { JSON_FAIL("expected int"); }
+       bufstr_add(_json_buffer, s, 0);
+       JSON_END();
+}
 
 ERASEABLE
-int json_parse(string in, bool() func) {
-    string trimmed = "";
-    LABEL(trim) {
-        int o = strstrofs(in, "\"", 0);
-        if (o >= 0) {
-            string part = substring(in, 0, o + 1); in = substring(in, o + 1, -1);
-            part = strreplace(" ", "", part);
-            part = strreplace("\n", "", part);
-            trimmed = strcat(trimmed, part);
-            goto trim_str;
-        } else {
-            string part = in;
-            part = strreplace(" ", "", part);
-            part = strreplace("\n", "", part);
-            trimmed = strcat(trimmed, part);
-            goto done;
-        }
-    }
-    LABEL(trim_str) {
-        int o = strstrofs(in, "\"", 0);
-        int esc = strstrofs(in, "\\\"", 0);
-        if (o < esc || esc < 0) {
-            // simple string
-            string part = substring(in, 0, o + 1); in = substring(in, o + 1, -1);
-            trimmed = strcat(trimmed, part);
-            goto trim;
-        } else {
-            // has escape
-            string part = substring(in, 0, esc + 2); in = substring(in, esc + 2, -1);
-            trimmed = strcat(trimmed, part);
-            goto trim_str;
-        }
-    }
-    LABEL(done);
+int json_parse(string in, bool() func)
+{
+       string trimmed = "";
+       LABEL(trim)
+       {
+               int o = strstrofs(in, "\"", 0);
+               if (o >= 0) {
+                       string part = substring(in, 0, o + 1);
+                       in = substring(in, o + 1, -1);
+                       part = strreplace(" ", "", part);
+                       part = strreplace("\n", "", part);
+                       trimmed = strcat(trimmed, part);
+                       goto trim_str;
+               } else {
+                       string part = in;
+                       part = strreplace(" ", "", part);
+                       part = strreplace("\n", "", part);
+                       trimmed = strcat(trimmed, part);
+                       goto done;
+               }
+       }
+       LABEL(trim_str)
+       {
+               int o = strstrofs(in, "\"", 0);
+               int esc = strstrofs(in, "\\\"", 0);
+               if (o < esc || esc < 0) {
+                       // simple string
+                       string part = substring(in, 0, o + 1);
+                       in = substring(in, o + 1, -1);
+                       trimmed = strcat(trimmed, part);
+                       goto trim;
+               } else {
+                       // has escape
+                       string part = substring(in, 0, esc + 2);
+                       in = substring(in, esc + 2, -1);
+                       trimmed = strcat(trimmed, part);
+                       goto trim_str;
+               }
+       }
+       LABEL(done);
 
-    STRING_ITERATOR_SET(_json, trimmed, 0);
-    _json_buffer = buf_create();
-    bool ret = func();
-    if (!ret) {
-        buf_del(_json_buffer);
-        _json_buffer = -1;
-    }
-    return _json_buffer;
+       STRING_ITERATOR_SET(_json, trimmed, 0);
+       _json_buffer = buf_create();
+       bool ret = func();
+       if (!ret) {
+               buf_del(_json_buffer);
+               _json_buffer = -1;
+       }
+       return _json_buffer;
 }
 
 ERASEABLE
 string json_get(int buf, string key)
 {
-    for (int i = 1, n = buf_getsize(buf); i < n; i += 2) {
-        if (bufstr_get(buf, i) == key) return bufstr_get(buf, i + 1);
-    }
-    return string_null;
+       for (int i = 1, n = buf_getsize(buf); i < n; i += 2) {
+               if (bufstr_get(buf, i) == key) { return bufstr_get(buf, i + 1); }
+       }
+       return string_null;
 }
 
 ERASEABLE
 void json_del(int buf)
 {
-    buf_del(buf);
+       buf_del(buf);
 }
 
 ERASEABLE
 void json_dump(int buf)
 {
-    for (int i = 0, n = buf_getsize(buf); i < n; ++i) {
-        print(bufstr_get(buf, i), "\n");
-    }
+       for (int i = 0, n = buf_getsize(buf); i < n; ++i) {
+               print(bufstr_get(buf, i), "\n");
+       }
 }
 
 #undef JSON_BEGIN
@@ -301,16 +330,16 @@ void json_dump(int buf)
 
 TEST(json, Parse)
 {
-    string s = "{\n\
+       string s = "{\n\
     \"m_string\": \"\\\"string\\\"\",\n\
     \"m_int\": 123,\n\
     \"m_bool\": true,\n\
     \"m_null\": null,\n\
     \"m_obj\": { },\n\
     \"m_arr\": [ ]\n}"; // "
-    print(s, "\n");
-    int buf = json_parse(s, _json_parse_object);
-    EXPECT_NE(-1, buf);
-    json_dump(buf);
-    SUCCEED();
+       print(s, "\n");
+       int buf = json_parse(s, _json_parse_object);
+       EXPECT_NE(-1, buf);
+       json_dump(buf);
+       SUCCEED();
 }