aboutsummaryrefslogtreecommitdiff
path: root/src/query_data.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/query_data.cpp')
-rw-r--r--src/query_data.cpp361
1 files changed, 361 insertions, 0 deletions
diff --git a/src/query_data.cpp b/src/query_data.cpp
new file mode 100644
index 000000000..5b97512ee
--- /dev/null
+++ b/src/query_data.cpp
@@ -0,0 +1,361 @@
+struct QueryValue;
+struct QueryValuePair;
+
+gbAllocator query_value_allocator = {};
+
+enum QueryKind {
+ Query_Invalid,
+ Query_String,
+ Query_Boolean,
+ Query_Integer,
+ Query_Float,
+ Query_Array,
+ Query_Map,
+};
+
+struct QueryValuePair {
+ String key;
+ QueryValue *value;
+};
+
+
+struct QueryValue {
+ QueryKind kind;
+ bool packed;
+};
+
+struct QueryValueString : QueryValue {
+ QueryValueString(String const &v) {
+ kind = Query_String;
+ value = v;
+ packed = false;
+ }
+ String value;
+};
+
+struct QueryValueBoolean : QueryValue {
+ QueryValueBoolean(bool v) {
+ kind = Query_Boolean;
+ value = v;
+ packed = false;
+ }
+ bool value;
+};
+
+struct QueryValueInteger : QueryValue {
+ QueryValueInteger(i64 v) {
+ kind = Query_Integer;
+ value = v;
+ packed = false;
+ }
+ i64 value;
+};
+
+struct QueryValueFloat : QueryValue {
+ QueryValueFloat(f64 v) {
+ kind = Query_Float;
+ value = v;
+ packed = false;
+ }
+ f64 value;
+};
+
+struct QueryValueArray : QueryValue {
+ QueryValueArray() {
+ kind = Query_Array;
+ array_init(&value, query_value_allocator);
+ packed = false;
+ }
+ QueryValueArray(Array<QueryValue *> const &v) {
+ kind = Query_Array;
+ value = v;
+ packed = false;
+ }
+ Array<QueryValue *> value;
+
+ void reserve(isize cap) {
+ array_reserve(&value, cap);
+ }
+ void add(QueryValue *v) {
+ array_add(&value, v);
+ }
+ void add(char const *v) {
+ add(make_string_c(cast(char *)v));
+ }
+ void add(String const &v) {
+ auto val = gb_alloc_item(query_value_allocator, QueryValueString);
+ *val = QueryValueString(v);
+ add(val);
+ }
+ void add(bool v) {
+ auto val = gb_alloc_item(query_value_allocator, QueryValueBoolean);
+ *val = QueryValueBoolean(v);
+ add(val);
+ }
+ void add(i64 v) {
+ auto val = gb_alloc_item(query_value_allocator, QueryValueInteger);
+ *val = QueryValueInteger(v);
+ add(val);
+ }
+ void add(f64 v) {
+ auto val = gb_alloc_item(query_value_allocator, QueryValueFloat);
+ *val = QueryValueFloat(v);
+ add(val);
+ }
+};
+
+struct QueryValueMap : QueryValue {
+ QueryValueMap() {
+ kind = Query_Map;
+ array_init(&value, query_value_allocator);
+ packed = false;
+ }
+ QueryValueMap(Array<QueryValuePair> const &v) {
+ kind = Query_Map;
+ value = v;
+ packed = false;
+ }
+ Array<QueryValuePair> value;
+
+
+ void reserve(isize cap) {
+ array_reserve(&value, cap);
+ }
+ void add(char const *k, QueryValue *v) {
+ add(make_string_c(cast(char *)k), v);
+ }
+ void add(String const &k, QueryValue *v) {
+ QueryValuePair kv = {k, v};
+ array_add(&value, kv);
+ }
+
+ void add(char const *k, String const &v) {
+ auto val = gb_alloc_item(query_value_allocator, QueryValueString);
+ *val = QueryValueString(v);
+ add(k, val);
+ }
+ void add(char const *k, char const *v) {
+ add(k, make_string_c(cast(char *)v));
+ }
+ void add(char const *k, bool v) {
+ auto val = gb_alloc_item(query_value_allocator, QueryValueBoolean);
+ *val = QueryValueBoolean(v);
+ add(k, val);
+ }
+ void add(char const *k, i64 v) {
+ auto val = gb_alloc_item(query_value_allocator, QueryValueInteger);
+ *val = QueryValueInteger(v);
+ add(k, val);
+ }
+ void add(char const *k, f64 v) {
+ auto val = gb_alloc_item(query_value_allocator, QueryValueFloat);
+ *val = QueryValueFloat(v);
+ add(k, val);
+ }
+ void add(String const &k, String const &v) {
+ auto val = gb_alloc_item(query_value_allocator, QueryValueString);
+ *val = QueryValueString(v);
+ add(k, val);
+ }
+ void add(String const &k, char const *v) {
+ add(k, make_string_c(cast(char *)v));
+ }
+ void add(String const &k, bool v) {
+ auto val = gb_alloc_item(query_value_allocator, QueryValueBoolean);
+ *val = QueryValueBoolean(v);
+ add(k, val);
+ }
+ void add(String const &k, i64 v) {
+ auto val = gb_alloc_item(query_value_allocator, QueryValueInteger);
+ *val = QueryValueInteger(v);
+ add(k, val);
+ }
+ void add(String const &k, f64 v) {
+ auto val = gb_alloc_item(query_value_allocator, QueryValueFloat);
+ *val = QueryValueFloat(v);
+ add(k, val);
+ }
+};
+
+
+#define DEF_QUERY_PROC(TYPE, VALUETYPE, NAME) TYPE *NAME(VALUETYPE value) { \
+ auto v = gb_alloc_item(query_value_allocator, TYPE); \
+ *v = TYPE(value); \
+ return v; \
+}
+#define DEF_QUERY_PROC0(TYPE, NAME) TYPE *NAME() { \
+ auto v = gb_alloc_item(query_value_allocator, TYPE); \
+ *v = TYPE(); \
+ return v; \
+}
+
+DEF_QUERY_PROC(QueryValueString, String const &, query_value_string);
+DEF_QUERY_PROC(QueryValueBoolean, bool, query_value_boolean);
+DEF_QUERY_PROC(QueryValueInteger, i64, query_value_integer);
+DEF_QUERY_PROC(QueryValueFloat, f64, query_value_float);
+DEF_QUERY_PROC(QueryValueArray, Array<QueryValue *> const &, query_value_array);
+DEF_QUERY_PROC(QueryValueMap, Array<QueryValuePair> const &, query_value_map);
+DEF_QUERY_PROC0(QueryValueArray, query_value_array);
+DEF_QUERY_PROC0(QueryValueMap, query_value_map);
+
+isize qprintf(bool format, isize indent, char const *fmt, ...) {
+ if (format) while (indent --> 0) {
+ gb_printf("\t");
+ }
+ va_list va;
+ va_start(va, fmt);
+ isize res = gb_printf_va(fmt, va);
+ va_end(va);
+ return res;
+}
+
+bool qv_valid_char(u8 c) {
+ if (c >= 0x80) {
+ return false;
+ }
+
+ switch (c) {
+ case '\"':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ case '\f':
+ return false;
+ }
+
+ return true;
+}
+
+void print_query_data_as_json(QueryValue *value, bool format = true, isize indent = 0) {
+ if (value == nullptr) {
+ gb_printf("null");
+ return;
+ }
+ switch (value->kind) {
+ case Query_String: {
+ auto v = cast(QueryValueString *)value;
+ String name = v->value;
+ isize extra = 0;
+ for (isize i = 0; i < name.len; i++) {
+ u8 c = name[i];
+ if (!qv_valid_char(c)) {
+ extra += 5;
+ }
+ }
+
+ if (extra == 0) {
+ gb_printf("\"%.*s\"", LIT(name));
+ return;
+ }
+
+ char const hex_table[] = "0123456789ABCDEF";
+ isize buf_len = name.len + extra + 2 + 1;
+
+ gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
+ defer (gb_temp_arena_memory_end(tmp));
+
+ u8 *buf = gb_alloc_array(string_buffer_allocator, u8, buf_len);
+
+ isize j = 0;
+
+ for (isize i = 0; i < name.len; i++) {
+ u8 c = name[i];
+ if (qv_valid_char(c)) {
+ buf[j+0] = c;
+ j += 1;
+ } else if (c == '"') {
+ buf[j+0] = '\\';
+ buf[j+1] = '\"';
+ j += 2;
+ } else {
+ switch (c) {
+ case '\n': buf[j+0] = '\\'; buf[j+1] = 'n'; j += 2; break;
+ case '\r': buf[j+0] = '\\'; buf[j+1] = 'r'; j += 2; break;
+ case '\t': buf[j+0] = '\\'; buf[j+1] = 't'; j += 2; break;
+ case '\v': buf[j+0] = '\\'; buf[j+1] = 'v'; j += 2; break;
+ case '\f':
+ default:
+ buf[j+0] = '\\';
+ buf[j+1] = hex_table[0];
+ buf[j+2] = hex_table[0];
+ buf[j+3] = hex_table[c >> 4];
+ buf[j+4] = hex_table[c & 0x0f];
+ j += 5;
+ break;
+ }
+ }
+ }
+
+ gb_printf("\"%s\"", buf);
+ return;
+ }
+ case Query_Boolean: {
+ auto v = cast(QueryValueBoolean *)value;
+ if (v->value) {
+ gb_printf("true");
+ } else {
+ gb_printf("false");
+ }
+ return;
+ }
+ case Query_Integer: {
+ auto v = cast(QueryValueInteger *)value;
+ gb_printf("%lld", v->value);
+ return;
+ }
+ case Query_Float: {
+ auto v = cast(QueryValueFloat *)value;
+ gb_printf("%f", v->value);
+ return;
+ }
+ case Query_Array: {
+ auto v = cast(QueryValueArray *)value;
+ if (v->value.count > 0) {
+ bool ff = format && !v->packed;
+ gb_printf("[");
+ if (ff) gb_printf("\n");
+ for_array(i, v->value) {
+ qprintf(ff, indent+1, "");
+ print_query_data_as_json(v->value[i], ff, indent+1);
+ if (i < v->value.count-1) {
+ gb_printf(",");
+ if (!ff && format) {
+ gb_printf(" ");
+ }
+ }
+ if (ff) gb_printf("\n");
+ }
+ qprintf(ff, indent, "]");
+ } else {
+ gb_printf("[]");
+ }
+ return;
+ }
+ case Query_Map: {
+ auto v = cast(QueryValueMap *)value;
+ if (v->value.count > 0) {
+ bool ff = format && !v->packed;
+ gb_printf("{");
+ if (ff) gb_printf("\n");
+ for_array(i, v->value) {
+ auto kv = v->value[i];
+ qprintf(ff, indent+1, "\"%.*s\":", LIT(kv.key));
+ if (format) gb_printf(" ");
+ print_query_data_as_json(kv.value, ff, indent+1);
+ if (i < v->value.count-1) {
+ gb_printf(",");
+ if (!ff && format) {
+ gb_printf(" ");
+ }
+ }
+ if (ff) gb_printf("\n");
+ }
+ qprintf(ff, indent, "}");
+ } else {
+ gb_printf("{}");
+ }
+ return;
+ }
+ }
+}