trying to port web app starter from PHP

This commit is contained in:
udo
2026-04-19 09:38:23 +00:00
parent 46d98a092f
commit be514d63d6
546 changed files with 76910 additions and 2807 deletions
+324 -53
View File
@@ -12,25 +12,36 @@ String process_text_literal(Request* context, SharedUnit* su, String content)
bool inside_quote = false;
String code_buffer = "";
bool is_field = false;
bool escape_field = false;
for(u32 i = 0; i < content.length(); i++)
{
char c = content[i];
char c1 = (i + 1 < content.length()) ? content[i + 1] : '\0';
char c2 = (i + 2 < content.length()) ? content[i + 2] : '\0';
switch(mode)
{
case(0):
if(c == '<' && content[i+1] == '?')
if(c == '<' && c1 == '?')
{
code_buffer = "";
if(content[i+2] == '=')
if(c2 == '=')
{
is_field = true;
escape_field = true;
i += 2;
}
else if(c2 == ':')
{
is_field = true;
escape_field = false;
i += 2;
}
else
{
is_field = false;
escape_field = false;
i += 1;
}
mode = 1; // code-parsing mode
@@ -43,7 +54,7 @@ String process_text_literal(Request* context, SharedUnit* su, String content)
case(1):
if(inside_quote)
{
if(quote_char == c && content[i-1] != '\\')
if(quote_char == c && (i == 0 || content[i-1] != '\\'))
inside_quote = false;
code_buffer.append(1, c);
}
@@ -55,19 +66,32 @@ String process_text_literal(Request* context, SharedUnit* su, String content)
quote_char = c;
code_buffer.append(1, c);
}
else if(c == '?' && content[i+1] == '>')
else if(c == '?' && c1 == '>')
{
mode = 0;
i += 1;
if(is_field)
{
pc.append(
HT_END +
"print(html_escape( " +
code_buffer +
" )); " +
HT_START
);
if(escape_field)
{
pc.append(
HT_END +
"print(html_escape( " +
code_buffer +
" )); " +
HT_START
);
}
else
{
pc.append(
HT_END +
"print( " +
code_buffer +
" ); " +
HT_START
);
}
}
else
{
@@ -87,6 +111,57 @@ String process_text_literal(Request* context, SharedUnit* su, String content)
return(HT_START + pc + HT_END);
}
String preprocess_named_render_syntax(String content)
{
String result = "";
String current_line = "";
auto flush_line = [&]() {
if(current_line.length() == 0)
return;
String line = current_line;
String line_break = "";
if(line.length() > 0 && line.back() == '\n')
{
line_break = "\n";
line.pop_back();
}
u32 indent_length = 0;
while(indent_length < line.length() && isspace(line[indent_length]))
indent_length += 1;
String indent = line.substr(0, indent_length);
String trimmed = trim(line);
if(trimmed.rfind("RENDER:", 0) == 0)
{
String signature = trimmed.substr(7);
auto open_paren_pos = signature.find("(");
if(open_paren_pos != String::npos)
{
String render_name = trim(signature.substr(0, open_paren_pos));
String render_signature = signature.substr(open_paren_pos);
if(render_name != "")
line = indent + "EXPORT void render_" + safe_name(render_name) + render_signature;
}
}
result += line + line_break;
current_line = "";
};
for(auto c : content)
{
current_line.append(1, c);
if(c == '\n')
flush_line();
}
flush_line();
return(result);
}
String preprocess_shared_unit_char_wise(Request* context, SharedUnit* su, String content)
{
String pc =
@@ -104,10 +179,12 @@ String preprocess_shared_unit_char_wise(Request* context, SharedUnit* su, String
for(u32 i = 0; i < source_length; i++)
{
char c = content[i];
char c1 = (i + 1 < source_length) ? content[i + 1] : '\0';
char c2 = (i + 2 < source_length) ? content[i + 2] : '\0';
current_line.append(1, c);
if(mode == 1)
{
if(c == '<' && (content[i+1] == '/') && (content[i+2] == '>'))
if(c == '<' && c1 == '/' && c2 == '>')
{
i += 2;
pc.append(process_text_literal(context, su, html_buffer));
@@ -119,7 +196,7 @@ String preprocess_shared_unit_char_wise(Request* context, SharedUnit* su, String
html_buffer.append(1, c);
}
}
else if(!inside_quote && c == '<' && (content[i+1] == '>'))
else if(!inside_quote && c == '<' && c1 == '>')
{
mode = 1;
token = "";
@@ -147,16 +224,20 @@ String preprocess_shared_unit_char_wise(Request* context, SharedUnit* su, String
pc.append("#include \"" + sub_su->bin_path + "/" + sub_su->pre_file_name + "\"\n");
}
}
else if(current_line.substr(0, 6) == "EXPORT" && isspace(current_line[6]))
else
{
current_line = "";
auto end_declaration_pos = content.find("{", i);
if(end_declaration_pos != std::string::npos)
String trimmed_line = trim(current_line);
if(c == 10 && trimmed_line.length() > 7 && trimmed_line.substr(0, 6) == "EXPORT" && isspace(trimmed_line[6]))
{
pc.append(1, '\n');
String declaration = trim(content.substr(i, end_declaration_pos - i));
su->api_declarations.push_back(declaration+";\n");
//printf("declaration found: %s\n", declaration.c_str());
current_line = "";
auto end_declaration_pos = content.find("{", i);
if(end_declaration_pos != std::string::npos)
{
pc.append(1, '\n');
String declaration = trim(content.substr(i, end_declaration_pos - i));
su->api_declarations.push_back(declaration+";\n");
//printf("declaration found: %s\n", declaration.c_str());
}
}
}
}
@@ -168,11 +249,13 @@ String preprocess_shared_unit_char_wise(Request* context, SharedUnit* su, String
String preprocess_shared_unit(Request* context, SharedUnit* su)
{
String content = file_get_contents(su->file_name);
content = preprocess_named_render_syntax(content);
return(
preprocess_shared_unit_char_wise(
context,
su,
file_get_contents(su->file_name)
content
)
);
}
@@ -223,9 +306,9 @@ void load_shared_unit(Request* context, SharedUnit* su, String file_name)
su->on_setup = (request_handler)dlsym(su->so_handle, "set_current_request");
if ((error = dlerror()) != NULL)
printf("Error - %s in %s\n", error, su->file_name.c_str());
su->on_render = (call_handler)dlsym(su->so_handle, "render");
su->on_render = (request_ref_handler)dlsym(su->so_handle, "render");
dlerror();
su->on_websocket = (call_handler)dlsym(su->so_handle, "websocket");
su->on_websocket = (request_ref_handler)dlsym(su->so_handle, "websocket");
dlerror();
su->api_declarations = split(file_get_contents(su->api_file_name), "\n");
//else
@@ -291,6 +374,11 @@ SharedUnit* get_shared_unit(Request* context, String file_name, bool opt_so_opti
{
SharedUnit* su = context->server->units[file_name];
auto mod_time = file_mtime(file_name);
auto setup_template_time = file_mtime(
context->server->config["COMPILER_SYS_PATH"] + "/" +
context->server->config["SETUP_TEMPLATE"]);
if(setup_template_time > mod_time)
mod_time = setup_template_time;
auto compiled_time = su ? file_mtime(su->so_name) : 0;
bool do_recompile = false;
if(su && (compiled_time < mod_time || mod_time == 0))
@@ -378,36 +466,141 @@ SharedUnit* compiler_load_shared_unit(Request* context, String file_name, String
}
void compiler_invoke(Request* context, String file_name, DTree& call_param)
String component_normalize_path(String name)
{
name = trim(name);
if(name.length() >= 4 && name.substr(name.length() - 4) == ".uce")
return(name);
return(name + ".uce");
}
void component_parse_target(String target, String& file_name, String& render_name)
{
target = trim(target);
render_name = "render";
auto render_split_pos = target.find(":");
if(render_split_pos != String::npos)
{
render_name = trim(target.substr(render_split_pos + 1));
target = trim(target.substr(0, render_split_pos));
if(render_name == "")
render_name = "render";
}
file_name = target;
}
String component_resolve_path(String name)
{
String file_name;
String render_name;
component_parse_target(name, file_name, render_name);
if(file_name == "")
return("");
StringList candidates;
auto push_candidate = [&] (String candidate) {
if(candidate == "")
return;
candidates.push_back(candidate);
};
push_candidate(file_name);
push_candidate(component_normalize_path(file_name));
if(file_name.rfind("components/", 0) != 0)
{
push_candidate("components/" + file_name);
push_candidate(component_normalize_path("components/" + file_name));
}
std::map<String, bool> seen;
for(auto& candidate : candidates)
{
if(seen[candidate])
continue;
seen[candidate] = true;
String resolved = candidate;
if(resolved[0] != '/')
resolved = expand_path(resolved, get_cwd());
if(file_exists(resolved))
return(resolved);
}
return("");
}
String render_handler_symbol(String render_name)
{
render_name = trim(render_name);
if(render_name == "" || render_name == "render")
return("render");
return("render_" + safe_name(render_name));
}
request_ref_handler get_render_handler(SharedUnit* su, String render_name)
{
String symbol = render_handler_symbol(render_name);
if(symbol == "render")
return(su->on_render);
auto it = su->api_functions.find(symbol);
if(it != su->api_functions.end())
return((request_ref_handler)it->second);
auto handler = (request_ref_handler)dlsym(su->so_handle, symbol.c_str());
dlerror();
su->api_functions[symbol] = (void*)handler;
return(handler);
}
bool compiler_invoke_render(Request* context, String file_name, String render_name, String* error_out = 0)
{
auto su = compiler_load_shared_unit(context, file_name, "", false);
if(!su)
return(false);
if(!su->on_setup)
{
if(error_out)
*error_out = "internal error: set_current_request() not defined in " + file_name;
return(false);
}
auto handler = get_render_handler(su, render_name);
if(!handler)
{
if(error_out)
{
if(trim(render_name) == "" || trim(render_name) == "render")
*error_out = "no RENDER() entry point";
else
*error_out = "no RENDER:" + render_name + "() entry point";
}
return(false);
}
String prev_wd = get_cwd();
set_cwd(su->src_path);
su->on_setup(context);
handler(*context);
set_cwd(prev_wd);
return(true);
}
void compiler_invoke(Request* context, String file_name)
{
printf("(i) compiler_invoke file %s\n", file_name.c_str());
auto su = compiler_load_shared_unit(context, file_name, "", false);
if(su)
String error_message = "";
if(!compiler_invoke_render(context, file_name, "render", &error_message) && error_message != "")
{
if(!su->on_setup)
{
if(context->stats.invoke_count == 1)
context->header["Content-Type"] = "text/plain";
print("internal error: set_current_request() not defined in", file_name, "\n");
}
else if(!su->on_render)
{
if(context->stats.invoke_count == 1)
context->header["Content-Type"] = "text/plain";
print("no RENDER() entry point");
}
else
{
String prev_wd = get_cwd();
set_cwd(su->src_path);
su->on_setup(context);
su->on_render(call_param);
set_cwd(prev_wd);
}
if(context->stats.invoke_count == 1)
context->header["Content-Type"] = "text/plain";
print(error_message);
}
}
void compiler_invoke_websocket(Request* context, String file_name, DTree& call_param)
void compiler_invoke_websocket(Request* context, String file_name)
{
auto su = compiler_load_shared_unit(context, file_name, "", false);
if(!su)
@@ -428,20 +621,98 @@ void compiler_invoke_websocket(Request* context, String file_name, DTree& call_p
String prev_wd = get_cwd();
set_cwd(su->src_path);
su->on_setup(context);
su->on_websocket(call_param);
su->on_websocket(*context);
set_cwd(prev_wd);
}
void render_file(String file_name)
{
//printf("(i) render_file(%s)\n", file_name.c_str());
DTree call_param;
compiler_invoke(context, file_name, call_param);
compiler_invoke(context, file_name);
}
void render_file(String file_name, DTree& call_param)
void render_file(String file_name, Request& context)
{
compiler_invoke(context, file_name, call_param);
compiler_invoke(&context, file_name);
}
String component_resolve(String name)
{
return(component_resolve_path(name));
}
bool component_exists(String name)
{
return(component_resolve(name) != "");
}
String component_error_banner(String message)
{
return("<div class=\"banner\">" + html_escape(message) + "</div>");
}
void render_component(String name)
{
DTree props;
render_component(name, props, *context);
}
void render_component(String name, Request& context)
{
DTree props;
render_component(name, props, context);
}
void render_component(String name, DTree props)
{
render_component(name, props, *context);
}
void render_component(String name, DTree props, Request& context)
{
String file_name;
String render_name;
component_parse_target(name, file_name, render_name);
String resolved_name = component_resolve_path(file_name);
if(resolved_name == "")
{
print(component_error_banner("component not found: " + file_name));
return;
}
DTree previous_call = context.call;
context.call = props;
String error_message = "";
if(!compiler_invoke_render(&context, resolved_name, render_name, &error_message) && error_message != "")
print(component_error_banner(error_message));
context.call = previous_call;
}
String component(String name)
{
DTree props;
return(component(name, props, *context));
}
String component(String name, Request& context)
{
DTree props;
return(component(name, props, context));
}
String component(String name, DTree props)
{
return(component(name, props, *context));
}
String component(String name, DTree props, Request& context)
{
ob_start();
render_component(name, props, context);
return(ob_get_close());
}
SharedUnit* load_file(String file_name)
+17 -5
View File
@@ -1,5 +1,7 @@
#define RENDER() extern "C" void render(DTree& call)
#define WS() extern "C" void websocket(DTree& call)
#pragma once
#define RENDER(X) extern "C" void render(Request& context)
#define WS(X) extern "C" void websocket(Request& context)
#define EXPORT extern "C"
String process_html_literal(Request* context, SharedUnit* su, String content);
@@ -8,13 +10,23 @@ void setup_unit_paths(Request* context, SharedUnit* su, String file_name);
void load_shared_unit(Request* context, SharedUnit* su, String file_name);
void compile_shared_unit(Request* context, SharedUnit* su, String file_name);
SharedUnit* get_shared_unit(Request* context, String file_name, bool opt_so_optional = false);
void compiler_invoke(Request* context, String file_name, DTree& call_param);
void compiler_invoke_websocket(Request* context, String file_name, DTree& call_param);
void compiler_invoke(Request* context, String file_name);
void compiler_invoke_websocket(Request* context, String file_name);
SharedUnit* compiler_load_shared_unit(Request* context, String file_name, String current_path = "", bool opt_so_optional = false);
SharedUnit* load_file(String file_name);
void render_file(String file_name);
void render_file(String file_name, DTree& call_param);
void render_file(String file_name, Request& context);
DTree* call_file(String file_name, String function_name, DTree* call_param = 0);
String component_resolve(String name);
bool component_exists(String name);
void render_component(String name);
void render_component(String name, Request& context);
void render_component(String name, DTree props);
void render_component(String name, DTree props, Request& context);
String component(String name);
String component(String name, Request& context);
String component(String name, DTree props);
String component(String name, DTree props, Request& context);
StringList precompile_jobs;
+167 -13
View File
@@ -1,10 +1,30 @@
namespace {
template <typename TreePtr>
TreePtr dtree_resolve_reference(TreePtr tree)
{
u32 depth = 0;
while(tree && tree->type == 'R' && depth < 16)
{
TreePtr target = reinterpret_cast<TreePtr>(tree->_ptr);
if(target == 0 || target == tree)
break;
tree = target;
depth += 1;
}
return(tree);
}
}
void DTree::each(std::function <void (DTree t, String key)> f)
{
switch(type)
const DTree& target = deref();
switch(target.type)
{
case('M'):
for (auto it = _map.begin(); it != _map.end(); ++it)
for (auto it = target._map.begin(); it != target._map.end(); ++it)
{
f(it->second, it->first);
}
@@ -17,43 +37,49 @@ void DTree::each(std::function <void (DTree t, String key)> f)
bool DTree::is_array()
{
return(type == 'M');
return(deref().type == 'M');
}
String DTree::to_string()
{
switch(type)
const DTree& target = deref();
switch(target.type)
{
case('S'):
return(_String);
return(target._String);
break;
case('F'):
return(std::to_string(_float));
return(std::to_string(target._float));
break;
case('B'):
return(_bool ? "(true)" : "(false)");
return(target._bool ? "(true)" : "(false)");
break;
case('M'):
return("");
break;
case('P'):
return(std::to_string((u64)_ptr));
return(std::to_string((u64)target._ptr));
break;
case('R'):
return("");
break;
}
return("");
}
String DTree::to_json()
{
switch(type)
const DTree& target = deref();
switch(target.type)
{
case('S'):
return(json_escape(_String));
return(json_escape(target._String));
break;
case('F'):
return(std::to_string(_float));
return(std::to_string(target._float));
break;
case('B'):
return(_bool ? "true" : "false");
return(target._bool ? "true" : "false");
break;
case('M'):
return("\"(array)\"");
@@ -61,12 +87,17 @@ String DTree::to_json()
case('P'):
return("\"(pointer)\"");
break;
case('R'):
return("\"(reference)\"");
break;
}
return("\"(unknown)\"");
}
String DTree::get_type_name()
{
switch(type)
const DTree& target = deref();
switch(target.type)
{
case('S'):
return("String");
@@ -83,11 +114,62 @@ String DTree::get_type_name()
case('P'):
return("pointer");
break;
case('R'):
return("reference");
break;
}
return("unknown");
}
bool DTree::is_reference()
{
return(type == 'R');
}
DTree* DTree::reference_target()
{
if(type != 'R')
return(0);
DTree* target = dtree_resolve_reference(this);
if(target == 0 || target == this || target->type == 'R')
return(0);
return(target);
}
const DTree* DTree::reference_target() const
{
if(type != 'R')
return(0);
const DTree* target = dtree_resolve_reference(this);
if(target == 0 || target == this || target->type == 'R')
return(0);
return(target);
}
DTree& DTree::deref()
{
DTree* target = dtree_resolve_reference(this);
if(target == 0)
return(*this);
return(*target);
}
const DTree& DTree::deref() const
{
const DTree* target = dtree_resolve_reference(this);
if(target == 0)
return(*this);
return(*target);
}
void DTree::set_type(char t)
{
DTree* target = reference_target();
if(target)
{
target->set_type(t);
return;
}
if(type != t)
{
type = t;
@@ -103,30 +185,60 @@ void DTree::set_type(char t)
void DTree::set(String s)
{
DTree* target = reference_target();
if(target)
{
target->set(s);
return;
}
set_type('S');
_String = s;
}
void DTree::set(void* p)
{
DTree* target = reference_target();
if(target)
{
target->set(p);
return;
}
set_type('P');
_ptr = p;
}
void DTree::set(f64 f)
{
DTree* target = reference_target();
if(target)
{
target->set(f);
return;
}
set_type('F');
_float = f;
}
void DTree::set_bool(bool b)
{
DTree* target = reference_target();
if(target)
{
target->set_bool(b);
return;
}
set_type('B');
_bool = b;
}
void DTree::set(DTree source)
{
DTree* target = reference_target();
if(target)
{
target->set(source);
return;
}
set_type(source.type);
switch(type)
{
@@ -145,11 +257,20 @@ void DTree::set(DTree source)
case('P'):
_ptr = source._ptr;
break;
case('R'):
_ptr = source._ptr;
break;
}
}
void DTree::set(StringMap source)
{
DTree* target = reference_target();
if(target)
{
target->set(source);
return;
}
set_type('M');
for (auto it = source.begin(); it != source.end(); ++it)
{
@@ -157,13 +278,25 @@ void DTree::set(StringMap source)
}
}
void DTree::set_reference(DTree* target)
{
type = 'R';
_ptr = target;
}
DTree* DTree::key(String s)
{
DTree* target = reference_target();
if(target)
return(target->key(s));
set_type('M');
return(&_map[s]);
}
DTree& DTree::operator [] (String s) {
DTree* target = reference_target();
if(target)
return((*target)[s]);
set_type('M');
return(_map[s]);
}
@@ -176,6 +309,12 @@ void DTree::operator = (StringMap v) { set(v); }
void DTree::push(DTree& child)
{
DTree* target = reference_target();
if(target)
{
target->push(child);
return;
}
set_type('M');
_map[std::to_string(_array_index)] = child;
_array_index += 1;
@@ -183,6 +322,9 @@ void DTree::push(DTree& child)
DTree DTree::pop()
{
DTree* target = reference_target();
if(target)
return(target->pop());
set_type('M');
auto last = _map.rbegin();
DTree result = last->second;
@@ -192,12 +334,24 @@ DTree DTree::pop()
void DTree::remove(String s)
{
DTree* target = reference_target();
if(target)
{
target->remove(s);
return;
}
set_type('M');
_map.erase(s);
}
void DTree::clear()
{
DTree* target = reference_target();
if(target)
{
target->clear();
return;
}
set_type('M');
_map.clear();
}
+8
View File
@@ -1,3 +1,5 @@
#pragma once
String json_escape(String s);
struct DTree {
@@ -16,6 +18,11 @@ struct DTree {
String to_string();
String to_json();
String get_type_name();
bool is_reference();
DTree* reference_target();
const DTree* reference_target() const;
DTree& deref();
const DTree& deref() const;
void set_type(char t);
void set(String s);
void set(void* p);
@@ -23,6 +30,7 @@ struct DTree {
void set_bool(bool b);
void set(DTree source);
void set(StringMap source);
void set_reference(DTree* target);
DTree* key(String s);
DTree& operator [] (String s);
void operator = (String v);
+9 -3
View File
@@ -77,9 +77,9 @@ String replace(String s, String search, String replace_with)
String trim(String raw)
{
u32 len = raw.length();
u32 start_pos = 0;
u32 end_pos = len - 1;
s64 len = raw.length();
s64 start_pos = 0;
s64 end_pos = len - 1;
if(len == 0 || (len == 1 && isspace(raw[0])))
return("");
while(start_pos < len && isspace(raw[start_pos]))
@@ -610,7 +610,13 @@ void ob_close()
delete context->ob;
context->ob_stack.pop_back();
if(context->ob_stack.size() == 0)
{
ob_start();
}
else
{
context->ob = context->ob_stack.back();
}
}
String ob_get()
+2
View File
@@ -1,4 +1,6 @@
#pragma once
u8 char_to_u8(char input);
u8 hex_to_u8(String src);
u64 int_val(String s, u32 base = 10);
+2
View File
@@ -1,3 +1,5 @@
#pragma once
/* ================ sha1.h ================ */
/*
SHA-1 in C
+1378
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -0,0 +1,6 @@
#pragma once
DTree markdown_to_ast(String src);
DTree markdown_to_ast(String src, DTree options);
String markdown_to_html(String src);
String markdown_to_html(String src, DTree options);
+2
View File
@@ -1,3 +1,5 @@
#pragma once
struct MySQLFieldInfo {
String name;
String table;
+45 -9
View File
@@ -10,6 +10,45 @@
#include <sys/file.h>
#include "sys.h"
String capture_backtrace_string(u32 max_frames, u32 skip_frames)
{
if(max_frames == 0)
return("");
std::vector<void*> frames(max_frames);
size_t size = backtrace(frames.data(), max_frames);
if(size == 0)
return("");
char** symbols = backtrace_symbols(frames.data(), size);
if(!symbols)
return("");
String trace;
for(size_t i = skip_frames; i < size; i++)
{
trace += symbols[i];
trace += "\n";
}
free(symbols);
return(trace);
}
String signal_name(int sig)
{
switch(sig)
{
case SIGABRT: return("SIGABRT");
case SIGBUS: return("SIGBUS");
case SIGFPE: return("SIGFPE");
case SIGILL: return("SIGILL");
case SIGINT: return("SIGINT");
case SIGSEGV: return("SIGSEGV");
case SIGTERM: return("SIGTERM");
default: return("");
}
}
String shell_exec(String cmd)
{
//printf("(i) shell_exec(%s)\n", cmd.c_str());
@@ -410,15 +449,12 @@ StringMap memcache_get_multiple(u64 connection, StringList keys)
void on_segfault(int sig)
{
void *array[10];
size_t size;
// get void*'s for all entries on the stack
size = backtrace(array, 10);
// print out all the frames to stderr
fprintf(stderr, "SEG FAULT: %d:\n", sig);
backtrace_symbols_fd(array, size, STDERR_FILENO);
String trace = capture_backtrace_string(32, 1);
String sig_label = signal_name(sig);
if(sig_label != "")
fprintf(stderr, "SEG FAULT: %d (%s):\n%s", sig, sig_label.c_str(), trace.c_str());
else
fprintf(stderr, "SEG FAULT: %d:\n%s", sig, trace.c_str());
exit(1);
}
+7 -3
View File
@@ -1,3 +1,5 @@
#pragma once
#include <signal.h>
String shell_exec(String cmd);
@@ -43,11 +45,13 @@ u8 ws_opcode();
bool ws_is_binary();
StringList ws_connections(String scope = "");
u64 ws_connection_count(String scope = "");
bool ws_send(String message, String scope = "");
u64 ws_broadcast(String message, String scope = "");
bool ws_send_to(String connection_id, String message);
bool ws_send(String message, bool binary = false, String scope = "");
bool ws_send_to(String connection_id, String message, bool binary = false);
bool ws_close(String connection_id = "");
String capture_backtrace_string(u32 max_frames = 32, u32 skip_frames = 0);
String signal_name(int sig);
String memcache_escape_key(String key);
StringList memcache_escape_keys(StringList keys);
u64 memcache_connect(String host = "127.0.0.1", short port = 11211);
+10 -5
View File
@@ -1,3 +1,5 @@
#pragma once
#include <string>
#include <map>
#include <list>
@@ -52,7 +54,7 @@ typedef std::ostringstream ByteStream;
struct Request;
struct DTree;
typedef void (*call_handler)(DTree& call_param);
typedef void (*request_ref_handler)(Request& request);
typedef DTree* (*dtree_call_handler)(DTree* call_param);
typedef void (*request_handler)(Request* request);
@@ -77,8 +79,8 @@ struct SharedUnit {
void* so_handle;
request_handler on_setup;
call_handler on_render;
call_handler on_websocket;
request_ref_handler on_render;
request_ref_handler on_websocket;
String compiler_messages;
time_t last_compiled;
@@ -113,7 +115,7 @@ String nibble(String div, String& haystack);
#include "dtree.h"
void compiler_invoke(Request* context, String file_name, DTree& call_param);
void compiler_invoke(Request* context, String file_name);
struct Request {
@@ -126,6 +128,8 @@ struct Request {
StringMap session;
DTree var;
DTree call;
DTree connection;
String session_id = "";
String session_name = "";
@@ -148,7 +152,7 @@ struct Request {
struct Flags {
bool log_request = true;
bool is_finished = false;
int status;
int status = 0;
bool output_closed = false;
bool params_closed = false;
bool input_closed = false;
@@ -173,6 +177,7 @@ struct Request {
bool is_websocket = false;
String websocket_connection_id = "";
String websocket_scope = "";
DTree* websocket_connection_state = 0;
u8 websocket_opcode = 0;
bool websocket_is_binary = false;
bool websocket_is_text = false;
+1
View File
@@ -7,4 +7,5 @@
#include "sys.cpp"
#include "uri.cpp"
#include "compiler.cpp"
#include "markdown.cpp"
#include "mysql-connector.cpp"
+3 -2
View File
@@ -1,10 +1,11 @@
#pragma once
#include "types.h"
#include "hash.h"
#include "functionlib.h"
#include "sys.h"
#include "uri.h"
#include "compiler.h"
#include "markdown.h"
#include "mysql-connector.h"
+2 -1
View File
@@ -1,3 +1,4 @@
#pragma once
#include "uce_lib.h"
+2
View File
@@ -1,4 +1,6 @@
#pragma once
String var_dump(URI uri, String prefix = "", String postfix = "\n");
String uri_decode(String q);