JSON parser
This commit is contained in:
parent
a02370ff68
commit
b1b4a0267a
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
#define RENDER() extern "C" void render()
|
||||
|
||||
string process_html_literal(SharedUnit* su, string content)
|
||||
string process_html_literal(Request* context, SharedUnit* su, string content)
|
||||
{
|
||||
string pc;
|
||||
string HT_START = "context->print(R\"(";
|
||||
@ -74,11 +74,11 @@ string process_html_literal(SharedUnit* su, string content)
|
||||
return(HT_START + pc + HT_END);
|
||||
}
|
||||
|
||||
string preprocess_shared_unit(SharedUnit* su)
|
||||
string preprocess_shared_unit(Request* context, SharedUnit* su)
|
||||
{
|
||||
string content = file_get_contents(su->file_name);
|
||||
printf("(c) compiling with root dir %s\n", context->server->config.COMPILER_SYS_PATH.c_str());
|
||||
string pc = ("#include \"")+context->server->config.COMPILER_SYS_PATH +"/src/lib/uce_gen.h\" \n";
|
||||
string pc = ("#include \"")+context->server->config.COMPILER_SYS_PATH +"/src/lib/unit.h\" \n";
|
||||
string token = "";
|
||||
string html_buffer = "";
|
||||
u8 mode = 0;
|
||||
@ -94,7 +94,7 @@ string preprocess_shared_unit(SharedUnit* su)
|
||||
u32 len = token.length() + 3 + end_pos - i;
|
||||
html_buffer.append(content.substr(i, len - (token.length() == 0 ? 3 : 0)));
|
||||
i += len - 1;
|
||||
pc.append(process_html_literal(su, html_buffer));
|
||||
pc.append(process_html_literal(context, su, html_buffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -137,7 +137,7 @@ string preprocess_shared_unit(SharedUnit* su)
|
||||
return(pc);
|
||||
}
|
||||
|
||||
void setup_unit_paths(SharedUnit* su, string file_name)
|
||||
void setup_unit_paths(Request* context, SharedUnit* su, string file_name)
|
||||
{
|
||||
su->file_name = file_name;
|
||||
|
||||
@ -155,9 +155,9 @@ void setup_unit_paths(SharedUnit* su, string file_name)
|
||||
su->so_name = su->bin_path + "/" + su->bin_file_name;
|
||||
}
|
||||
|
||||
void load_shared_unit(SharedUnit* su, string file_name)
|
||||
void load_shared_unit(Request* context, SharedUnit* su, string file_name)
|
||||
{
|
||||
setup_unit_paths(su, file_name);
|
||||
setup_unit_paths(context, su, file_name);
|
||||
|
||||
su->on_render = 0;
|
||||
su->on_setup = 0;
|
||||
@ -188,18 +188,18 @@ void load_shared_unit(SharedUnit* su, string file_name)
|
||||
}
|
||||
}
|
||||
|
||||
void compile_shared_unit(SharedUnit* su, string file_name)
|
||||
void compile_shared_unit(Request* context, SharedUnit* su, string file_name)
|
||||
{
|
||||
setup_unit_paths(su, file_name);
|
||||
setup_unit_paths(context, su, file_name);
|
||||
|
||||
if(!file_exists(su->file_name))
|
||||
{
|
||||
su->compiler_messages = "source file not found";
|
||||
su->compiler_messages = "source file not found (" + su->file_name + ")";
|
||||
return;
|
||||
}
|
||||
|
||||
shell_exec("mkdir -p " + shell_escape(su->pre_path));
|
||||
file_put_contents(su->pre_path + "/" + su->pre_file_name, preprocess_shared_unit(su));
|
||||
file_put_contents(su->pre_path + "/" + su->pre_file_name, preprocess_shared_unit(context, su));
|
||||
|
||||
printf("Config.COMPILE_SCRIPT %s\n", string(su->pre_path + "/" + su->pre_file_name).c_str());
|
||||
|
||||
@ -217,12 +217,12 @@ void compile_shared_unit(SharedUnit* su, string file_name)
|
||||
}
|
||||
else
|
||||
{
|
||||
load_shared_unit(su, file_name);
|
||||
load_shared_unit(context, su, file_name);
|
||||
printf("(i) compiled unit %s\n", file_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
SharedUnit* get_shared_unit(string file_name)
|
||||
SharedUnit* get_shared_unit(Request* context, string file_name)
|
||||
{
|
||||
SharedUnit* su = context->server->units[file_name];
|
||||
auto mod_time = file_mtime(file_name);
|
||||
@ -239,13 +239,13 @@ SharedUnit* get_shared_unit(string file_name)
|
||||
|
||||
if(do_recompile)
|
||||
{
|
||||
compile_shared_unit(su, file_name);
|
||||
compile_shared_unit(context, su, file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
load_shared_unit(su, file_name);
|
||||
load_shared_unit(context, su, file_name);
|
||||
if(!su->so_handle)
|
||||
compile_shared_unit(su, file_name);
|
||||
compile_shared_unit(context, su, file_name);
|
||||
}
|
||||
|
||||
context->server->units[file_name] = su;
|
||||
@ -253,15 +253,16 @@ SharedUnit* get_shared_unit(string file_name)
|
||||
return(su);
|
||||
}
|
||||
|
||||
void compiler_invoke(string file_name)
|
||||
void compiler_invoke(Request* context, string file_name)
|
||||
{
|
||||
printf("(i) invoke %s\n", file_name.c_str());
|
||||
if(file_name[0] != '/')
|
||||
{
|
||||
file_name = expand_path(file_name);
|
||||
}
|
||||
printf("(i) invoke %s\n", file_name.c_str());
|
||||
|
||||
//printf("(i) invoke(%s)\n", file_name.c_str());
|
||||
auto su = get_shared_unit(file_name);
|
||||
auto su = get_shared_unit(context, file_name);
|
||||
if(!su)
|
||||
{
|
||||
printf("Error loading unit %s\n", file_name.c_str());
|
||||
@ -286,4 +287,5 @@ void compiler_invoke(string file_name)
|
||||
}
|
||||
}
|
||||
|
||||
invoke_handler invoke;
|
||||
|
||||
|
||||
|
||||
@ -1,160 +0,0 @@
|
||||
string var_dump(StringMap map, string prefix = "", string postfix = "\n")
|
||||
{
|
||||
string result = "";
|
||||
|
||||
for (auto it = map.begin(); it != map.end(); ++it)
|
||||
{
|
||||
result.append(prefix + it->first + ": " + it->second + postfix);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
string var_dump(StringList map, string prefix = "", string postfix = "\n")
|
||||
{
|
||||
string result = "";
|
||||
|
||||
for (u32 i = 0; i < map.size(); i++)
|
||||
{
|
||||
result.append(prefix + map[i] + postfix);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
u8 char_to_u8(char input)
|
||||
{
|
||||
if(input >= '0' && input <= '9')
|
||||
return input - '0';
|
||||
if(input >= 'A' && input <= 'F')
|
||||
return input - 'A' + 10;
|
||||
if(input >= 'a' && input <= 'f')
|
||||
return input - 'a' + 10;
|
||||
return(0);
|
||||
}
|
||||
|
||||
u8 hex_to_u8(string src)
|
||||
{
|
||||
return(char_to_u8(src[0])*16 + char_to_u8(src[1]));
|
||||
}
|
||||
|
||||
template <typename ITYPE>
|
||||
string to_hex(ITYPE w, size_t hex_len = sizeof(ITYPE)<<1)
|
||||
{
|
||||
static const char* digits = "0123456789ABCDEF";
|
||||
string rc(hex_len,'0');
|
||||
for (size_t i=0, j=(hex_len-1)*4 ; i<hex_len; ++i,j-=4)
|
||||
rc[i] = digits[(w>>j) & 0x0f];
|
||||
return(rc);
|
||||
}
|
||||
|
||||
string trim(string raw)
|
||||
{
|
||||
u32 len = raw.length();
|
||||
u32 start_pos = 0;
|
||||
u32 end_pos = len - 1;
|
||||
if(len == 0 || (len == 1 && isspace(raw[0])))
|
||||
return("");
|
||||
while(start_pos < len && isspace(raw[start_pos]))
|
||||
start_pos++;
|
||||
while(end_pos >= 0 && isspace(raw[end_pos]))
|
||||
end_pos--;
|
||||
if(end_pos < start_pos)
|
||||
return("");
|
||||
return(raw.substr(start_pos, 1 + end_pos - start_pos));
|
||||
}
|
||||
|
||||
StringList explode(string str, string delim = "\n")
|
||||
{
|
||||
StringList result;
|
||||
int start = 0;
|
||||
int end = str.find(delim);
|
||||
while (end != string::npos)
|
||||
{
|
||||
result.push_back(str.substr(start, end - start));
|
||||
start = end + delim.size();
|
||||
end = str.find(delim, start);
|
||||
}
|
||||
result.push_back(str.substr(start, end - start));
|
||||
return(result);
|
||||
}
|
||||
|
||||
string implode(StringList l, string delim = "\n")
|
||||
{
|
||||
string result;
|
||||
for(u32 i = 0; i < l.size(); i++)
|
||||
{
|
||||
string s = l[i];
|
||||
if(i > 0)
|
||||
result.append(delim);
|
||||
result.append(s);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
string html_escape(string s)
|
||||
{
|
||||
string result;
|
||||
|
||||
for(u32 i = 0; i < s.length(); i++)
|
||||
{
|
||||
char c = s[i];
|
||||
switch(c)
|
||||
{
|
||||
case('&'):
|
||||
result.append("&");
|
||||
break;
|
||||
case('<'):
|
||||
result.append("<");
|
||||
break;
|
||||
case('>'):
|
||||
result.append(">");
|
||||
break;
|
||||
case('"'):
|
||||
result.append(""");
|
||||
break;
|
||||
default:
|
||||
result.append(1, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
string html_escape(u64 a)
|
||||
{
|
||||
return(std::to_string(a));
|
||||
}
|
||||
|
||||
string html_escape(f64 a)
|
||||
{
|
||||
return(std::to_string(a));
|
||||
}
|
||||
|
||||
u64 int_val(string s, u32 base = 10)
|
||||
{
|
||||
return(strtoll(s.c_str(), 0, base));
|
||||
}
|
||||
|
||||
string nibble(string div, string& haystack)
|
||||
{
|
||||
auto pos = haystack.find(div);
|
||||
if(pos == string::npos)
|
||||
{
|
||||
auto result = haystack;
|
||||
haystack.clear();
|
||||
return(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto result = haystack.substr(0, pos);
|
||||
haystack.erase(0, pos+div.length());
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
|
||||
string json_escape(string s)
|
||||
{
|
||||
return(string("\"")+s+"\"");
|
||||
}
|
||||
290
src/lib/dtree.h
290
src/lib/dtree.h
@ -1,5 +1,48 @@
|
||||
struct DTree;
|
||||
|
||||
string json_escape(string s)
|
||||
{
|
||||
//return(string("\"")+s+"\"");
|
||||
string result;
|
||||
u32 i = 0;
|
||||
result.append(1, '"');
|
||||
while(i < s.length())
|
||||
{
|
||||
char c = s[i];
|
||||
switch(c)
|
||||
{
|
||||
case('\t'):
|
||||
result.append("\\t");
|
||||
break;
|
||||
case('\n'):
|
||||
result.append("\\n");
|
||||
break;
|
||||
case('"'):
|
||||
result.append("\\\"");
|
||||
break;
|
||||
case('\r'):
|
||||
result.append("\\r");
|
||||
break;
|
||||
case('\\'):
|
||||
result.append("\\\\");
|
||||
break;
|
||||
case('\b'):
|
||||
result.append("\\b");
|
||||
break;
|
||||
case('\f'):
|
||||
result.append("\\f");
|
||||
break;
|
||||
default:
|
||||
result.append(1, c);
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
result.append(1, '"');
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
struct DTree {
|
||||
|
||||
char type = 'S';
|
||||
@ -42,13 +85,13 @@ struct DTree {
|
||||
return(std::to_string(_float));
|
||||
break;
|
||||
case('B'):
|
||||
return(_bool ? "true" : "false");
|
||||
return(_bool ? "(true)" : "(false)");
|
||||
break;
|
||||
case('M'):
|
||||
return("(array)");
|
||||
break;
|
||||
case('P'):
|
||||
return(to_hex((u64)_ptr));
|
||||
return(std::to_string((u64)_ptr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -125,6 +168,39 @@ struct DTree {
|
||||
_bool = b;
|
||||
}
|
||||
|
||||
void set(DTree source)
|
||||
{
|
||||
type = source.type;
|
||||
switch(type)
|
||||
{
|
||||
case('S'):
|
||||
_string = source._string;
|
||||
break;
|
||||
case('F'):
|
||||
_float = source._float;
|
||||
break;
|
||||
case('B'):
|
||||
_bool = source._bool;
|
||||
break;
|
||||
case('M'):
|
||||
_map = source._map;
|
||||
break;
|
||||
case('P'):
|
||||
_ptr = source._ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void set(StringMap source)
|
||||
{
|
||||
type = 'M';
|
||||
_map.clear();
|
||||
for (auto it = source.begin(); it != source.end(); ++it)
|
||||
{
|
||||
(*this)[it->first] = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
DTree* key(string s)
|
||||
{
|
||||
type = 'M';
|
||||
@ -139,7 +215,8 @@ struct DTree {
|
||||
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 operator = (DTree v) { set(v); }
|
||||
void operator = (StringMap v) { set(v); }
|
||||
|
||||
void remove(string s)
|
||||
{
|
||||
@ -160,213 +237,6 @@ 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(1, '\t');
|
||||
break;
|
||||
case('n'):
|
||||
result.append(1, '\n');
|
||||
break;
|
||||
case('r'):
|
||||
result.append(1, '\r');
|
||||
break;
|
||||
case('\\'):
|
||||
result.append(1, '\\');
|
||||
break;
|
||||
case('b'):
|
||||
result.append(1, '\b');
|
||||
break;
|
||||
case('f'):
|
||||
result.append(1, '\f');
|
||||
break;
|
||||
case('u'):
|
||||
// todo decode
|
||||
break;
|
||||
default:
|
||||
result.append(1, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.append(1, c);
|
||||
}
|
||||
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(1, c);
|
||||
}
|
||||
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(1, c);
|
||||
}
|
||||
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];
|
||||
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 = "";
|
||||
json_consume_space(s, i);
|
||||
while(i < s.length())
|
||||
{
|
||||
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);
|
||||
printf("%s\n", key.c_str());
|
||||
i += 1;
|
||||
json_consume_space(s, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
// malformed
|
||||
return(result);
|
||||
}
|
||||
i += 1;
|
||||
json_consume_space(s, i);
|
||||
}
|
||||
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 = "";
|
||||
|
||||
345
src/lib/functionlib.h
Normal file
345
src/lib/functionlib.h
Normal file
@ -0,0 +1,345 @@
|
||||
string var_dump(StringMap map, string prefix = "", string postfix = "\n")
|
||||
{
|
||||
string result = "";
|
||||
|
||||
for (auto it = map.begin(); it != map.end(); ++it)
|
||||
{
|
||||
result.append(prefix + it->first + ": " + it->second + postfix);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
string var_dump(StringList slist, string prefix = "", string postfix = "\n")
|
||||
{
|
||||
string result = "";
|
||||
|
||||
for (auto& s : slist)
|
||||
{
|
||||
result.append(prefix + s + postfix);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
u8 char_to_u8(char input)
|
||||
{
|
||||
if(input >= '0' && input <= '9')
|
||||
return input - '0';
|
||||
if(input >= 'A' && input <= 'F')
|
||||
return input - 'A' + 10;
|
||||
if(input >= 'a' && input <= 'f')
|
||||
return input - 'a' + 10;
|
||||
return(0);
|
||||
}
|
||||
|
||||
u8 hex_to_u8(string src)
|
||||
{
|
||||
return(char_to_u8(src[0])*16 + char_to_u8(src[1]));
|
||||
}
|
||||
|
||||
string trim(string raw)
|
||||
{
|
||||
u32 len = raw.length();
|
||||
u32 start_pos = 0;
|
||||
u32 end_pos = len - 1;
|
||||
if(len == 0 || (len == 1 && isspace(raw[0])))
|
||||
return("");
|
||||
while(start_pos < len && isspace(raw[start_pos]))
|
||||
start_pos++;
|
||||
while(end_pos >= 0 && isspace(raw[end_pos]))
|
||||
end_pos--;
|
||||
if(end_pos < start_pos)
|
||||
return("");
|
||||
return(raw.substr(start_pos, 1 + end_pos - start_pos));
|
||||
}
|
||||
|
||||
StringList split(string str, string delim = "\n")
|
||||
{
|
||||
StringList result;
|
||||
int start = 0;
|
||||
int end = str.find(delim);
|
||||
while (end != string::npos)
|
||||
{
|
||||
result.push_back(str.substr(start, end - start));
|
||||
start = end + delim.size();
|
||||
end = str.find(delim, start);
|
||||
}
|
||||
result.push_back(str.substr(start, end - start));
|
||||
return(result);
|
||||
}
|
||||
|
||||
string join(StringList l, string delim = "\n")
|
||||
{
|
||||
string result;
|
||||
u32 i = 0;
|
||||
for(auto& s : l)
|
||||
{
|
||||
if(i > 0)
|
||||
result.append(delim);
|
||||
result.append(s);
|
||||
i += 1;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
string html_escape(string s)
|
||||
{
|
||||
string result;
|
||||
|
||||
for(u32 i = 0; i < s.length(); i++)
|
||||
{
|
||||
char c = s[i];
|
||||
switch(c)
|
||||
{
|
||||
case('&'):
|
||||
result.append("&");
|
||||
break;
|
||||
case('<'):
|
||||
result.append("<");
|
||||
break;
|
||||
case('>'):
|
||||
result.append(">");
|
||||
break;
|
||||
case('"'):
|
||||
result.append(""");
|
||||
break;
|
||||
default:
|
||||
result.append(1, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
string html_escape(u64 a)
|
||||
{
|
||||
return(std::to_string(a));
|
||||
}
|
||||
|
||||
string html_escape(f64 a)
|
||||
{
|
||||
return(std::to_string(a));
|
||||
}
|
||||
|
||||
u64 int_val(string s, u32 base = 10)
|
||||
{
|
||||
return(strtoll(s.c_str(), 0, base));
|
||||
}
|
||||
|
||||
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, char termination_char = '"')
|
||||
{
|
||||
string result;
|
||||
//echo("json_decode_string " + s.substr(i) + "\n");
|
||||
while(i < s.length())
|
||||
{
|
||||
char c = s[i];
|
||||
if(c == termination_char)
|
||||
{
|
||||
i += 1;
|
||||
//echo("json_decode_string = " + result + "\n");
|
||||
return(result);
|
||||
}
|
||||
else if(c == '\\')
|
||||
{
|
||||
i += 1;
|
||||
c = s[i];
|
||||
switch(c)
|
||||
{
|
||||
case('t'):
|
||||
result.append(1, '\t');
|
||||
break;
|
||||
case('n'):
|
||||
result.append(1, '\n');
|
||||
break;
|
||||
case('r'):
|
||||
result.append(1, '\r');
|
||||
break;
|
||||
case('\\'):
|
||||
result.append(1, '\\');
|
||||
break;
|
||||
case('b'):
|
||||
result.append(1, '\b');
|
||||
break;
|
||||
case('f'):
|
||||
result.append(1, '\f');
|
||||
break;
|
||||
case('u'):
|
||||
// todo decode
|
||||
break;
|
||||
default:
|
||||
result.append(1, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.append(1, c);
|
||||
}
|
||||
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(1, c);
|
||||
}
|
||||
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(1, c);
|
||||
}
|
||||
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];
|
||||
//echo("json_decode_value " + s.substr(i) + "\n");
|
||||
if(c == '"' || c == '\'') // string value
|
||||
{
|
||||
result.type = 'S';
|
||||
i += 1;
|
||||
result._string = json_decode_string(s, i, s[i-1]);
|
||||
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;
|
||||
result.type = 'M';
|
||||
string key = "";
|
||||
json_consume_space(s, i);
|
||||
//echo("json_decode_map " + s.substr(i) + "\n");
|
||||
while(i < s.length())
|
||||
{
|
||||
char c = s[i];
|
||||
if(c == '}')
|
||||
{
|
||||
i += 1;
|
||||
return(result);
|
||||
}
|
||||
else if(c == ',')
|
||||
{
|
||||
i += 1;
|
||||
}
|
||||
else if(c == '"' || c == '\'')
|
||||
{
|
||||
i += 1;
|
||||
key = json_decode_string(s, i, s[i-1]);
|
||||
json_consume_space(s, i);
|
||||
if(s[i] != ':')
|
||||
return(result); // malformed
|
||||
i += 1;
|
||||
DTree v = json_decode_value(s, i);
|
||||
//result._map[key] = json_decode_value(s, i);
|
||||
//echo("KV " + key + " = " + to_string(v) + "\n");
|
||||
//printf("map add %s (%c) \n", key.c_str(), s[i]);
|
||||
result._map[key] = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
// malformed
|
||||
return(result);
|
||||
}
|
||||
json_consume_space(s, i);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
DTree json_decode(string s)
|
||||
{
|
||||
u32 i = 0;
|
||||
return(json_decode_value(s, i));
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
string shell_exec(string cmd)
|
||||
{
|
||||
printf("(i) shell_exec(%s)\n", cmd.c_str());
|
||||
@ -59,9 +62,9 @@ string basename(string fn)
|
||||
string dirname(string fn)
|
||||
{
|
||||
string result;
|
||||
auto seg = explode(fn, "/");
|
||||
auto seg = split(fn, "/");
|
||||
seg.pop_back();
|
||||
result = implode(seg, "/");
|
||||
result = join(seg, "/");
|
||||
//printf("dirname(%s) %s seg#%i\n", fn.c_str(), result.c_str(), seg.size());
|
||||
return(result);
|
||||
}
|
||||
@ -140,13 +143,27 @@ void unlink(string file_name)
|
||||
string expand_path(string path)
|
||||
{
|
||||
string result;
|
||||
char buf[PATH_MAX];
|
||||
char *res = realpath(path.c_str(), buf);
|
||||
if(res)
|
||||
|
||||
auto base_path = split(get_cwd(), "/");
|
||||
auto rel_path = split(path, "/");
|
||||
|
||||
for(auto& s : rel_path)
|
||||
{
|
||||
result.append(res);
|
||||
if(s == "..")
|
||||
{
|
||||
base_path.pop_back();
|
||||
}
|
||||
else if(s == ".")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
base_path.push_back(s);
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
|
||||
return(join(base_path, "/"));
|
||||
}
|
||||
|
||||
#include <execinfo.h>
|
||||
@ -165,3 +182,44 @@ void on_segfault(int sig) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
f64 microtime()
|
||||
{
|
||||
return ((f64)std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::high_resolution_clock::now().time_since_epoch()).count()) / 1000000;
|
||||
}
|
||||
|
||||
u64 time()
|
||||
{
|
||||
return(std::time(0));
|
||||
}
|
||||
|
||||
string date(string format = "", u64 timestamp = 0)
|
||||
{
|
||||
string ts;
|
||||
string fmt;
|
||||
if(timestamp > 0)
|
||||
ts = string("-d '@")+std::to_string(timestamp)+"'";
|
||||
if(format != "")
|
||||
fmt = string("+'"+format+"'");
|
||||
return(trim(shell_exec("date "+ts+" "+fmt)));
|
||||
}
|
||||
|
||||
string gmdate(string format = "", u64 timestamp = 0)
|
||||
{
|
||||
string ts;
|
||||
string fmt;
|
||||
if(timestamp > 0)
|
||||
ts = string("-d '@")+std::to_string(timestamp)+"'";
|
||||
if(format == "RFC1123")
|
||||
format = "%a, %d %b %Y %T GMT";
|
||||
if(format != "")
|
||||
fmt = string("+'"+format+"'");
|
||||
return(trim(shell_exec("date -u "+ts+" "+fmt)));
|
||||
}
|
||||
|
||||
u64 parse_time(string time_string)
|
||||
{
|
||||
return(int_val(trim(shell_exec("date -u -d '"+time_string+"' +'%s'"))));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
f64 microtime()
|
||||
{
|
||||
return ((f64)std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::high_resolution_clock::now().time_since_epoch()).count()) / 1000000;
|
||||
}
|
||||
|
||||
u64 time()
|
||||
{
|
||||
return(std::time(0));
|
||||
}
|
||||
|
||||
string date(string format = "", u64 timestamp = 0)
|
||||
{
|
||||
string ts;
|
||||
string fmt;
|
||||
if(timestamp > 0)
|
||||
ts = string("-d '@")+std::to_string(timestamp)+"'";
|
||||
if(format != "")
|
||||
fmt = string("+'"+format+"'");
|
||||
return(trim(shell_exec("date "+ts+" "+fmt)));
|
||||
}
|
||||
|
||||
string gmdate(string format = "", u64 timestamp = 0)
|
||||
{
|
||||
string ts;
|
||||
string fmt;
|
||||
if(timestamp > 0)
|
||||
ts = string("-d '@")+std::to_string(timestamp)+"'";
|
||||
if(format == "RFC1123")
|
||||
format = "%a, %d %b %Y %T GMT";
|
||||
if(format != "")
|
||||
fmt = string("+'"+format+"'");
|
||||
return(trim(shell_exec("date -u "+ts+" "+fmt)));
|
||||
}
|
||||
|
||||
u64 parse_time(string time_string)
|
||||
{
|
||||
return(int_val(trim(shell_exec("date -u -d '"+time_string+"' +'%s'"))));
|
||||
}
|
||||
@ -3,6 +3,7 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <filesystem>
|
||||
#include <ctype.h>
|
||||
#include <fstream>
|
||||
@ -36,7 +37,7 @@ typedef long long s64;
|
||||
#define echo(s) context->print(s)
|
||||
|
||||
typedef std::map<string, string> StringMap;
|
||||
typedef std::vector<string> StringList;
|
||||
typedef std::list<string> StringList;
|
||||
|
||||
typedef void (*invoke_handler)(string file_name);
|
||||
|
||||
@ -104,7 +105,45 @@ struct ServerState {
|
||||
std::map<string, SharedUnit*> units;
|
||||
ServerSettings config;
|
||||
|
||||
} server_state;
|
||||
};
|
||||
|
||||
void compiler_invoke(Request* context, string file_name);
|
||||
|
||||
struct URI {
|
||||
|
||||
StringMap query;
|
||||
StringMap parts;
|
||||
|
||||
};
|
||||
|
||||
string nibble(string div, string& haystack)
|
||||
{
|
||||
auto pos = haystack.find(div);
|
||||
if(pos == string::npos)
|
||||
{
|
||||
auto result = haystack;
|
||||
haystack.clear();
|
||||
return(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto result = haystack.substr(0, pos);
|
||||
haystack.erase(0, pos+div.length());
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ITYPE>
|
||||
string to_hex(ITYPE w, size_t hex_len = sizeof(ITYPE)<<1)
|
||||
{
|
||||
static const char* digits = "0123456789ABCDEF";
|
||||
string rc(hex_len,'0');
|
||||
for (size_t i=0, j=(hex_len-1)*4 ; i<hex_len; ++i,j-=4)
|
||||
rc[i] = digits[(w>>j) & 0x0f];
|
||||
return(rc);
|
||||
}
|
||||
|
||||
#include "dtree.h"
|
||||
|
||||
struct Request {
|
||||
|
||||
@ -115,6 +154,9 @@ struct Request {
|
||||
StringMap post;
|
||||
StringMap cookies;
|
||||
StringMap session;
|
||||
|
||||
DTree var;
|
||||
|
||||
string session_id = "";
|
||||
string session_name = "";
|
||||
std::vector<UploadedFile> uploaded_files;
|
||||
@ -130,7 +172,10 @@ struct Request {
|
||||
f64 time_start;
|
||||
f64 time_end;
|
||||
|
||||
invoke_handler invoke;
|
||||
void invoke(string file_name)
|
||||
{
|
||||
compiler_invoke(this, file_name);
|
||||
}
|
||||
|
||||
void print(string s)
|
||||
{
|
||||
@ -139,11 +184,6 @@ struct Request {
|
||||
|
||||
};
|
||||
|
||||
struct URI {
|
||||
|
||||
StringMap query;
|
||||
StringMap parts;
|
||||
|
||||
};
|
||||
|
||||
typedef Request FastCGIRequest;
|
||||
|
||||
Request* context;
|
||||
|
||||
@ -1,20 +1,7 @@
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "datastructures.h"
|
||||
#include "dtree.h"
|
||||
#include "functionlib.h"
|
||||
#include "sys.h"
|
||||
#include "time.h"
|
||||
|
||||
Request* context;
|
||||
|
||||
#include "uri.h"
|
||||
#include "compiler.h"
|
||||
|
||||
extern "C" void set_current_request(Request* _request)
|
||||
{
|
||||
context = _request;
|
||||
invoke = _request->invoke;
|
||||
signal(SIGSEGV, on_segfault);
|
||||
}
|
||||
|
||||
|
||||
8
src/lib/unit.h
Normal file
8
src/lib/unit.h
Normal file
@ -0,0 +1,8 @@
|
||||
#include "uce_gen.h"
|
||||
|
||||
extern "C" void set_current_request(Request* _request)
|
||||
{
|
||||
context = _request;
|
||||
signal(SIGSEGV, on_segfault);
|
||||
}
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
|
||||
#include "fastcgi/src/fcgicc.cc"
|
||||
|
||||
FastCGIServer server;
|
||||
ServerState server_state;
|
||||
|
||||
int handle_request(FastCGIRequest& request) {
|
||||
// This is always the first event to occur. It occurs when the
|
||||
// server receives all parameters. There may be more data coming on the
|
||||
@ -39,7 +42,6 @@ int handle_complete(FastCGIRequest& request) {
|
||||
context = &request;
|
||||
request.server = &server_state;
|
||||
request.time_start = microtime();
|
||||
request.invoke = compiler_invoke;
|
||||
request.header["Content-Type"] = context->server->config.CONTENT_TYPE;
|
||||
request.get = parse_query(request.params["QUERY_STRING"]);
|
||||
|
||||
@ -63,7 +65,7 @@ int handle_complete(FastCGIRequest& request) {
|
||||
}
|
||||
|
||||
// printf("(i) request ready\n");
|
||||
invoke(request.params["SCRIPT_FILENAME"]);
|
||||
request.invoke(request.params["SCRIPT_FILENAME"]);
|
||||
|
||||
string headers =
|
||||
var_dump(request.header, "", "\r\n") +
|
||||
@ -88,15 +90,11 @@ int handle_complete(FastCGIRequest& request) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
FastCGIServer server;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
signal(SIGSEGV, on_segfault);
|
||||
srand(time());
|
||||
|
||||
invoke = compiler_invoke;
|
||||
|
||||
// Set up our request handlers
|
||||
server.request_handler(&handle_request);
|
||||
server.data_handler(&handle_data);
|
||||
@ -106,7 +104,7 @@ int main(int argc, char** argv)
|
||||
server_state.config.COMPILER_SYS_PATH = get_cwd();
|
||||
|
||||
printf("Compiler base path: %s\n", server_state.config.COMPILER_SYS_PATH.c_str());
|
||||
|
||||
|
||||
server_state.config.BIN_DIRECTORY =
|
||||
server_state.config.COMPILER_SYS_PATH + "/" + server_state.config.BIN_DIRECTORY;
|
||||
server_state.config.COMPILE_SCRIPT =
|
||||
|
||||
@ -17,7 +17,8 @@ RENDER()
|
||||
|
||||
t.key("a")->set("valueA");
|
||||
t.key("b")->set("valueB");
|
||||
t.key("c")->key("c-d")->set("valueCD");
|
||||
t.key("c")->key("c-dt")->set_bool(true);
|
||||
t.key("c")->key("c-df")->set_bool(false);
|
||||
t.key("c")->key("c-e")->set("valueCE");
|
||||
t.key("c")->key("c-f")->set(&t);
|
||||
t.key("g")->key("g-h")->key("h-i")->set("valueHI");
|
||||
@ -25,6 +26,7 @@ RENDER()
|
||||
t["g"]["x"]["y2"] = &t;
|
||||
t["g"]["x"]["y3"] = time();
|
||||
t["g"]["x"]["y4"] = "Ünicödä";
|
||||
t["l"] = context->params;
|
||||
|
||||
string j;
|
||||
echo(j = json_encode(t));
|
||||
@ -34,7 +36,17 @@ RENDER()
|
||||
Parsed:
|
||||
|
||||
<pre><?
|
||||
echo(var_dump(json_decode("{\"abc\": \"valueA\"}")));
|
||||
echo(var_dump(
|
||||
json_decode(j)
|
||||
));
|
||||
?></pre>
|
||||
|
||||
Compare:
|
||||
|
||||
<pre><?
|
||||
echo(var_dump(
|
||||
t
|
||||
));
|
||||
?></pre>
|
||||
|
||||
Params
|
||||
|
||||
@ -11,9 +11,10 @@ RENDER()
|
||||
</h1>
|
||||
<pre><?
|
||||
echo("Base WD: " + get_cwd() + "\n");
|
||||
invoke("/Code/uce.openfu.com/uce/test/test2/working-dir-test.uce");
|
||||
context->invoke("test2/working-dir-test.uce");
|
||||
?></pre>
|
||||
<pre><?= var_dump(context->params) ?></pre>
|
||||
</>
|
||||
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user