diff --git a/bin/uce_fastcgi.debug.linux.bin b/bin/uce_fastcgi.debug.linux.bin index e218c0f..3456865 100755 Binary files a/bin/uce_fastcgi.debug.linux.bin and b/bin/uce_fastcgi.debug.linux.bin differ diff --git a/src/fastcgi/src/fcgicc.cc b/src/fastcgi/src/fcgicc.cc index ed06247..e02fb4e 100644 --- a/src/fastcgi/src/fcgicc.cc +++ b/src/fastcgi/src/fcgicc.cc @@ -509,9 +509,30 @@ FastCGIServer::process_write_request(Connection& connection, RequestID id, } if ((request.in_closed || request.status != 0) && !request.output_closed) { + + request.out = + var_dump(request.header, "", "\r\n") + + var_dump(request.set_cookies, "", "\r\n") + + "\r\n"; + + for(auto obs : request.ob_stack) + { + request.out += obs->str(); + delete obs; + } + request.ob_stack.clear(); + write_data(connection.output_buffer, id, request.out, FCGI_STDOUT); write_data(connection.output_buffer, id, request.err, FCGI_STDERR); + request.time_end = microtime(); + printf("(r) pid:%i\t%s\t%0.6fs\t%0.1fkB\n", + my_pid, + request.params["REQUEST_URI"].c_str(), + request.time_end - request.time_start, + (f32)(request.out.length()/1024) + ); + FCGI_EndRequestRecord complete; bzero(&complete, sizeof(complete)); complete.header.version = FCGI_VERSION_1; diff --git a/src/lib/compiler.cpp b/src/lib/compiler.cpp index 217c241..15364f2 100644 --- a/src/lib/compiler.cpp +++ b/src/lib/compiler.cpp @@ -4,7 +4,7 @@ String process_html_literal(Request* context, SharedUnit* su, String content) { String pc; - String HT_START = "context->print(R\"("; + String HT_START = "print(R\"("; String HT_END = ")\");"; u8 mode = 0; @@ -63,7 +63,7 @@ String process_html_literal(Request* context, SharedUnit* su, String content) { pc.append( HT_END + - "echo(html_escape( " + + "print(html_escape( " + code_buffer + " )); " + HT_START @@ -299,17 +299,17 @@ void compiler_invoke(Request* context, String file_name, DTree& call_param) if(!su) { printf("Error loading unit %s\n", file_name.c_str()); - context->print("Error loading unit: "+file_name); + print("Error loading unit: "+file_name); } else if(!su->on_render) { context->header["Content-Type"] = "text/plain"; - context->print("Compiler error: "+su->compiler_messages); + print("Compiler error: "+su->compiler_messages); } else { if(su->compiler_messages.length() > 0) - context->print(su->compiler_messages); + print(su->compiler_messages); else { String prev_wd = get_cwd(); diff --git a/src/lib/functionlib.cpp b/src/lib/functionlib.cpp index 6dcb6d6..e586325 100644 --- a/src/lib/functionlib.cpp +++ b/src/lib/functionlib.cpp @@ -184,14 +184,14 @@ String json_encode(DTree t) String json_decode_String(String s, u32& i, char termination_char) { String result; - //echo("json_decode_String " + s.substr(i) + "\n"); + //print("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"); + //print("json_decode_String = " + result + "\n"); return(result); } else if(c == '\\') @@ -289,7 +289,7 @@ DTree json_decode_value(String s, u32& i) String value = ""; json_consume_space(s, i); char c = s[i]; - //echo("json_decode_value " + s.substr(i) + "\n"); + //print("json_decode_value " + s.substr(i) + "\n"); if(c == '"' || c == '\'') // String value { result.type = 'S'; @@ -329,7 +329,7 @@ DTree json_decode_map(String s, u32& i) result.type = 'M'; String key = ""; json_consume_space(s, i); - //echo("json_decode_map " + s.substr(i) + "\n"); + //print("json_decode_map " + s.substr(i) + "\n"); while(i < s.length()) { char c = s[i]; @@ -352,7 +352,7 @@ DTree json_decode_map(String s, u32& i) i += 1; DTree v = json_decode_value(s, i); //result._map[key] = json_decode_value(s, i); - //echo("KV " + key + " = " + to_String(v) + "\n"); + //print("KV " + key + " = " + to_String(v) + "\n"); //printf("map add %s (%c) \n", key.c_str(), s[i]); result._map[key] = v; } @@ -372,4 +372,28 @@ DTree json_decode(String s) return(json_decode_value(s, i)); } +void ob_start() +{ + context->ob_start(); +} + +void ob_close() +{ + delete context->ob; + context->ob_stack.pop_back(); + if(context->ob_stack.size() == 0) + ob_start(); +} + +String ob_get() +{ + return(context->ob->str()); +} + +String ob_get_close() +{ + String result = context->ob->str(); + ob_close(); + return(result); +} diff --git a/src/lib/functionlib.h b/src/lib/functionlib.h index 2a67d6c..10b2e23 100644 --- a/src/lib/functionlib.h +++ b/src/lib/functionlib.h @@ -24,3 +24,8 @@ DTree json_decode(String s); String var_dump(StringMap map, String prefix = "", String postfix = "\n"); String var_dump(StringList slist, String prefix = "", String postfix = "\n"); + +void ob_start(); +void ob_clear(); +String ob_get_clear(); +String ob_get(); diff --git a/src/lib/sys.cpp b/src/lib/sys.cpp index 6008954..e374d82 100644 --- a/src/lib/sys.cpp +++ b/src/lib/sys.cpp @@ -247,7 +247,7 @@ u64 socket_connect(String host, short port) auto sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(sockfd < 0) { - echo("SOCKET ERROR (could not open socket)\n"); + print("SOCKET ERROR (could not open socket)\n"); perror("SOCKET ERROR "); return(0); } @@ -259,7 +259,7 @@ u64 socket_connect(String host, short port) if(connect(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0) { - echo("SOCKET ERROR (could not connect to address " + String(host) + ":" + std::to_string(port) + ")\n"); + print("SOCKET ERROR (could not connect to address " + String(host) + ":" + std::to_string(port) + ")\n"); perror("SOCKET ERROR "); return(0); } @@ -438,3 +438,4 @@ void on_child_exit(int sig) } } + diff --git a/src/lib/types.cpp b/src/lib/types.cpp index 77fe370..b255529 100644 --- a/src/lib/types.cpp +++ b/src/lib/types.cpp @@ -50,9 +50,10 @@ void Request::invoke(String file_name, DTree& call_param) compiler_invoke(this, file_name, call_param); } -void Request::print(String s) +void Request::ob_start() { - out.append(s); + ob_stack.push_back(new std::ostringstream()); + ob = ob_stack.back(); } Request::~Request() diff --git a/src/lib/types.h b/src/lib/types.h index 93e7a05..d2e1b2a 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -3,6 +3,7 @@ #include #include #include +#include typedef unsigned char u8; typedef signed char s8; @@ -17,6 +18,30 @@ typedef long long s64; typedef std::string String; +String operator+(String lhs, u64 rhs) { + return(lhs + std::to_string(rhs)); +} + +String operator+(String lhs, u32 rhs) { + return(lhs + std::to_string(rhs)); +} + +String operator+(String lhs, s64 rhs) { + return(lhs + std::to_string(rhs)); +} + +String operator+(String lhs, s32 rhs) { + return(lhs + std::to_string(rhs)); +} + +String operator+(String lhs, f64 rhs) { + return(lhs + std::to_string(rhs)); +} + +String operator+(String lhs, f32 rhs) { + return(lhs + std::to_string(rhs)); +} + #define DEBUG_MEMORY_OFF; #define NO_GLOBAL_ARENA_ALLOCATOR; @@ -105,9 +130,6 @@ void operator delete(void * p) throw() } #endif -//#define to_String(a) std::to_String(a) -#define echo(s) context->print(s) - typedef std::map StringMap; typedef std::vector StringList; @@ -217,13 +239,21 @@ struct Request { MemoryArena* request_arena; String in; + std::vector ob_stack; + std::ostringstream* ob; String out; String err; + bool is_finished = false; + f64 time_init; f64 time_start; f64 time_end; + struct Stats { + u32 bytes_written; + } stats; + struct Resources { std::vector sockets; std::vector mysql_connections; @@ -231,7 +261,9 @@ struct Request { void invoke(String file_name); void invoke(String file_name, DTree& call_param); - void print(String s); + + void ob_start(); + ~Request(); }; @@ -239,3 +271,11 @@ struct Request { typedef Request FastCGIRequest; Request* context; + +#include + +template +void print(Ts... args) +{ + ((*context->ob << args), ...); +} diff --git a/src/linux_fastcgi.cpp b/src/linux_fastcgi.cpp index ad63de0..4da03a8 100644 --- a/src/linux_fastcgi.cpp +++ b/src/linux_fastcgi.cpp @@ -12,6 +12,8 @@ int handle_request(FastCGIRequest& request) { // standard input stream. request.request_arena = request_arena; request.time_init = microtime(); + request.ob_start(); // this one is for the headers + request.ob_start(); // this one is for the content if (request.params.count("REQUEST_URI")) return 0; // OK, continue processing else @@ -70,12 +72,6 @@ int handle_complete(FastCGIRequest& request) { request.invoke(request.params["SCRIPT_FILENAME"]); switch_to_system_alloc(); - String headers = - var_dump(request.header, "", "\r\n") + - var_dump(request.set_cookies, "", "\r\n") + - "\r\n"; - request.out = headers + request.out; - for( auto &f : request.uploaded_files) { unlink(f.tmp_name); @@ -86,14 +82,6 @@ int handle_complete(FastCGIRequest& request) { cleanup_mysql_connections(); - request.time_end = microtime(); - printf("(r) pid:%i\t%s\t%0.6fs\t%0.1fkB\n", - my_pid, - request.params["REQUEST_URI"].c_str(), - request.time_end - request.time_start, - (f32)(request.out.length()/1024) - ); - return 0; } diff --git a/test/cookie.uce b/test/cookie.uce index c50a959..b898cb5 100644 --- a/test/cookie.uce +++ b/test/cookie.uce @@ -14,13 +14,13 @@ RENDER() set_cookie("test-cookie-1", "test-value-1", time() + 30*60); set_cookie("test-cookie-2", "test-value-2", time() + 30*60*24); - echo(var_dump(context->set_cookies)); + print(var_dump(context->set_cookies)); ?> Get
cookies));
+		print(var_dump(context->cookies));
 
 		?>
Params diff --git a/test/dtree.uce b/test/dtree.uce index 004007f..97a7ff4 100644 --- a/test/dtree.uce +++ b/test/dtree.uce @@ -16,16 +16,16 @@ RENDER()
@@ -43,7 +43,7 @@ RENDER() t["g"]["x"]["y2"] = &t; t["g"]["x"]["y3"] = time(); t["g"]["x"]["y4"] = "Ünicödä"; - echo(var_dump(t)); + print(var_dump(t)); ?> diff --git a/test/inc-test.cpp b/test/inc-test.cpp index 69d160f..4550c6c 100644 --- a/test/inc-test.cpp +++ b/test/inc-test.cpp @@ -1,4 +1,4 @@ void test_output() { - echo("hello from include!"); + print("hello from include!"); } diff --git a/test/index.uce b/test/index.uce index 12001db..d3ee131 100644 --- a/test/index.uce +++ b/test/index.uce @@ -26,8 +26,8 @@ RENDER()
  • File I/O
  • diff --git a/test/json.uce b/test/json.uce index ffcea99..3110f7e 100644 --- a/test/json.uce +++ b/test/json.uce @@ -29,14 +29,14 @@ RENDER() t["l"] = context->params; String j; - echo(j = json_encode(t)); + print(j = json_encode(t)); ?> Parsed:
    @@ -44,7 +44,7 @@ RENDER() Compare:
    diff --git a/test/memcached.uce b/test/memcached.uce index f091dae..db8465b 100644 --- a/test/memcached.uce +++ b/test/memcached.uce @@ -17,7 +17,7 @@ RENDER() auto sfd = memcache_connect(); - echo(memcache_command(sfd, "stats")); + print(memcache_command(sfd, "stats")); ?> @@ -27,9 +27,9 @@ RENDER() memcache_set(sfd, "test_key", "test_value"); memcache_set(sfd, "test_key2", "test_value2"); - echo("raw:: "+memcache_command(sfd, "get test_key")+"\n"); - echo("get:: "+memcache_get(sfd, "test_key")+"\n"); - echo("multiple::\n"+var_dump(memcache_get_multiple(sfd, {"test_key", "test_key2"}))+"\n"); + print("raw:: "+memcache_command(sfd, "get test_key")+"\n"); + print("get:: "+memcache_get(sfd, "test_key")+"\n"); + print("multiple::\n"+var_dump(memcache_get_multiple(sfd, {"test_key", "test_key2"}))+"\n"); ?> diff --git a/test/mysql.uce b/test/mysql.uce index 1dd31da..744a885 100644 --- a/test/mysql.uce +++ b/test/mysql.uce @@ -21,11 +21,11 @@ RENDER() MySQL con; if(con.connect("localhost", "root", "")) { - echo("connection established\n"); - echo("error: "+con.error()+"\n"); - echo("quotation test: "+con.escape("‘\"' or 1=1;–.")+"\n"); - echo("query parse: "+con.parse_query_parameters(query, params)+"\n"); - echo(var_dump(con.query("SHOW DATABASES"))); + print("connection established\n"); + print("error: "+con.error()+"\n"); + print("quotation test: "+con.escape("‘\"' or 1=1;–.")+"\n"); + print("query parse: "+con.parse_query_parameters(query, params)+"\n"); + print(var_dump(con.query("SHOW DATABASES"))); con.query("USE mysql"); ?> @@ -34,7 +34,7 @@ RENDER()
    session["stored-value"] = make_session_id();
    -		echo("action: storing value "+context->session["stored-value"]);
    +		print("action: storing value "+context->session["stored-value"]);
     	}
     	else if(action == "destroy")
     	{
     		session_destroy();
    -		echo("action: destroying session");
    +		print("action: destroying session");
     	}
     
     	<>
    @@ -40,9 +40,9 @@ RENDER()
     		Info
     		
    cookies));
    -		echo("SESSION:\n");
    -		echo(var_dump(context->session));
    +		print(var_dump(context->cookies));
    +		print("SESSION:\n");
    +		print(var_dump(context->session));
     
     		?>
    Params diff --git a/test/string.uce b/test/string.uce new file mode 100644 index 0000000..80b00ef --- /dev/null +++ b/test/string.uce @@ -0,0 +1,27 @@ + + + + + +RENDER() +{ + DTree t; + + <> + +

    + UCE Test: + Strings +

    + +
    + + Params +
    params) ?>
    + + +} diff --git a/test/working-dir.uce b/test/working-dir.uce index ea575c6..6322d3d 100644 --- a/test/working-dir.uce +++ b/test/working-dir.uce @@ -10,7 +10,7 @@ RENDER() Working Directory
    invoke("test2/working-dir-test.uce");
     		?>
    params) ?>