optimize
This commit is contained in:
parent
61a700479d
commit
244477f0a0
20 changed files with 140 additions and 231 deletions
|
@ -15,7 +15,6 @@ set(SRC
|
||||||
state/outside_section.cpp
|
state/outside_section.cpp
|
||||||
visitor/is_node_empty.cpp
|
visitor/is_node_empty.cpp
|
||||||
visitor/render_node.cpp
|
visitor/render_node.cpp
|
||||||
visitor/render_section.cpp
|
visitor/render_section.cpp)
|
||||||
visitor/to_json.cpp)
|
|
||||||
|
|
||||||
add_library(mstch STATIC ${SRC})
|
add_library(mstch STATIC ${SRC})
|
||||||
|
|
|
@ -1,32 +1,37 @@
|
||||||
#include "render_context.hpp"
|
#include "render_context.hpp"
|
||||||
#include "state/outside_section.hpp"
|
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
#include "state/outside_section.hpp"
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
using namespace mstch;
|
using namespace mstch;
|
||||||
|
|
||||||
const mstch::node render_context::null_node;
|
const mstch::node render_context::null_node;
|
||||||
|
|
||||||
render_context::render_context(
|
render_context::push::push(render_context& context, const mstch::object& obj):
|
||||||
const mstch::object& object,
|
context(context)
|
||||||
const std::map<std::string,std::string>& partials):
|
|
||||||
partials(partials),
|
|
||||||
objects{object},
|
|
||||||
state(new state::outside_section)
|
|
||||||
{
|
{
|
||||||
for(auto& partial: this->partials)
|
context.objects.push_front(obj);
|
||||||
partial.second = strip_whitespace(partial.second);
|
context.push_state<state::outside_section>();
|
||||||
|
}
|
||||||
|
|
||||||
|
render_context::push::~push() {
|
||||||
|
context.objects.pop_front();
|
||||||
|
context.state.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string render_context::push::render(const std::string& tmplt) {
|
||||||
|
return context.render(tmplt);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_context::render_context(
|
render_context::render_context(
|
||||||
const mstch::object& object,
|
const mstch::object& object,
|
||||||
const render_context& context):
|
const std::map<std::string,std::string>& partials):
|
||||||
partials(context.partials),
|
partials{partials},
|
||||||
objects(context.objects),
|
objects{object}
|
||||||
state(new state::outside_section)
|
|
||||||
{
|
{
|
||||||
objects.push_front(object);
|
push_state<state::outside_section>();
|
||||||
|
for(auto& partial: this->partials)
|
||||||
|
partial.second = strip_whitespace(partial.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mstch::node& render_context::find_node(
|
const mstch::node& render_context::find_node(
|
||||||
|
@ -55,7 +60,7 @@ std::string render_context::render(const std::string& t) {
|
||||||
auto re = std::regex("\\{{2}[^\\}]*\\}{2}|\\{{3}[^\\}]*\\}{3}");
|
auto re = std::regex("\\{{2}[^\\}]*\\}{2}|\\{{3}[^\\}]*\\}{3}");
|
||||||
std::sregex_token_iterator it(t.begin(), t.end(), re, {-1, 0});
|
std::sregex_token_iterator it(t.begin(), t.end(), re, {-1, 0});
|
||||||
for (; it != std::sregex_token_iterator(); ++it)
|
for (; it != std::sregex_token_iterator(); ++it)
|
||||||
output << state->render(*this, token(it->str()));
|
output << state.top()->render(*this, token(it->str()));
|
||||||
return output.str();
|
return output.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
#include "mstch/mstch.hpp"
|
#include "mstch/mstch.hpp"
|
||||||
#include "state/render_state.hpp"
|
#include "state/render_state.hpp"
|
||||||
|
@ -17,22 +18,35 @@ namespace mstch {
|
||||||
const std::deque<object>& current_objects);
|
const std::deque<object>& current_objects);
|
||||||
std::map<std::string,std::string> partials;
|
std::map<std::string,std::string> partials;
|
||||||
std::deque<mstch::object> objects;
|
std::deque<mstch::object> objects;
|
||||||
std::unique_ptr<state::render_state> state;
|
std::stack<std::unique_ptr<state::render_state>> state;
|
||||||
|
template<class T, class... Args>
|
||||||
|
void push_state(Args&&... args) {
|
||||||
|
state.push(std::unique_ptr<state::render_state>(
|
||||||
|
new T(std::forward<Args>(args)...)));
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
|
class push {
|
||||||
|
private:
|
||||||
|
render_context& context;
|
||||||
|
public:
|
||||||
|
push(render_context& context, const mstch::object& obj = {});
|
||||||
|
~push();
|
||||||
|
std::string render(const std::string& tmplt);
|
||||||
|
};
|
||||||
render_context(
|
render_context(
|
||||||
const mstch::object& object,
|
const mstch::object& object,
|
||||||
const std::map<std::string,std::string>& partials);
|
const std::map<std::string,std::string>& partials);
|
||||||
render_context(
|
|
||||||
const mstch::object& object, const render_context& context);
|
|
||||||
const mstch::node& get_node(const std::string& token);
|
const mstch::node& get_node(const std::string& token);
|
||||||
std::string render(const std::string& tmplt);
|
std::string render(const std::string& tmplt);
|
||||||
std::string render_partial(const std::string& partial_name);
|
std::string render_partial(const std::string& partial_name);
|
||||||
template<class T, class... Args>
|
template<class T, class... Args>
|
||||||
void set_state(Args&&... args) {
|
void set_state(Args&&... args) {
|
||||||
state = std::unique_ptr<state::render_state>(
|
state.top() = std::unique_ptr<state::render_state>(
|
||||||
new T(std::forward<Args>(args)...));
|
new T(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //_MSTCH_RENDER_CONTEXT_H_
|
#endif //_MSTCH_RENDER_CONTEXT_H_
|
||||||
|
|
|
@ -1,46 +1,41 @@
|
||||||
#include "visitor/render_section.hpp"
|
|
||||||
#include "visitor/to_json.hpp"
|
|
||||||
#include "visitor/is_node_empty.hpp"
|
|
||||||
#include "in_inverted_section.hpp"
|
#include "in_inverted_section.hpp"
|
||||||
#include "outside_section.hpp"
|
#include "outside_section.hpp"
|
||||||
#include "render_context.hpp"
|
#include "visitor/render_section.hpp"
|
||||||
|
#include "visitor/is_node_empty.hpp"
|
||||||
|
|
||||||
using namespace mstch;
|
using namespace mstch;
|
||||||
|
|
||||||
state::in_inverted_section::in_inverted_section(
|
state::in_inverted_section::in_inverted_section(
|
||||||
const std::string& section_name):
|
const std::string& section_name):
|
||||||
section_name(section_name),
|
section_name(section_name), skipped_openings(0)
|
||||||
skipped_openings(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string state::in_inverted_section::render(
|
std::string state::in_inverted_section::render(
|
||||||
render_context& ctx,
|
render_context& ctx, const token& token)
|
||||||
const token& token)
|
|
||||||
{
|
{
|
||||||
switch(token.type()) {
|
switch(token.token_type()) {
|
||||||
case token_type::section_close:
|
case token::type::section_close:
|
||||||
if(token.content() == section_name && skipped_openings == 0) {
|
if(token.content() == section_name && skipped_openings == 0) {
|
||||||
std::ostringstream out;
|
std::string out;
|
||||||
auto& section_node = ctx.get_node(section_name);
|
auto& section_node = ctx.get_node(section_name);
|
||||||
if(boost::apply_visitor(visitor::is_node_empty(), section_node))
|
if(boost::apply_visitor(visitor::is_node_empty(), section_node))
|
||||||
out << render_context(mstch::object{}, ctx)
|
out = render_context::push(ctx).render(section_text.str());
|
||||||
.render(section_text.str());
|
|
||||||
ctx.set_state<outside_section>();
|
ctx.set_state<outside_section>();
|
||||||
return out.str();
|
return out;
|
||||||
} else {
|
} else {
|
||||||
skipped_openings--;
|
skipped_openings--;
|
||||||
section_text << token.raw();
|
section_text << token.raw();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case token_type::inverted_section_open:
|
case token::type::inverted_section_open:
|
||||||
case token_type::section_open:
|
case token::type::section_open:
|
||||||
skipped_openings++;
|
skipped_openings++;
|
||||||
case token_type::text:
|
case token::type::text:
|
||||||
case token_type::variable:
|
case token::type::variable:
|
||||||
case token_type::unescaped_variable:
|
case token::type::unescaped_variable:
|
||||||
case token_type::comment:
|
case token::type::comment:
|
||||||
case token_type::partial:
|
case token::type::partial:
|
||||||
section_text << token.raw();
|
section_text << token.raw();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,7 @@ namespace mstch {
|
||||||
public:
|
public:
|
||||||
in_inverted_section(const std::string §ion_name);
|
in_inverted_section(const std::string §ion_name);
|
||||||
std::string render(
|
std::string render(
|
||||||
render_context &context,
|
render_context &context, const token &token) override;
|
||||||
const token &token) override;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "visitor/is_node_empty.hpp"
|
|
||||||
#include "visitor/render_section.hpp"
|
|
||||||
#include "in_section.hpp"
|
#include "in_section.hpp"
|
||||||
#include "outside_section.hpp"
|
#include "outside_section.hpp"
|
||||||
|
#include "visitor/is_node_empty.hpp"
|
||||||
|
#include "visitor/render_section.hpp"
|
||||||
|
|
||||||
using namespace mstch;
|
using namespace mstch;
|
||||||
|
|
||||||
|
@ -10,15 +10,12 @@ state::in_section::in_section(const std::string& section_name):
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string state::in_section::render(
|
std::string state::in_section::render(render_context& ctx, const token& token) {
|
||||||
render_context& ctx,
|
switch(token.token_type()) {
|
||||||
const token& token)
|
case token::type::section_close:
|
||||||
{
|
|
||||||
switch(token.type()) {
|
|
||||||
case token_type::section_close:
|
|
||||||
if(token.content() == section_name && skipped_openings == 0) {
|
if(token.content() == section_name && skipped_openings == 0) {
|
||||||
auto section_node = ctx.get_node(section_name);
|
auto section_node = ctx.get_node(section_name);
|
||||||
std::string out("");
|
std::string out;
|
||||||
if (!boost::apply_visitor(visitor::is_node_empty(), section_node))
|
if (!boost::apply_visitor(visitor::is_node_empty(), section_node))
|
||||||
out = boost::apply_visitor(
|
out = boost::apply_visitor(
|
||||||
visitor::render_section(ctx, section_text.str()),
|
visitor::render_section(ctx, section_text.str()),
|
||||||
|
@ -30,14 +27,14 @@ std::string state::in_section::render(
|
||||||
section_text << token.raw();
|
section_text << token.raw();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case token_type::inverted_section_open:
|
case token::type::inverted_section_open:
|
||||||
case token_type::section_open:
|
case token::type::section_open:
|
||||||
skipped_openings++;
|
skipped_openings++;
|
||||||
case token_type::text:
|
case token::type::text:
|
||||||
case token_type::variable:
|
case token::type::variable:
|
||||||
case token_type::unescaped_variable:
|
case token::type::unescaped_variable:
|
||||||
case token_type::comment:
|
case token::type::comment:
|
||||||
case token_type::partial:
|
case token::type::partial:
|
||||||
section_text << token.raw();
|
section_text << token.raw();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,7 @@ namespace mstch {
|
||||||
public:
|
public:
|
||||||
in_section(const std::string& section_name);
|
in_section(const std::string& section_name);
|
||||||
std::string render(
|
std::string render(
|
||||||
render_context& context,
|
render_context& context, const token& token) override;
|
||||||
const token& token) override;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,32 +7,29 @@
|
||||||
using namespace mstch;
|
using namespace mstch;
|
||||||
|
|
||||||
std::string state::outside_section::render(
|
std::string state::outside_section::render(
|
||||||
render_context& ctx,
|
render_context& ctx, const token& token)
|
||||||
const token& token)
|
|
||||||
{
|
{
|
||||||
switch(token.type()) {
|
switch(token.token_type()) {
|
||||||
case token_type::section_open:
|
case token::type::section_open:
|
||||||
ctx.set_state<in_section>(token.content());
|
ctx.set_state<in_section>(token.content());
|
||||||
break;
|
break;
|
||||||
case token_type::inverted_section_open:
|
case token::type::inverted_section_open:
|
||||||
ctx.set_state<in_inverted_section>(token.content());
|
ctx.set_state<in_inverted_section>(token.content());
|
||||||
break;
|
break;
|
||||||
case token_type::variable:
|
case token::type::variable:
|
||||||
case token_type::unescaped_variable: {
|
case token::type::unescaped_variable: {
|
||||||
std::set<visitor::render_node::flag> flags{};
|
std::set<visitor::render_node::flag> flags{};
|
||||||
if (token.type() == token_type::variable)
|
if (token.token_type() == token::type::variable)
|
||||||
flags.insert(visitor::render_node::flag::escape_html);
|
flags.insert(visitor::render_node::flag::escape_html);
|
||||||
return boost::apply_visitor(
|
return boost::apply_visitor(
|
||||||
visitor::render_node(flags), ctx.get_node(token.content()));
|
visitor::render_node(flags), ctx.get_node(token.content()));
|
||||||
}
|
}
|
||||||
case token_type::comment: break;
|
case token::type::comment: break;
|
||||||
case token_type::text:
|
case token::type::text:
|
||||||
return token.raw();
|
return token.raw();
|
||||||
case token_type::partial:
|
case token::type::partial:
|
||||||
return ctx.render_partial(token.content());
|
return ctx.render_partial(token.content());
|
||||||
case token_type::section_close:
|
case token::type::section_close: break;
|
||||||
// TODO ERROR
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,7 @@ namespace mstch {
|
||||||
class outside_section: public render_state {
|
class outside_section: public render_state {
|
||||||
public:
|
public:
|
||||||
std::string render(
|
std::string render(
|
||||||
render_context &context,
|
render_context &context, const token &token) override;
|
||||||
const token &token) override;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,7 @@ namespace mstch {
|
||||||
public:
|
public:
|
||||||
virtual ~render_state() {}
|
virtual ~render_state() {}
|
||||||
virtual std::string render(
|
virtual std::string render(
|
||||||
render_context& context,
|
render_context& context, const token& token) = 0;
|
||||||
const token& token) = 0;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,46 +6,41 @@
|
||||||
|
|
||||||
using namespace mstch;
|
using namespace mstch;
|
||||||
|
|
||||||
|
std::tuple<int,int,token::type> token::token_info(const std::string& inside) {
|
||||||
|
switch (inside.at(0)) {
|
||||||
|
case '>': return std::make_tuple(1, 0, type::partial);
|
||||||
|
case '^': return std::make_tuple(1, 0, type::inverted_section_open);
|
||||||
|
case '/': return std::make_tuple(1, 0, type::section_close);
|
||||||
|
case '&': return std::make_tuple(1, 0, type::unescaped_variable);
|
||||||
|
case '#': return std::make_tuple(1, 0, type::section_open);
|
||||||
|
case '{':
|
||||||
|
if (inside.at(inside.size() - 1) == '}')
|
||||||
|
return std::make_tuple(1, 1, type::unescaped_variable);
|
||||||
|
else
|
||||||
|
return std::make_tuple(0, 0, type::variable);
|
||||||
|
case '!': return std::make_tuple(1, 0, type::comment);
|
||||||
|
default: return std::make_tuple(0, 0, type::variable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
token::token(const std::string& raw_token): raw_val(raw_token) {
|
token::token(const std::string& raw_token): raw_val(raw_token) {
|
||||||
std::regex token_match("\\{{2}[^\\}]*\\}{2}|\\{{3}[^\\}]*\\}{3}");
|
std::regex token_match("\\{{2}[^\\}]*\\}{2}|\\{{3}[^\\}]*\\}{3}");
|
||||||
if(std::regex_match(raw_token, token_match)) {
|
if(std::regex_match(raw_token, token_match)) {
|
||||||
std::string inside = raw_token.substr(2, raw_token.size() - 4);
|
std::string inside{raw_token.substr(2, raw_token.size() - 4)};
|
||||||
boost::trim(inside);
|
boost::trim(inside);
|
||||||
if (inside.size() > 0 && inside.at(0) == '#') {
|
if (inside.size() > 0) {
|
||||||
type_val = token_type::section_open;
|
int lpad, rpad;
|
||||||
content_val = inside.substr(1);
|
std::tie(lpad, rpad, type_val) = token_info(inside);
|
||||||
} else if (inside.size() > 0 && inside.at(0) == '>') {
|
content_val = inside.substr(lpad, inside.size() - lpad - rpad);
|
||||||
type_val = token_type::partial;
|
|
||||||
content_val = inside.substr(1);
|
|
||||||
} else if (inside.size() > 0 && inside.at(0) == '^') {
|
|
||||||
type_val = token_type::inverted_section_open;
|
|
||||||
content_val = inside.substr(1);
|
|
||||||
} else if (inside.size() > 0 && inside.at(0) == '/') {
|
|
||||||
type_val = token_type::section_close;
|
|
||||||
content_val = inside.substr(1);
|
|
||||||
} else if (inside.size() > 0 && inside.at(0) == '&') {
|
|
||||||
type_val = token_type::unescaped_variable;
|
|
||||||
content_val = inside.substr(1);
|
|
||||||
} else if (inside.size() > 0 && inside.at(0) == '{' &&
|
|
||||||
inside.at(inside.size() - 1) == '}')
|
|
||||||
{
|
|
||||||
type_val = token_type::unescaped_variable;
|
|
||||||
content_val = inside.substr(1, inside.size() - 2);
|
|
||||||
} else if (inside.size() > 0 && inside.at(0) == '!') {
|
|
||||||
type_val = token_type::comment;
|
|
||||||
content_val = inside.substr(1);
|
|
||||||
} else {
|
|
||||||
type_val = token_type::variable;
|
|
||||||
content_val = inside;
|
|
||||||
}
|
|
||||||
boost::trim(content_val);
|
boost::trim(content_val);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
type_val = token_type::text;
|
type_val = type::text;
|
||||||
content_val = raw_token;
|
content_val = raw_token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
token_type token::type() const {
|
token::type token::token_type() const {
|
||||||
return type_val;
|
return type_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,20 +4,20 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace mstch {
|
namespace mstch {
|
||||||
enum class token_type {
|
class token {
|
||||||
|
public:
|
||||||
|
enum class type {
|
||||||
text, variable, section_open, section_close, inverted_section_open,
|
text, variable, section_open, section_close, inverted_section_open,
|
||||||
unescaped_variable, comment, partial
|
unescaped_variable, comment, partial
|
||||||
};
|
};
|
||||||
|
|
||||||
class token {
|
|
||||||
private:
|
private:
|
||||||
token_type type_val;
|
type type_val;
|
||||||
std::string content_val;
|
std::string content_val;
|
||||||
std::string raw_val;
|
std::string raw_val;
|
||||||
|
std::tuple<int,int,type> token_info(const std::string& inside);
|
||||||
public:
|
public:
|
||||||
token(const std::string& raw_token);
|
token(const std::string& raw_token);
|
||||||
token_type type() const;
|
type token_type() const;
|
||||||
std::string content() const;
|
std::string content() const;
|
||||||
std::string raw() const;
|
std::string raw() const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,22 +3,18 @@
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
|
|
||||||
std::string mstch::strip_whitespace(std::string tmplt) {
|
std::string mstch::strip_whitespace(const std::string& tmplt) {
|
||||||
std::regex comment_match("\\{\\{![^\\}]*\\}\\}");
|
std::regex comment_match("\\{\\{![^\\}]*\\}\\}");
|
||||||
tmplt = std::regex_replace(tmplt, comment_match, "{{!}}");
|
|
||||||
std::ostringstream out;
|
|
||||||
std::istringstream in(tmplt);
|
|
||||||
std::string line;
|
|
||||||
std::regex tag_match("\\{{2}[ ]*[#|/|^|!|>]{1}[^\\}]*\\}{2}");
|
std::regex tag_match("\\{{2}[ ]*[#|/|^|!|>]{1}[^\\}]*\\}{2}");
|
||||||
std::regex whitespace_match("^\\s*$");
|
std::regex whitespace_match("^\\s*$");
|
||||||
while (std::getline(in, line)) {
|
std::ostringstream out;
|
||||||
|
std::istringstream in(std::regex_replace(tmplt, comment_match, "{{!}}"));
|
||||||
|
for(std::string line; std::getline(in, line);) {
|
||||||
std::string no_tags = std::regex_replace(line, tag_match, "");
|
std::string no_tags = std::regex_replace(line, tag_match, "");
|
||||||
if (no_tags != line && std::regex_match(no_tags, whitespace_match)) {
|
if (no_tags != line && std::regex_match(no_tags, whitespace_match))
|
||||||
out << std::regex_replace(line, std::regex("\\s"), "");
|
out << std::regex_replace(line, std::regex("\\s"), "");
|
||||||
} else {
|
else
|
||||||
out << line;
|
out << line << (in.eof()?"":"\n");
|
||||||
if(!in.eof()) out << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace mstch {
|
namespace mstch {
|
||||||
std::string strip_whitespace(std::string tmplt);
|
std::string strip_whitespace(const std::string& tmplt);
|
||||||
std::string html_escape(std::string str);
|
std::string html_escape(std::string str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,9 @@ bool visitor::is_node_empty::operator()(const object& obj) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool visitor::is_node_empty::operator()(const string_lambda& lambda) const {
|
bool visitor::is_node_empty::operator()(const string_lambda& lambda) const {
|
||||||
return false; // TODO
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool visitor::is_node_empty::operator()(const renderer_lambda& lambda) const {
|
bool visitor::is_node_empty::operator()(const renderer_lambda& lambda) const {
|
||||||
return false; // TODO
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,7 @@
|
||||||
|
|
||||||
using namespace mstch;
|
using namespace mstch;
|
||||||
|
|
||||||
visitor::render_node::render_node(std::set<flag> flags):
|
visitor::render_node::render_node(std::set<flag> flags): flags(flags) {
|
||||||
flags(flags)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string visitor::render_node::operator()(const boost::blank& blank) const {
|
std::string visitor::render_node::operator()(const boost::blank& blank) const {
|
||||||
|
|
|
@ -1,49 +1,43 @@
|
||||||
#include "render_section.hpp"
|
#include "render_section.hpp"
|
||||||
#include "is_node_empty.hpp"
|
|
||||||
|
|
||||||
using namespace mstch;
|
using namespace mstch;
|
||||||
|
|
||||||
visitor::render_section::render_section(
|
visitor::render_section::render_section(
|
||||||
render_context& context,
|
render_context& ctx, const std::string& section, std::set<flag> flags):
|
||||||
const std::string& section,
|
ctx(ctx), section(section), flags(flags)
|
||||||
std::set<flag> flags):
|
|
||||||
context(context),
|
|
||||||
section(section),
|
|
||||||
flags(flags)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string visitor::render_section::operator()(
|
std::string visitor::render_section::operator()(
|
||||||
const boost::blank& blank) const
|
const boost::blank& blank) const
|
||||||
{
|
{
|
||||||
return render_context(mstch::object{{".", mstch::node{}}}, context)
|
return render_context::push(ctx, {{".", {}}}).render(section);
|
||||||
.render(section);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string visitor::render_section::operator()(const int& i) const {
|
std::string visitor::render_section::operator()(const int& i) const {
|
||||||
return render_context(mstch::object{{".", i}}, context).render(section);
|
return render_context::push(ctx, {{".", i}}).render(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string visitor::render_section::operator()(const bool& b) const {
|
std::string visitor::render_section::operator()(const bool& b) const {
|
||||||
return render_context(mstch::object{{".", b}}, context).render(section);
|
return render_context::push(ctx, {{".", b}}).render(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string visitor::render_section::operator()(const std::string& str) const {
|
std::string visitor::render_section::operator()(const std::string& str) const {
|
||||||
return render_context(mstch::object{{".", str}}, context).render(section);
|
return render_context::push(ctx, {{".", str}}).render(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string visitor::render_section::operator()(const object& obj) const {
|
std::string visitor::render_section::operator()(const object& obj) const {
|
||||||
return render_context(obj, context).render(section);
|
return render_context::push(ctx, obj).render(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string visitor::render_section::operator()(const array& a) const {
|
std::string visitor::render_section::operator()(const array& a) const {
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
if(flags.find(flag::keep_array) != flags.end())
|
if(flags.find(flag::keep_array) != flags.end())
|
||||||
out << render_context(mstch::object{{".", a}}, context).render(section);
|
out << render_context::push(ctx, {{".", a}}).render(section);
|
||||||
else
|
else
|
||||||
for (auto& item: a)
|
for (auto& item: a)
|
||||||
out << boost::apply_visitor(
|
out << boost::apply_visitor(
|
||||||
render_section(context, section, {flag::keep_array}), item);
|
render_section(ctx, section, {flag::keep_array}), item);
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +51,6 @@ std::string visitor::render_section::operator()(
|
||||||
const renderer_lambda& lambda) const
|
const renderer_lambda& lambda) const
|
||||||
{
|
{
|
||||||
return (lambda())(section, [&](const std::string& text) {
|
return (lambda())(section, [&](const std::string& text) {
|
||||||
return render_context(mstch::object{}, context).render(text);
|
return render_context::push(ctx).render(text);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,12 +14,12 @@ namespace mstch {
|
||||||
public:
|
public:
|
||||||
enum class flag { keep_array };
|
enum class flag { keep_array };
|
||||||
private:
|
private:
|
||||||
render_context& context;
|
render_context& ctx;
|
||||||
std::string section;
|
std::string section;
|
||||||
std::set<flag> flags;
|
std::set<flag> flags;
|
||||||
public:
|
public:
|
||||||
render_section(
|
render_section(
|
||||||
render_context& context,
|
render_context& ctx,
|
||||||
const std::string& section,
|
const std::string& section,
|
||||||
std::set<flag> flags = {});
|
std::set<flag> flags = {});
|
||||||
std::string operator()(const boost::blank& blank) const;
|
std::string operator()(const boost::blank& blank) const;
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
#include "to_json.hpp"
|
|
||||||
|
|
||||||
using namespace mstch;
|
|
||||||
|
|
||||||
std::string visitor::to_json::operator()(const boost::blank& blank) const {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string visitor::to_json::operator()(const int& i) const {
|
|
||||||
return std::to_string(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string visitor::to_json::operator()(const bool& b) const {
|
|
||||||
return b?"true":"false";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string visitor::to_json::operator()(const std::string& str) const {
|
|
||||||
return "\"" + str + "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string visitor::to_json::operator()(const array& arr) const {
|
|
||||||
bool first = true;
|
|
||||||
std::ostringstream out;
|
|
||||||
out << "[";
|
|
||||||
for(auto& item: arr) {
|
|
||||||
first?(first = false):(out << ", ");
|
|
||||||
out << boost::apply_visitor(*this, item);
|
|
||||||
}
|
|
||||||
out << "]";
|
|
||||||
return out.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string visitor::to_json::operator()(const object& obj) const {
|
|
||||||
bool first = true;
|
|
||||||
std::ostringstream out;
|
|
||||||
out << "{";
|
|
||||||
for(auto& item: obj) {
|
|
||||||
first?(first = false):(out << ", ");
|
|
||||||
out << item.first << ": " << boost::apply_visitor(*this, item.second);
|
|
||||||
}
|
|
||||||
out << "}";
|
|
||||||
return out.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string visitor::to_json::operator()(const string_lambda& lambda) const {
|
|
||||||
return ""; // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string visitor::to_json::operator()(const renderer_lambda& lambda) const {
|
|
||||||
return ""; // TODO
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef _MSTCH_TO_JSON_H_
|
|
||||||
#define _MSTCH_TO_JSON_H_
|
|
||||||
|
|
||||||
#include <boost/variant/static_visitor.hpp>
|
|
||||||
#include <boost/blank.hpp>
|
|
||||||
#include "render_context.hpp"
|
|
||||||
|
|
||||||
#include "mstch/mstch.hpp"
|
|
||||||
|
|
||||||
namespace mstch {
|
|
||||||
namespace visitor {
|
|
||||||
class to_json: public boost::static_visitor<std::string> {
|
|
||||||
public:
|
|
||||||
std::string operator()(const boost::blank& blank) const;
|
|
||||||
std::string operator()(const int& i) const;
|
|
||||||
std::string operator()(const bool& b) const;
|
|
||||||
std::string operator()(const std::string& str) const;
|
|
||||||
std::string operator()(const array& arr) const;
|
|
||||||
std::string operator()(const object& obj) const;
|
|
||||||
std::string operator()(const string_lambda& lambda) const;
|
|
||||||
std::string operator()(const renderer_lambda& lambda) const;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //_MSTCH_TO_JSON_H_
|
|
Loading…
Add table
Add a link
Reference in a new issue