Files
Odin/src/query_data.cpp
gingerBill 458ec5922e odin query
Output .json file containing information about the program
2019-05-25 20:24:19 +01:00

362 lines
8.0 KiB
C++

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;
}
}
}