diff options
Diffstat (limited to 'src/query_data.cpp')
| -rw-r--r-- | src/query_data.cpp | 361 |
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; + } + } +} |