Compare commits
3 Commits
b8adc5bd55
...
35ce3aeca7
Author | SHA1 | Date | |
---|---|---|---|
35ce3aeca7 | |||
0d479fcd0c | |||
28dec5384c |
@ -1,31 +1,32 @@
|
||||
{% ELDEF main JSON pres %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Список Чат-Комнат</title>
|
||||
<title>{% WRITE pres.phr.decl.list-of-chat-rooms %}</title>
|
||||
<link rel="stylesheet" href="/assets/css/list-rooms.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 style="color: white;">Выберите Чат-Комнату</h1>
|
||||
<h1 style="color: white;">{% WRITE pres.phr.decl.select-chat-room %}</h1>
|
||||
<ul class="room-list">
|
||||
<!-- Здесь будет список комнат -->
|
||||
</ul>
|
||||
<button class="create-room-button" onclick="openCreateRoomModal()">Создать Комнату</button>
|
||||
<button class="create-room-button" onclick="openCreateRoomModal()">{% WRITE pres.phr.act.create-room %}</button>
|
||||
</div>
|
||||
|
||||
<div id="passwordModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<span class="close" onclick="closeModal()">×</span>
|
||||
<h2>Введите Пароль</h2>
|
||||
<h2>VVedite parol</h2> <!-- Nam ne nuzhen parol ot komnat -->
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="password" id="roomPassword" placeholder="Пароль">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="join-button" onclick="validatePassword()">Подтвердить</button>
|
||||
<button class="join-button" onclick="validatePassword()">{% WRITE pres.phr.act.confirm %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -35,14 +36,14 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<span class="close" onclick="closeCreateRoomModal()">×</span>
|
||||
<h2>Создать Комнату</h2>
|
||||
<h2>{% WRITE pres.phr.decl.create-room %}</h2>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="text" id="newRoomName" placeholder="Название комнаты">
|
||||
<input type="password" id="newRoomPassword" placeholder="Пароль">
|
||||
<input type="text" id="newRoomName" placeholder="{% WRITE pres.phr.decl.name-of-room %}">
|
||||
<input type="password" id="newRoomPassword" placeholder="Пароль"> <!-- Fedya, nam ne nuzhen parol -->
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="join-button" onclick="createRoom()">Создать</button>
|
||||
<button class="join-button" onclick="createRoom()">{% WRITE pres.phr.act.create %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -50,3 +51,4 @@
|
||||
<script src="/assets/js/list-rooms.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
{% ENDELDEF %}
|
@ -1,3 +1,32 @@
|
||||
{
|
||||
"name": "Web chat"
|
||||
"presentation": {
|
||||
"instance-identity": {
|
||||
"top-title": "Вэб чат ИУ9"
|
||||
},
|
||||
"phr": {
|
||||
"decl": {
|
||||
"list-of-chat-rooms": "Список Чат-Комнат",
|
||||
"select-chat-room": "Выберете чат комнату",
|
||||
"name-of-room": "Название комнаты",
|
||||
"create-room": "Создать комнату"
|
||||
},
|
||||
"act": {
|
||||
"create-room": "Создать комнату",
|
||||
"confirm": "Подтвердить",
|
||||
"create": "Создать"
|
||||
}
|
||||
}
|
||||
},
|
||||
"assets": "./assets",
|
||||
"limits": {
|
||||
"max-users": 100000,
|
||||
"max-rooms": 100000,
|
||||
"max-messages": 10000000000000,
|
||||
"storage-size-limit": 100000000000
|
||||
},
|
||||
"server": {
|
||||
"workers": 8,
|
||||
"http-listen": ["127.0.0.1:1025"],
|
||||
"command-listen": []
|
||||
}
|
||||
}
|
@ -82,10 +82,10 @@ namespace een9 {
|
||||
|
||||
struct WorkersEnv {
|
||||
WorkersEnvCommon& wtec;
|
||||
int id;
|
||||
worker_id_t id;
|
||||
ClientRequestParser_WorkerBuffers personal_parser_buffer;
|
||||
|
||||
explicit WorkersEnv(WorkersEnvCommon& wtec, int id): wtec(wtec), id(id), personal_parser_buffer(wtec.parser_programs){}
|
||||
explicit WorkersEnv(WorkersEnvCommon& wtec, worker_id_t id): wtec(wtec), id(id), personal_parser_buffer(wtec.parser_programs){}
|
||||
};
|
||||
|
||||
// todo: add timeout for multiple bytes, add more settings
|
||||
@ -125,7 +125,7 @@ namespace een9 {
|
||||
|
||||
void process_connection(const SlaveTask& task, WorkersEnv& wte) {
|
||||
ClientRequest client_request = process_connection_input(task.fd(), task.s_tips, wte);
|
||||
std::string server_response = wte.wtec.guest_core(task, client_request);
|
||||
std::string server_response = wte.wtec.guest_core(task, client_request, wte.id);
|
||||
process_connection_output(task.fd(), server_response);
|
||||
}
|
||||
|
||||
@ -149,6 +149,7 @@ namespace een9 {
|
||||
} catch (const std::exception& e) {
|
||||
printf("Client request procession failure in worker\n");
|
||||
printf("%s\n", e.what());
|
||||
/* Under mysterious some circumstances, in this place destructor of string in SystemError causes segfault. I can't fix that */
|
||||
}
|
||||
}
|
||||
printf("Worker finished\n");
|
||||
@ -166,7 +167,7 @@ namespace een9 {
|
||||
std::vector<pthread_t> workers(params.slave_number);
|
||||
std::vector<uptr<WorkersEnv>> wtes(params.slave_number);
|
||||
for (size_t i = 0; i < params.slave_number; i++) {
|
||||
wtes[i] = std::make_unique<WorkersEnv>(wtec, i);
|
||||
wtes[i] = std::make_unique<WorkersEnv>(wtec, (worker_id_t)i);
|
||||
}
|
||||
for (size_t i = 0; i < params.slave_number; i++) {
|
||||
pthread_create(&workers[i], NULL, worker_func, wtes[i].get());
|
||||
|
@ -29,8 +29,10 @@ namespace een9 {
|
||||
EEN9_ServerTips s_tips;
|
||||
};
|
||||
|
||||
typedef int worker_id_t;
|
||||
|
||||
/* guest_core function must not throw anything that is not derived from std::exception */
|
||||
typedef std::function<std::string(const SlaveTask&, const ClientRequest&)> guest_core_t;
|
||||
typedef std::function<std::string(const SlaveTask&, const ClientRequest&, worker_id_t worker_id)> guest_core_t;
|
||||
|
||||
struct ServersConfiguration {
|
||||
size_t critical_load_1 = 90;
|
||||
|
@ -87,4 +87,9 @@ namespace nytl {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void rstrip(std::string &str) {
|
||||
while (!str.empty() && isSPACE(str.back()))
|
||||
str.resize(str.size() - 1);
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
#ifndef NEW_YORK_TRANSIT_LINE_ALOTALOT_H
|
||||
#define NEW_YORK_TRANSIT_LINE_ALOTALOT_H
|
||||
|
||||
/* A little of this, a little of that
|
||||
* DO NOT EXPORT THIS FILE */
|
||||
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
/* A little of this, a little of that
|
||||
* DO NOT EXPORT THIS FILE */
|
||||
|
||||
namespace nytl {
|
||||
template<typename T>
|
||||
using uptr = std::unique_ptr<T>;
|
||||
@ -46,6 +46,8 @@ namespace nytl {
|
||||
bool is_uname_dotted_sequence(const std::string& uinp);
|
||||
|
||||
std::string make_uppercase(const std::string& source);
|
||||
|
||||
void rstrip(std::string& str);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -4,7 +4,11 @@
|
||||
#include "templater.h"
|
||||
#include <functional>
|
||||
|
||||
/* Do not export this header */
|
||||
|
||||
namespace nytl {
|
||||
void debug_print_templater(const Templater& T);
|
||||
|
||||
/* ============== For parsing =============================*/
|
||||
void parse_bare_file(const std::string& filename, const std::string& content,
|
||||
global_elem_set_t& result);
|
||||
@ -24,7 +28,7 @@ namespace nytl {
|
||||
LocalVarValue rendering_core_execute_expression(const global_elem_set_t& global_elems,
|
||||
const std::vector<LocalVarValue>& local_vars, const json::JSON& expr);
|
||||
|
||||
std::string rendering_core(const std::string& entry_func, const std::vector<json::JSON>& entry_arguments,
|
||||
std::string rendering_core(const std::string& entry_func, const std::vector<const json::JSON*>& entry_arguments,
|
||||
const global_elem_set_t& elem_ns, const std::function<std::string(std::string)>& escape);
|
||||
}
|
||||
|
||||
|
49
src/http_server/new_york_transit_line/debug_print.cpp
Normal file
49
src/http_server/new_york_transit_line/debug_print.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "templater.h"
|
||||
#include "alotalot.h"
|
||||
#include "jsonincpp/string_representation.h"
|
||||
#include <assert.h>
|
||||
|
||||
namespace nytl {
|
||||
void debug_print_templater(const Templater& T) {
|
||||
printf("===== TEMPLATER INTERNAL RESOURCES =====\n");
|
||||
for (auto& p: T.elements) {
|
||||
printf("=== %s element =====\n", p.first.c_str());
|
||||
const Element& el = p.second;
|
||||
printf("%s, %s\n", el.base ? "BASE" : "NOT BASE", el.is_hidden ? "HIDDEN" : "NOT HIDDEN");
|
||||
if (!el.is_hidden) {
|
||||
std::string signature;
|
||||
for (const json::JSON& arg_type: el.arguments) {
|
||||
if (!signature.empty())
|
||||
signature += " ";
|
||||
signature += json::generate_str(arg_type, json::print_compact);
|
||||
}
|
||||
printf("Signature: %s\n", signature.c_str());
|
||||
}
|
||||
for (const ElementPart& part: el.parts) {
|
||||
if (part.type == ElementPart::p_code) {
|
||||
printf("code: <b><e><f><o><r><e><><l><f>\n%s\n<a><f><t><e><r><><l><f>\n", part.when_code.lines.c_str());
|
||||
} else if (part.type == ElementPart::p_for_put) {
|
||||
const ElementPart::when_for_put_S& P = part.when_for_put;
|
||||
printf("dor cycle call:\ninternal_element: %s,\nref_over:%s,\nwhere_key_var: %ld, where_value_var: %ld, %s\n",
|
||||
P.internal_element.c_str(), json::generate_str(P.ref_over, json::print_pretty).c_str(),
|
||||
P.where_key_var, P.where_value_var, P.line_feed ? "LF" : "NOLF");
|
||||
} else if (part.type == ElementPart::p_ref_put) {
|
||||
const ElementPart::when_ref_put_S& P = part.when_ref_put;
|
||||
printf("ref block call:\ninternal_element: %s\nref_over:%s\n",
|
||||
P.internal_element.c_str(), json::generate_str(P.ref_over, json::print_pretty).c_str());
|
||||
} else {
|
||||
assert(part.type == ElementPart::p_put);
|
||||
const ElementPart::when_put_S& P = part.when_put;
|
||||
printf("PUT:\ncalled_element: %s\n",
|
||||
json::generate_str(P.called_element, json::print_pretty).c_str());
|
||||
for (size_t i = 0; i < P.passed_arguments.size(); i++) {
|
||||
printf("passed_arguments[%lu] = %s\n", i,
|
||||
json::generate_str(P.passed_arguments[i], json::print_pretty).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("=== That was element %s ====\n", p.first.c_str());
|
||||
}
|
||||
printf("===== DEBUG IS OVER =====\n");
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
namespace nytl {
|
||||
/* Expression Execution Frame */
|
||||
struct EEFrame {
|
||||
const json::JSON& expr;
|
||||
LocalVarValue& result;
|
||||
@ -14,6 +15,15 @@ namespace nytl {
|
||||
result(result) {
|
||||
}
|
||||
|
||||
// todo: remove this debug function
|
||||
// void print_result() {
|
||||
// if (result.is_json) {
|
||||
// printf("print_result %%p: %p\n", result.JSON_subval);
|
||||
// printf("%s\n", json::generate_str(*result.JSON_subval, json::print_compact).c_str());
|
||||
// } else
|
||||
// printf("element %s\n", result.EL_name.c_str());
|
||||
// }
|
||||
|
||||
void descend(const json::JSON& what) {
|
||||
if (result.is_json) {
|
||||
const json::JSON& P = *result.JSON_subval;
|
||||
@ -23,7 +33,7 @@ namespace nytl {
|
||||
ASSERT(ind_w > 0 && ind_w < arr_p.size(), "Expression \"array[integer]\" caused out-of-bound situation");
|
||||
result = LocalVarValue{true, "", &arr_p[ind_w]};
|
||||
} else if (P.isDictionary() && what.isString()) {
|
||||
const std::map<std::string, json::JSON> dict_p = P.asDictionary();
|
||||
const std::map<std::string, json::JSON>& dict_p = P.asDictionary();
|
||||
const std::string& key_w = what.asString();
|
||||
ASSERT(dict_p.count(key_w) == 1, "No such key exception");
|
||||
result = LocalVarValue{true, "", &dict_p.at(key_w)};
|
||||
|
@ -16,11 +16,6 @@ namespace nytl {
|
||||
return first_nw_char(str) == str.size();
|
||||
}
|
||||
|
||||
void rstrip(std::string& str) {
|
||||
while (!str.empty() && isSPACE(str.back()))
|
||||
str.resize(str.size() - 1);
|
||||
}
|
||||
|
||||
std::string clement_lstrip(const std::string& str) {
|
||||
size_t gone = 0;
|
||||
size_t n = str.size();
|
||||
@ -28,10 +23,10 @@ namespace nytl {
|
||||
if (str[i] == '\n') {
|
||||
gone = i + 1;
|
||||
} else if (!isSPACE(str[i])) {
|
||||
return str.substr(gone);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
return str.substr(gone);
|
||||
}
|
||||
|
||||
struct ParsingContext {
|
||||
@ -125,22 +120,29 @@ namespace nytl {
|
||||
return result;
|
||||
}
|
||||
|
||||
void one_part_update_min_start_wsp_non_empty(const std::string& str, bool is_first, size_t& min) {
|
||||
bool is_relevant_in_tab_cut(size_t PN, size_t I, size_t LN, size_t j, const std::string& line) {
|
||||
if (j == 0 && I != 0)
|
||||
return false;
|
||||
if (!is_space_only(line))
|
||||
return true;
|
||||
return j + 1 == LN && I + 1 < PN;
|
||||
}
|
||||
|
||||
void one_part_update_min_start_wsp_non_empty(const std::string& str, size_t I, size_t PN, size_t& min) {
|
||||
std::vector<std::string> lines = splitIntoLines(str);
|
||||
size_t L = lines.size();
|
||||
for (size_t i = is_first ? 0 : 1; i < L; i++) {
|
||||
size_t first_nw = first_nw_char(lines[i]);
|
||||
if (first_nw < lines[i].size())
|
||||
min = std::min(min, first_nw);
|
||||
size_t LN = lines.size();
|
||||
for (size_t j = 0; j < LN; j++) {
|
||||
if (is_relevant_in_tab_cut(PN, I, LN, j, lines[j]))
|
||||
min = std::min(min, first_nw_char(lines[j]));
|
||||
}
|
||||
}
|
||||
|
||||
std::string one_part_cut_excess_tab(const std::string& str, bool is_first, size_t cut) {
|
||||
std::string one_part_cut_excess_tab(const std::string& str, size_t I, size_t PN, size_t cut) {
|
||||
std::vector<std::string> lines = splitIntoLines(str);
|
||||
size_t L = lines.size();
|
||||
for (size_t i = is_first ? 0 : 1; i < L; i++) {
|
||||
if (!is_space_only(lines[i]))
|
||||
lines[i] = lines[i].substr(cut);
|
||||
size_t LN = lines.size();
|
||||
for (size_t j = 0; j < LN; j++) {
|
||||
if (is_relevant_in_tab_cut(PN, I, LN, j, lines[j]))
|
||||
lines[j] = lines[j].substr(cut);
|
||||
}
|
||||
return concatenateLines(lines);
|
||||
}
|
||||
@ -149,17 +151,17 @@ namespace nytl {
|
||||
global_elem_set_t& result)
|
||||
{
|
||||
ASSERT(result.count(filename) == 0, "Repeated element " + filename);
|
||||
std::string P = clement_lstrip(content);
|
||||
rstrip(P);
|
||||
std::string txt = clement_lstrip(content);
|
||||
rstrip(txt);
|
||||
size_t cut = 9999999999999;
|
||||
one_part_update_min_start_wsp_non_empty(P, true, cut);
|
||||
P = one_part_cut_excess_tab(P, true, cut);
|
||||
one_part_update_min_start_wsp_non_empty(txt, 0, 1, cut);
|
||||
txt = one_part_cut_excess_tab(txt, 0, 1, cut);
|
||||
Element& el = result[filename];
|
||||
el.parts = {ElementPart{element_part_types::code}};
|
||||
el.parts[0].when_code.lines = mv(P);
|
||||
el.parts = {ElementPart{}};
|
||||
el.parts[0].when_code.lines = mv(txt);
|
||||
}
|
||||
|
||||
/* This function parses variable type */
|
||||
/* Type parsing frame */
|
||||
struct TPFrame {
|
||||
json::JSON& result;
|
||||
|
||||
@ -206,6 +208,7 @@ namespace nytl {
|
||||
/* From arg name to arg ID */
|
||||
typedef std::map<std::string, size_t> arg_name_list_t;
|
||||
|
||||
/* Expression parsing frame */
|
||||
struct EPFrame {
|
||||
json::JSON& result;
|
||||
|
||||
@ -295,6 +298,7 @@ namespace nytl {
|
||||
return peep(ctx) == syntax.magic_block_end[0];
|
||||
}
|
||||
|
||||
/* Element content parsing frame */
|
||||
struct ECPFrame {
|
||||
enum block_type{
|
||||
gone_for_nothing,
|
||||
@ -322,7 +326,7 @@ namespace nytl {
|
||||
uptr<ECPFrame> toMe(bool returned, ParsingContext& ctx, const TemplaterSettings& syntax, global_elem_set_t& elem_ns) {
|
||||
if (returned) {
|
||||
if (stopped_for == gone_for_for) {
|
||||
assert(result.parts.back().type == element_part_type_t::for_put);
|
||||
assert(result.parts.back().type == ElementPart::p_for_put);
|
||||
if (ret_data_int == 1)
|
||||
result.parts.back().when_for_put.line_feed = false;
|
||||
else if (ret_data_int == 2)
|
||||
@ -344,7 +348,7 @@ namespace nytl {
|
||||
std::string op = make_uppercase(readName(ctx));
|
||||
if (op == "FOR") {
|
||||
result.parts.emplace_back();
|
||||
result.parts.back().type = element_part_type_t::for_put;
|
||||
result.parts.back().type = ElementPart::p_for_put;
|
||||
ElementPart::when_for_put_S& P = result.parts.back().when_for_put;
|
||||
skipWhitespace(ctx);
|
||||
std::string V1 = readName(ctx);
|
||||
@ -387,7 +391,7 @@ namespace nytl {
|
||||
}
|
||||
if (op == "REF") {
|
||||
result.parts.emplace_back();
|
||||
result.parts.back().type = element_part_type_t::ref_put;
|
||||
result.parts.back().type = ElementPart::p_ref_put;
|
||||
ElementPart::when_ref_put_S& P = result.parts.back().when_ref_put;
|
||||
skipWhitespace(ctx);
|
||||
std::string Vn = readName(ctx);
|
||||
@ -411,7 +415,7 @@ namespace nytl {
|
||||
}
|
||||
if (op == "PUT") {
|
||||
result.parts.emplace_back();
|
||||
result.parts.back().type = element_part_type_t::put;
|
||||
result.parts.back().type = ElementPart::p_put;
|
||||
ElementPart::when_put_S& P = result.parts.back().when_put;
|
||||
skipWhitespace(ctx);
|
||||
P.called_element = parse_expression(ctx, local_var_names);
|
||||
@ -427,12 +431,13 @@ namespace nytl {
|
||||
}
|
||||
auto mediocre_operator = [&](const std::string& base_el) -> void {
|
||||
result.parts.emplace_back();
|
||||
result.parts.back().type = element_part_type_t::put;
|
||||
result.parts.back().type = ElementPart::p_put;
|
||||
ElementPart::when_put_S& P = result.parts.back().when_put;
|
||||
P.called_element["V"] = json::JSON(base_el);
|
||||
P.called_element["C"] = json::JSON(json::array);
|
||||
skipWhitespace(ctx);
|
||||
P.passed_arguments = {parse_expression(ctx, local_var_names)};
|
||||
skip_magic_block_end(ctx, syntax);
|
||||
};
|
||||
if (op == "WRITE") {
|
||||
mediocre_operator("str2text");
|
||||
@ -442,27 +447,29 @@ namespace nytl {
|
||||
mediocre_operator("str2code");
|
||||
goto ya_e_ya_h_i_ya_g_d_o;;
|
||||
}
|
||||
auto prepare_to_depart_parts = [&]() {
|
||||
assert(!result.parts.empty());
|
||||
if (result.parts[0].type == ElementPart::p_code)
|
||||
result.parts[0].when_code.lines = clement_lstrip(result.parts[0].when_code.lines);
|
||||
if (result.parts.back().type == ElementPart::p_code)
|
||||
rstrip(result.parts.back().when_code.lines);
|
||||
size_t cut = 999999999999;
|
||||
size_t N = result.parts.size();
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
if (result.parts[i].type == ElementPart::p_code) {
|
||||
one_part_update_min_start_wsp_non_empty(result.parts[i].when_code.lines, i, N, cut);
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
if (result.parts[i].type == ElementPart::p_code) {
|
||||
result.parts[i].when_code.lines = one_part_cut_excess_tab(result.parts[i].when_code.lines, i, N, cut);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (op == "ENDELDEF") {
|
||||
ASSERT(myself == gone_for_nothing, "Unexpected end of element");
|
||||
skip_magic_block_end(ctx, syntax);
|
||||
if (!result.parts.empty()) {
|
||||
if (result.parts[0].type == element_part_type_t::code)
|
||||
result.parts[0].when_code.lines = clement_lstrip(result.parts[0].when_code.lines);
|
||||
if (result.parts.back().type == element_part_type_t::code)
|
||||
rstrip(result.parts.back().when_code.lines);
|
||||
size_t cut = 999999999999;
|
||||
size_t N = result.parts.size();
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
if (result.parts[i].type == element_part_type_t::code) {
|
||||
one_part_update_min_start_wsp_non_empty(result.parts[i].when_code.lines, i == 0, cut);
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
if (result.parts[i].type == element_part_type_t::code) {
|
||||
result.parts[i].when_code.lines = one_part_cut_excess_tab(result.parts[i].when_code.lines, i == 0, cut);
|
||||
}
|
||||
}
|
||||
}
|
||||
prepare_to_depart_parts();
|
||||
return NULL;
|
||||
}
|
||||
if (op == "ENDFOR") {
|
||||
@ -480,10 +487,13 @@ namespace nytl {
|
||||
THROW("Expected LF, NOLF or end of magic block");
|
||||
}
|
||||
skip_magic_block_end(ctx, syntax);
|
||||
prepare_to_depart_parts();
|
||||
return NULL;
|
||||
}
|
||||
if (op == "ENDREF") {
|
||||
assert(myself == gone_for_ref);
|
||||
skip_magic_block_end(ctx, syntax);
|
||||
prepare_to_depart_parts();
|
||||
return NULL;
|
||||
}
|
||||
THROW("Unknown operator. Expected FOR, REF, PUT, WRITE, ROUGHINSERT, ENDELDEF, ENDFOR, ENDREF");
|
||||
|
@ -9,22 +9,25 @@ namespace nytl {
|
||||
std::string result;
|
||||
size_t cur_line_width = 0;
|
||||
|
||||
/* Fix idea: get rid of newlined_somewhere */
|
||||
void append(const std::string& text, size_t wsp_before_newlines, bool& newlined_somewhere) {
|
||||
size_t n = result.size();
|
||||
size_t m = text.size();
|
||||
result.reserve(n + m);
|
||||
for (size_t i = 0; i < m; i++) {
|
||||
result += text[i];
|
||||
if (text[i] == '\n') {
|
||||
newlined_somewhere = true;
|
||||
cur_line_width = 0;
|
||||
// newlined_somewhere = true;
|
||||
|
||||
result.resize(result.size() + wsp_before_newlines, ' ');
|
||||
cur_line_width = wsp_before_newlines;
|
||||
} else {
|
||||
if (cur_line_width == 0 && newlined_somewhere) {
|
||||
result.resize(result.size() + wsp_before_newlines, ' ');
|
||||
cur_line_width = wsp_before_newlines;
|
||||
}
|
||||
// if (cur_line_width == 0 && newlined_somewhere) {
|
||||
// result.resize(result.size() + wsp_before_newlines, ' ');
|
||||
// cur_line_width = wsp_before_newlines;
|
||||
// }
|
||||
cur_line_width++;
|
||||
}
|
||||
result += text[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -88,7 +91,7 @@ namespace nytl {
|
||||
RFrame_OverArray(const ElementPart::when_for_put_S& part, size_t multiline_put_start, const std::vector<LocalVarValue> &saved_args,
|
||||
const std::vector<json::JSON> &arr): RFrame_OverJSON(part, multiline_put_start, saved_args),
|
||||
arr(arr) {
|
||||
if (part.where_key_var < 0)
|
||||
if (part.where_key_var >= 0)
|
||||
additional_json_wrapper = json::JSON(json::Integer(0l));
|
||||
}
|
||||
|
||||
@ -106,7 +109,7 @@ namespace nytl {
|
||||
const std::map<std::string, json::JSON> &dict): RFrame_OverJSON(part, multiline_put_start, saved_args_plus_iter),
|
||||
dict(dict) {
|
||||
it = dict.begin();
|
||||
if (part.where_key_var < 0)
|
||||
if (part.where_key_var >= 0)
|
||||
addition_json_wrapper = json::JSON("");
|
||||
}
|
||||
|
||||
@ -114,6 +117,7 @@ namespace nytl {
|
||||
const std::function<std::string(std::string)> &escape) override;
|
||||
};
|
||||
|
||||
/* Rendering Frame */
|
||||
uptr<RFrame> RFrame_OverParts::toMe(bool returned, const global_elem_set_t &elem_ns, Ditch &result,
|
||||
const std::function<std::string(std::string)> &escape) {
|
||||
if (!returned)
|
||||
@ -147,7 +151,11 @@ namespace nytl {
|
||||
const json::JSON* X = passed_args[0].JSON_subval;
|
||||
assert(X);
|
||||
if (name == "jesc") {
|
||||
append(escape(json::generate_str(*X, json::print_pretty)), result);
|
||||
std::string escaped_json = escape(json::generate_str(*X, json::print_pretty));
|
||||
rstrip(escaped_json);
|
||||
append(escaped_json, result);
|
||||
} else if (name == "jesccomp") {
|
||||
append(escape(json::generate_str(*X, json::print_compact)), result);
|
||||
} else if (name == "str2text") {
|
||||
ASSERT(X->isString(), "str2text takes json string");
|
||||
append(escape(X->asString()), result);
|
||||
@ -161,10 +169,10 @@ namespace nytl {
|
||||
if (part_to_do == el.parts.size())
|
||||
return NULL;
|
||||
const ElementPart& cur_part = el.parts[part_to_do++];
|
||||
if (cur_part.type == element_part_types::code) {
|
||||
if (cur_part.type == ElementPart::p_code) {
|
||||
const ElementPart::when_code_S& pt = cur_part.when_code;
|
||||
append(pt.lines, result);
|
||||
} else if (cur_part.type == element_part_types::put) {
|
||||
} else if (cur_part.type == ElementPart::p_put) {
|
||||
const ElementPart::when_put_S& pt = cur_part.when_put;
|
||||
LocalVarValue called_element_expv = rendering_core_execute_expression(elem_ns, passed_args, pt.called_element);
|
||||
ASSERT(!called_element_expv.is_json, "Can't PUT json variable");
|
||||
@ -174,7 +182,7 @@ namespace nytl {
|
||||
passed_arguments_expv[i] = rendering_core_execute_expression(elem_ns, passed_args, pt.passed_arguments[i]);
|
||||
return std::make_unique<RFrame_OverParts>(called_element_expv.EL_name, passed_arguments_expv,
|
||||
result.cur_line_width);
|
||||
} else if (cur_part.type == element_part_types::for_put) {
|
||||
} else if (cur_part.type == ElementPart::p_for_put) {
|
||||
const ElementPart::when_for_put_S& pt = cur_part.when_for_put;
|
||||
LocalVarValue iting_over = rendering_core_execute_expression(elem_ns, passed_args, pt.ref_over);
|
||||
ASSERT(iting_over.is_json, "Can't iterate over element");
|
||||
@ -185,7 +193,7 @@ namespace nytl {
|
||||
return std::make_unique<RFrame_OverDictionary>(pt, result.cur_line_width, passed_args, container.asDictionary());
|
||||
} else
|
||||
THROW("Can't iterate over non-natalistic jsobject");
|
||||
} else if (cur_part.type == element_part_types::ref_put) {
|
||||
} else if (cur_part.type == ElementPart::p_ref_put) {
|
||||
const ElementPart::when_ref_put_S& pt = cur_part.when_ref_put;
|
||||
std::vector<LocalVarValue> more_variables(passed_args.size() + 1);
|
||||
std::copy(passed_args.begin(), passed_args.end(), more_variables.begin());
|
||||
@ -212,10 +220,10 @@ namespace nytl {
|
||||
}
|
||||
|
||||
uptr<RFrame> RFrame_OverDictionary::toMe(bool returned, RFrame_passed) {
|
||||
if (returned && part.line_feed)
|
||||
append("\n", result);
|
||||
if (it == dict.end())
|
||||
return NULL;
|
||||
if (returned && part.line_feed)
|
||||
append("\n", result);
|
||||
if (part.where_key_var > -1) {
|
||||
addition_json_wrapper.asString() = it->first;
|
||||
saved_args_plus_iter[part.where_key_var] = {true, "", &addition_json_wrapper};
|
||||
@ -227,18 +235,17 @@ namespace nytl {
|
||||
return std::make_unique<RFrame_OverParts>(part.internal_element, saved_args_plus_iter, wsp_before_newlines);
|
||||
}
|
||||
|
||||
std::string rendering_core(const std::string& entry_func, const std::vector<json::JSON>& entry_arguments,
|
||||
std::string rendering_core(const std::string& entry_func, const std::vector<const json::JSON*>& entry_arguments,
|
||||
const global_elem_set_t& elem_ns, const std::function<std::string(std::string)>& escape)
|
||||
{
|
||||
Ditch result;
|
||||
|
||||
std::vector<uptr<RFrame>> stack;
|
||||
|
||||
{
|
||||
size_t AN = entry_arguments.size();
|
||||
std::vector<LocalVarValue> entry_arguments_conv(AN);
|
||||
for (size_t i = 0; i < AN; i++)
|
||||
entry_arguments_conv[i] = {true, "", &entry_arguments[i]};
|
||||
entry_arguments_conv[i] = {true, "", entry_arguments[i]};
|
||||
stack.push_back(std::make_unique<RFrame_OverParts>(entry_func, entry_arguments_conv, 0));
|
||||
}
|
||||
bool returned = false;
|
||||
|
@ -112,7 +112,10 @@ namespace nytl {
|
||||
void Templater::update() {
|
||||
elements = {
|
||||
{"jesc", Element{{json::JSON(true)}, true}},
|
||||
{"jesccomp", Element{{json::JSON(true)}, true}},
|
||||
/* str2text base element has a dedicated operator - WRITE */
|
||||
{"str2text", Element{{json::JSON(true)}, true}},
|
||||
/* str2code base element has a dedicated operator - ROUGHINSERT */
|
||||
{"str2code", Element{{json::JSON(true)}, true}},
|
||||
};
|
||||
std::vector<InterestingFile> intersting_files = indexing_detour(settings.det);
|
||||
@ -127,7 +130,7 @@ namespace nytl {
|
||||
}
|
||||
|
||||
/* Still can throw some stuff derived from std::exception (like bad alloc) */
|
||||
std::string Templater::render(const std::string& element, const std::vector<json::JSON> &arguments) const {
|
||||
std::string Templater::render(const std::string& element, const std::vector<const json::JSON*> &arguments) const {
|
||||
ASSERT(is_uname_dotted_sequence(element), "Incorrect entry element name");
|
||||
return rendering_core(element, arguments, elements, settings.escape);
|
||||
}
|
||||
|
@ -10,21 +10,15 @@
|
||||
namespace nytl {
|
||||
typedef json::JSON expression_t;
|
||||
|
||||
namespace element_part_types {
|
||||
enum element_part_type_E {
|
||||
code,
|
||||
/* write statements really mean PUT str2text X */
|
||||
put,
|
||||
for_put,
|
||||
ref_put
|
||||
};
|
||||
}
|
||||
|
||||
typedef element_part_types::element_part_type_E element_part_type_t;
|
||||
|
||||
struct ElementPart {
|
||||
/* Used with all types */
|
||||
element_part_type_t type = element_part_types::code;
|
||||
enum element_part_type_E {
|
||||
p_code,
|
||||
/* write statements really mean PUT str2text X */
|
||||
p_put,
|
||||
p_for_put,
|
||||
p_ref_put
|
||||
} type = p_code;
|
||||
struct when_code_S {
|
||||
std::string lines;
|
||||
} when_code;
|
||||
@ -80,7 +74,7 @@ namespace nytl {
|
||||
void update();
|
||||
|
||||
/* Throws exception, derived from std::exception */
|
||||
std::string render(const std::string& element, const std::vector<json::JSON>& arguments) const;
|
||||
std::string render(const std::string& element, const std::vector<const json::JSON*>& arguments) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
{% ELDEF main %}
|
||||
AAAAAAAA
|
||||
|
||||
CCC
|
||||
DDD
|
||||
|
||||
|
||||
{% ENDELDEF %}
|
9
src/http_server/nytl_tests/HypertextPages/test.nytl.html
Normal file
9
src/http_server/nytl_tests/HypertextPages/test.nytl.html
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
{% ELDEF main JSON cba %}
|
||||
AAA
|
||||
{% FOR _:val IN cba %}
|
||||
TUTUTUTUTUTUTUTUN {% PUT jesccomp val %}
|
||||
{% ENDFOR %}
|
||||
|
||||
{% ENDELDEF %}
|
@ -1,6 +1,6 @@
|
||||
#include <jsonincpp/string_representation.h>
|
||||
#include <new_york_transit_line/templater.h>
|
||||
|
||||
/* Yep, tests for nytl depend on assets for website. Yep, I see no problem with that */
|
||||
#include <new_york_transit_line/core.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
@ -11,10 +11,17 @@ int main(int argc, char** argv) {
|
||||
std::string dir_path = argv[1];
|
||||
nytl::Templater templater(nytl::TemplaterSettings{nytl::TemplaterDetourRules{dir_path}});
|
||||
templater.update();
|
||||
std::string answer = templater.render("list-rooms", {});
|
||||
printf("%s\n<a><f><t><e><r><><l><f>\n", answer.c_str());
|
||||
std::string answer2 = templater.render("test", {});
|
||||
printf("%s\n<a><f><t><e><r><><l><f>\n", answer.c_str());
|
||||
nytl::debug_print_templater(templater);
|
||||
json::JSON cba;
|
||||
cba["boba"] = json::JSON("<>");
|
||||
cba["arr"][0] = json::JSON("zero");
|
||||
cba["arr"][1] = json::JSON("one");
|
||||
cba["arr"][2] = json::JSON("two");
|
||||
// printf("DEBUG WAS: %p\n", &cba["boba"].g());
|
||||
// printf("%s\n", json::generate_str(cba["boba"].g(), json::print_compact).c_str());
|
||||
// return 0;
|
||||
std::string answer2 = templater.render("test", {&cba});
|
||||
printf("%s\n<a><f><t><e><r><><l><f>\n", answer2.c_str());
|
||||
|
||||
return 0;
|
||||
}
|
@ -10,6 +10,8 @@
|
||||
#include <engine_engine_number_9/form_data_structure/urlencoded_query.h>
|
||||
#include <new_york_transit_line/templater.h>
|
||||
|
||||
#include "../http_server/engine_engine_number_9/running_mainloop.h"
|
||||
|
||||
bool termination = false;
|
||||
|
||||
void sigterm_action(int) {
|
||||
@ -17,7 +19,7 @@ void sigterm_action(int) {
|
||||
}
|
||||
|
||||
void usage(char** argv) {
|
||||
printf("Usage: %s <file with settings> <assets folder>\n", argv[0]);
|
||||
printf("Usage: %s <file with settings>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -32,30 +34,26 @@ std::string unsafe_client_request_stringification(const een9::ClientRequest& req
|
||||
}
|
||||
|
||||
int main(int argc, char** argv){
|
||||
printf("%s\n", regexis024::opcode_to_str(regexis024::opcode_t::DIE));
|
||||
try {
|
||||
een9_ASSERT_pl(argc > 0);
|
||||
if (argc < 1 + 2)
|
||||
if (argc < 1 + 1)
|
||||
usage(argv);
|
||||
if (!een9::isRegularFile(argv[1]) || !een9::endsIn(argv[1], ".json")) {
|
||||
printf("\"%s\" is not a json file\n", argv[1]);
|
||||
usage(argv);
|
||||
}
|
||||
std::string config_file = argv[1];
|
||||
if (!een9::isDirectory(argv[2])) {
|
||||
printf("\"%s\" is not a directory\n", argv[2]);
|
||||
usage(argv);
|
||||
}
|
||||
std::string assets_dir = argv[2];
|
||||
|
||||
std::string config_text;
|
||||
een9::readFile(config_file, config_text);
|
||||
json::JSON config = json::parse_str_flawless(config_text);
|
||||
een9_ASSERT(config.isDictionary(), "config root is not dictionary");
|
||||
een9_ASSERT(config["assets"].g().isString(), "config[\"\assets\"] is not string");
|
||||
std::string assets_dir = config["assets"].g().asString();
|
||||
een9_ASSERT(een9::isDirectory(assets_dir), "\"" + assets_dir + "\" is not a directory");
|
||||
|
||||
een9::StaticAssetManagerSlaveModule samI;
|
||||
samI.update({
|
||||
een9::StaticAssetManagerRule{assets_dir + "/HypertextPages", "/assets/html", {{".html", "text/html"}} },
|
||||
een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} },
|
||||
een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} },
|
||||
een9::StaticAssetManagerRule{assets_dir + "/img", "/assets/img", {
|
||||
@ -63,31 +61,47 @@ int main(int argc, char** argv){
|
||||
} },
|
||||
});
|
||||
|
||||
json::JSON& config_presentation = config["presentation"].g();
|
||||
|
||||
/* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */
|
||||
std::vector<std::unique_ptr<nytl::Templater>> templaters_copies(8);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
templaters_copies[i] = std::make_unique<nytl::Templater>(
|
||||
nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}});
|
||||
templaters_copies[i]->update();
|
||||
}
|
||||
|
||||
// printf("%s\n", templaters_copies[0]->render("list-rooms", {&config_presentation}).c_str());
|
||||
// return 0;
|
||||
|
||||
een9::MainloopParameters params;
|
||||
params.guest_core = [&samI](const een9::SlaveTask& task, const een9::ClientRequest& req) -> std::string {
|
||||
params.guest_core = [&samI, &templaters_copies, config_presentation]
|
||||
(const een9::SlaveTask& task, const een9::ClientRequest& req, een9::worker_id_t worker_id) -> std::string {
|
||||
een9_ASSERT_pl(0 <= worker_id && worker_id < templaters_copies.size());
|
||||
nytl::Templater& templater = *templaters_copies[worker_id];
|
||||
een9::StaticAsset sa;
|
||||
int ret;
|
||||
// printf("%s", unsafe_client_request_stringification(req).c_str());
|
||||
if (req.uri_path == "/output") {
|
||||
std::string text = unsafe_client_request_stringification(req);
|
||||
return een9::form_http_server_response_200("text/plain", text);
|
||||
}
|
||||
auto rteee = [&](const std::string& asset_path) -> std::string {
|
||||
ret = samI.get_asset(asset_path, sa);
|
||||
een9_ASSERT_pl(ret == 0);
|
||||
return een9::form_http_server_response_200(sa.type, sa.content);
|
||||
// if (req.uri_path == "/output") {
|
||||
// std::string text = unsafe_client_request_stringification(req);
|
||||
// return een9::form_http_server_response_200("text/plain", text);
|
||||
// }
|
||||
auto rteee = [&](const std::string& el_name, bool pass_phr) -> std::string {
|
||||
std::string page = templater.render(el_name,
|
||||
pass_phr ? std::vector<const json::JSON*>{&config_presentation} : std::vector<const json::JSON*>{});
|
||||
return een9::form_http_server_response_200("text/html", page);
|
||||
};
|
||||
if (req.uri_path == "/" || req.uri_path == "/list-rooms") {
|
||||
return rteee("/assets/html/list-rooms.html");
|
||||
return rteee("list-rooms", true);
|
||||
}
|
||||
if (req.uri_path == "/chat") {
|
||||
return rteee("/assets/html/chat.html");
|
||||
return rteee("chat", false);
|
||||
}
|
||||
if (req.uri_path == "/profile") {
|
||||
return rteee("/assets/html/profile.html");
|
||||
return rteee("profile", false);
|
||||
}
|
||||
if (req.uri_path == "/registration") {
|
||||
return rteee("/assets/html/registration.html");
|
||||
return rteee("registration", false);
|
||||
}
|
||||
/* Trying to interpret request as asset lookup */
|
||||
ret = samI.get_asset(req.uri_path, sa);
|
||||
@ -96,6 +110,7 @@ int main(int argc, char** argv){
|
||||
}
|
||||
return een9::form_http_server_response_404("text/html", "<h1> Not found! </h1>");
|
||||
};
|
||||
|
||||
params.ports_to_listen = {1025};
|
||||
params.slave_number = 8;
|
||||
params.open_admin_listener = false;
|
||||
|
Loading…
Reference in New Issue
Block a user