uce/src/lib/dtree.h
2021-11-15 09:17:54 +00:00

381 lines
5.5 KiB
C++

struct DTree;
struct DTree {
char type = 'S';
string _string;
f64 _float;
bool _bool;
void* _ptr;
std::map<string, DTree> _map;
void each(std::function <void (DTree t, string key)> f)
{
switch(type)
{
case('M'):
for (auto it = _map.begin(); it != _map.end(); ++it)
{
f(it->second, it->first);
}
break;
default:
f(*this, "");
break;
}
}
bool is_array()
{
return(type == 'M');
}
string to_string()
{
switch(type)
{
case('S'):
return(_string);
break;
case('F'):
return(std::to_string(_float));
break;
case('B'):
return(_bool ? "true" : "false");
break;
case('M'):
return("(array)");
break;
case('P'):
return(to_hex((u64)_ptr));
break;
}
}
string to_json()
{
switch(type)
{
case('S'):
return(json_escape(_string));
break;
case('F'):
return(std::to_string(_float));
break;
case('B'):
return(_bool ? "true" : "false");
break;
case('M'):
return("\"(array)\"");
break;
case('P'):
return("\"(pointer)\"");
break;
}
}
string get_type_name()
{
switch(type)
{
case('S'):
return("string");
break;
case('F'):
return("f64");
break;
case('B'):
return("bool");
break;
case('M'):
return("array");
break;
case('P'):
return("pointer");
break;
}
}
void set(string s)
{
if(type == 'M') _map.clear();
type = 'S';
_string = s;
}
void set(void* p)
{
if(type == 'M') _map.clear();
type = 'P';
_ptr = p;
}
void set(f64 f)
{
if(type == 'M') _map.clear();
type = 'F';
_float = f;
}
void set_bool(bool b)
{
if(type == 'M') _map.clear();
type = 'B';
_bool = b;
}
DTree* key(string s)
{
type = 'M';
return(&_map[s]);
}
DTree& operator [] (string s) {
type = 'M';
return(_map[s]);
}
void operator = (string v) { set(v); }
void operator = (f64 v) { set(v); }
void operator = (void* v) { set(v); }
void operator = (DTree v) { *this = v; }
void remove(string s)
{
type = 'M';
_map.erase(s);
}
void clear()
{
type = 'M';
_map.clear();
}
};
string to_string(DTree t)
{
return(t.to_string());
}
string json_encode(DTree t)
{
string result = "";
if(t.is_array())
{
result += "{";
u32 count = 0;
t.each([&] (DTree item, string key) {
if(count > 0)
result += ", ";
count += 1;
result += json_escape(key) + ": " + json_encode(item);
});
result += "}";
}
else
{
result = t.to_json();
}
return(result);
}
// https://i.stack.imgur.com/SHLOB.gif
string json_decode_string(string s, u32& i)
{
string result;
while(i < s.length())
{
char c = s[i];
if(c == '"')
{
i += 1;
return(result);
}
else if(c == '\\')
{
i += 1;
c = s[i];
switch(c)
{
case('t'):
result.append('\t', 1);
break;
case('n'):
result.append('\n', 1);
break;
case('r'):
result.append('\r', 1);
break;
case('\\'):
result.append('\\', 1);
break;
case('b'):
result.append('\b', 1);
break;
case('f'):
result.append('\f', 1);
break;
case('u'):
// todo decode
break;
default:
result.append(c, 1);
break;
}
}
else
{
result.append(c, 1);
}
i += 1;
}
return(result);
}
DTree json_decode_map(string s, u32& i);
void json_consume_space(string s, u32& i)
{
while(i < s.length() && isspace(s[i]))
i += 1;
}
string json_decode_keyword(string s, u32& i)
{
string result;
json_consume_space(s, i);
while(i < s.length())
{
char c = s[i];
if(isalnum(c))
{
result.append(c, 1);
}
else
{
return(result);
}
i += 1;
}
return(result);
}
string json_decode_number(string s, u32& i)
{
string result;
json_consume_space(s, i);
while(i < s.length())
{
char c = s[i];
if(isdigit(c) || c == '.')
{
result.append(c, 1);
}
else
{
return(result);
}
i += 1;
}
return(result);
}
DTree json_decode_value(string s, u32& i)
{
DTree result;
string value = "";
json_consume_space(s, i);
char c = s[i];
result.set("CHAR_");
result._string.append(to_string(c));
return(result);
if(c == '"') // string value
{
result.type = 'S';
i += 1;
result._string = json_decode_string(s, i);
return(result);
}
else if(isdigit(c))
{
result.type = 'S';
result._string = json_decode_number(s, i);
//result._float = stod(json_decode_number(s, i));
return(result);
}
else if(c == '{')
{
i += 1;
return(json_decode_map(s, i));
}
else
{
value = json_decode_keyword(s, i);
if(value == "true")
result.set_bool(true);
else if(value == "false")
result.set_bool(false);
else if(value == "null")
result.set("");
return(result);
}
return(result);
}
DTree json_decode_map(string s, u32& i)
{
DTree result;
string key = "";
while(i < s.length())
{
json_consume_space(s, i);
char c = s[i];
if(c == '}')
{
return(result);
}
else if(c == ',')
{
}
else if(c == '"')
{
i += 1;
key = json_decode_string(s, i);
json_consume_space(s, i);
if(s[i] != ':')
return(result); // malformed
result[key] = json_decode_value(s, i);
}
else
{
// malformed
return(result);
}
i += 1;
}
return(result);
}
DTree json_decode(string s)
{
u32 i = 0;
return(json_decode_value(s, i));
}
string var_dump(DTree map, string prefix = "", string postfix = "\n")
{
string result = "";
if(!map.is_array())
return(map.to_string());
map.each([&] (DTree item, string key) {
result += prefix + key + ": " + item.to_string() + postfix;
if(item.is_array())
result += var_dump(item, prefix + "\t");
});
return(result);
}