diff --git a/include/mstch.h b/include/mstch.h index 495a54e..93bdba8 100644 --- a/include/mstch.h +++ b/include/mstch.h @@ -7,7 +7,8 @@ namespace mstch { std::string render( const std::string& tmplt, const object& context, - const std::map& partials = std::map()); + const std::map& partials = + std::map()); } #endif // _MSTCH_H_ diff --git a/src/mstch.cpp b/src/mstch.cpp index 4be0b55..2252706 100644 --- a/src/mstch.cpp +++ b/src/mstch.cpp @@ -7,7 +7,8 @@ using namespace mstch; std::string strip_whitespace(std::string tmplt) { - tmplt = std::regex_replace(tmplt, std::regex("\\{\\{![^\\}]*\\}\\}"), "{{!}}"); + std::regex comment_match("\\{\\{![^\\}]*\\}\\}"); + tmplt = std::regex_replace(tmplt, comment_match, "{{!}}"); std::ostringstream out; std::istringstream in(tmplt); std::string line; @@ -29,5 +30,6 @@ std::string mstch::render( const std::string& tmplt, const object& root_object, const std::map& partials) { - return render_context(root_object, partials).render(strip_whitespace(tmplt)); + return render_context(root_object, partials) + .render(strip_whitespace(tmplt)); } diff --git a/src/render_context.cpp b/src/render_context.cpp index 40bd9fd..42a338d 100644 --- a/src/render_context.cpp +++ b/src/render_context.cpp @@ -8,14 +8,18 @@ using namespace mstch; const mstch::node render_context::null_node; -render_context::render_context(const mstch::object &object, const std::map& partials): +render_context::render_context( + const mstch::object &object, + const std::map& partials): partials(partials), objects{object}, state(new state::outside_section) { } -render_context::render_context(const mstch::object& object, const render_context& context): +render_context::render_context( + const mstch::object& object, + const render_context& context): partials(context.partials), objects(context.objects), state(new state::outside_section) @@ -23,10 +27,16 @@ render_context::render_context(const mstch::object& object, const render_context objects.push_front(object); } -const mstch::node& render_context::find_node(const std::string &token, const std::deque ¤t_objects) { +const mstch::node& render_context::find_node( + const std::string &token, + const std::deque ¤t_objects) +{ if(token != "." && token.find('.') != std::string::npos) { - return find_node(token.substr(token.rfind('.') + 1), - {boost::get(find_node(token.substr(0, token.rfind('.')), current_objects))}); + return find_node( + token.substr(token.rfind('.') + 1), + {boost::get(find_node( + token.substr(0, token.rfind('.')), + current_objects))}); } else { for (auto& object: current_objects) if (object.count(token) != 0) diff --git a/src/render_context.h b/src/render_context.h index ad56f06..337d618 100644 --- a/src/render_context.h +++ b/src/render_context.h @@ -12,18 +12,24 @@ namespace mstch { class render_context { private: static const mstch::node null_node; - const mstch::node& find_node(const std::string& token, const std::deque& current_objects); + const mstch::node& find_node( + const std::string& token, + const std::deque& current_objects); const std::map& partials; std::deque objects; std::unique_ptr state; public: - render_context(const mstch::object& object, const std::map& partials); - render_context(const mstch::object& object, const render_context& context); + render_context( + const mstch::object& object, + const std::map& partials); + render_context( + const mstch::object& object, const render_context& context); const mstch::node& get_node(const std::string& token); std::string render(const std::string& tmplt); template void set_state(Args&&... args) { - state = std::unique_ptr(new T(std::forward(args)...)); + state = std::unique_ptr( + new T(std::forward(args)...)); } }; } diff --git a/src/state/in_inverted_section.cpp b/src/state/in_inverted_section.cpp index 5796513..eeac8ba 100644 --- a/src/state/in_inverted_section.cpp +++ b/src/state/in_inverted_section.cpp @@ -7,36 +7,43 @@ using namespace mstch; -state::in_inverted_section::in_inverted_section(const std::string& section_name): +state::in_inverted_section::in_inverted_section( + const std::string& section_name): section_name(section_name), skipped_openings(0) { } -std::string state::in_inverted_section::render(render_context& context, const token& token) { +std::string state::in_inverted_section::render( + render_context& ctx, + const token& token) +{ switch(token.type()) { - case token_type::section_close: - if(token.content() == section_name && skipped_openings == 0) { - std::ostringstream out; - if(boost::apply_visitor(visitor::is_node_empty(), context.get_node(section_name))) - out << render_context(mstch::object{}, context).render(section_text.str()); - context.set_state(); - return out.str(); - } else { - skipped_openings--; - section_text << token.raw(); + case token_type::section_close: + if(token.content() == section_name && skipped_openings == 0) { + std::ostringstream out; + auto& section_node = ctx.get_node(section_name); + if(boost::apply_visitor(visitor::is_node_empty(), section_node)) { + auto empty = mstch::object{}; + out << render_context(empty, ctx).render(section_text.str()); } - break; - case token_type::inverted_section_open: - case token_type::section_open: - skipped_openings++; - case token_type::text: - case token_type::variable: - case token_type::unescaped_variable: - case token_type::comment: - case token_type::partial: + ctx.set_state(); + return out.str(); + } else { + skipped_openings--; section_text << token.raw(); - break; + } + break; + case token_type::inverted_section_open: + case token_type::section_open: + skipped_openings++; + case token_type::text: + case token_type::variable: + case token_type::unescaped_variable: + case token_type::comment: + case token_type::partial: + section_text << token.raw(); + break; } return ""; } diff --git a/src/state/in_inverted_section.h b/src/state/in_inverted_section.h index d10e411..97ae19a 100644 --- a/src/state/in_inverted_section.h +++ b/src/state/in_inverted_section.h @@ -6,14 +6,16 @@ namespace mstch { namespace state { - class in_inverted_section : public render_state, public std::enable_shared_from_this { + class in_inverted_section: public render_state { private: const std::string section_name; std::ostringstream section_text; int skipped_openings; public: in_inverted_section(const std::string §ion_name); - std::string render(render_context &context, const token &token) override; + std::string render( + render_context &context, + const token &token) override; }; } } diff --git a/src/state/in_section.cpp b/src/state/in_section.cpp index c8fc384..f6848cc 100644 --- a/src/state/in_section.cpp +++ b/src/state/in_section.cpp @@ -5,34 +5,40 @@ using namespace mstch; -state::in_section::in_section(const std::string& section_name): section_name(section_name), skipped_openings(0) { +state::in_section::in_section(const std::string& section_name): + section_name(section_name), skipped_openings(0) +{ } -std::string state::in_section::render(render_context& context, const token& token) { +std::string state::in_section::render( + render_context& ctx, + const token& token) +{ switch(token.type()) { - case token_type::section_close: - if(token.content() == section_name && skipped_openings == 0) { - auto section_node = context.get_node(section_name); - std::string out(""); - if (!boost::apply_visitor(visitor::is_node_empty(), section_node)) - out = boost::apply_visitor(visitor::render_section(context, section_text.str()), section_node); - context.set_state(); - return out; - } else { - skipped_openings--; - section_text << token.raw(); - } - break; - case token_type::inverted_section_open: - case token_type::section_open: - skipped_openings++; - case token_type::text: - case token_type::variable: - case token_type::unescaped_variable: - case token_type::comment: - case token_type::partial: + case token_type::section_close: + if(token.content() == section_name && skipped_openings == 0) { + auto section_node = ctx.get_node(section_name); + std::string out(""); + if (!boost::apply_visitor(visitor::is_node_empty(), section_node)) + out = boost::apply_visitor(visitor::render_section( + ctx, section_text.str()), section_node); + ctx.set_state(); + return out; + } else { + skipped_openings--; section_text << token.raw(); - break; + } + break; + case token_type::inverted_section_open: + case token_type::section_open: + skipped_openings++; + case token_type::text: + case token_type::variable: + case token_type::unescaped_variable: + case token_type::comment: + case token_type::partial: + section_text << token.raw(); + break; } return ""; } diff --git a/src/state/in_section.h b/src/state/in_section.h index e6e679c..be7cbb3 100644 --- a/src/state/in_section.h +++ b/src/state/in_section.h @@ -13,7 +13,9 @@ namespace mstch { int skipped_openings; public: in_section(const std::string& section_name); - std::string render(render_context& context, const token& token) override; + std::string render( + render_context& context, + const token& token) override; }; } } diff --git a/src/state/outside_section.cpp b/src/state/outside_section.cpp index 5bf5cac..8407fcd 100644 --- a/src/state/outside_section.cpp +++ b/src/state/outside_section.cpp @@ -6,26 +6,30 @@ using namespace mstch; -std::string state::outside_section::render(render_context& context, const token& token) { +std::string state::outside_section::render( + render_context& ctx, + const token& token) +{ switch(token.type()) { - case token_type::section_open: - context.set_state(token.content()); - break; - case token_type::inverted_section_open: - context.set_state(token.content()); - break; - case token_type::variable: - case token_type::unescaped_variable: - return boost::apply_visitor(visitor::render_node(token.type() == token_type::variable), - context.get_node(token.content())); - case token_type::comment: break; - case token_type::text: - return token.raw(); - case token_type::partial: - break;//render_context(mstch::object{{".", i}}, context).render(section); - case token_type::section_close: - // TODO ERROR - break; + case token_type::section_open: + ctx.set_state(token.content()); + break; + case token_type::inverted_section_open: + ctx.set_state(token.content()); + break; + case token_type::variable: + case token_type::unescaped_variable: + return boost::apply_visitor( + visitor::render_node(token.type() == token_type::variable), + ctx.get_node(token.content())); + case token_type::comment: break; + case token_type::text: + return token.raw(); + case token_type::partial: + break;//render_context(mstch::object{{".", i}}, ctx).render(section); + case token_type::section_close: + // TODO ERROR + break; } return ""; } diff --git a/src/state/outside_section.h b/src/state/outside_section.h index 2afd3c8..9d8cb7a 100644 --- a/src/state/outside_section.h +++ b/src/state/outside_section.h @@ -5,9 +5,11 @@ namespace mstch { namespace state { - class outside_section : public render_state { + class outside_section: public render_state { public: - std::string render(render_context &context, const token &token) override; + std::string render( + render_context &context, + const token &token) override; }; } } diff --git a/src/state/render_state.h b/src/state/render_state.h index e3be626..8d12d09 100644 --- a/src/state/render_state.h +++ b/src/state/render_state.h @@ -10,7 +10,9 @@ namespace mstch { class render_state { public: virtual ~render_state() {} - virtual std::string render(render_context& context, const token& token) = 0; + virtual std::string render( + render_context& context, + const token& token) = 0; }; } } diff --git a/src/token.cpp b/src/token.cpp index ce8af47..8b6a853 100644 --- a/src/token.cpp +++ b/src/token.cpp @@ -6,7 +6,8 @@ using namespace mstch; token::token(const std::string& raw_token): raw_val(raw_token) { - if(std::regex_match(raw_token, std::regex("\\{{2}[^\\}]*\\}{2}|\\{{3}[^\\}]*\\}{3}"))) { + std::regex token_match("\\{{2}[^\\}]*\\}{2}|\\{{3}[^\\}]*\\}{3}"); + if(std::regex_match(raw_token, token_match)) { std::string inside = raw_token.substr(2, raw_token.size() - 4); inside = trim(inside); if (inside.size() > 0 && inside.at(0) == '#') { @@ -24,7 +25,9 @@ token::token(const std::string& raw_token): raw_val(raw_token) { } 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) == '}') { + } 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) == '!') { diff --git a/src/token.h b/src/token.h index d681cc5..ff7c55b 100644 --- a/src/token.h +++ b/src/token.h @@ -5,7 +5,8 @@ namespace mstch { enum class token_type { - text, variable, section_open, section_close, inverted_section_open, unescaped_variable, comment, partial + text, variable, section_open, section_close, inverted_section_open, + unescaped_variable, comment, partial }; class token { diff --git a/src/utils.cpp b/src/utils.cpp index 57d17a2..36ce021 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -3,12 +3,18 @@ #include std::string& mstch::ltrim(std::string& s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + s.erase(s.begin(), std::find_if( + s.begin(), + s.end(), + std::not1(std::ptr_fun(std::isspace)))); return s; } std::string& mstch::rtrim(std::string& s) { - s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + s.erase(std::find_if( + s.rbegin(), + s.rend(), + std::not1(std::ptr_fun(std::isspace))).base(), s.end()); return s; } @@ -16,7 +22,11 @@ std::string& mstch::trim(std::string& s) { return ltrim(rtrim(s)); } -std::string mstch::replace_all(std::string str, const std::string& from, const std::string& to) { +std::string mstch::replace_all( + std::string str, + const std::string& from, + const std::string& to) +{ size_t start_pos = 0; while((start_pos = str.find(from, start_pos)) != std::string::npos) { str.replace(start_pos, from.length(), to); diff --git a/src/utils.h b/src/utils.h index ba1a13e..7777d5c 100644 --- a/src/utils.h +++ b/src/utils.h @@ -7,7 +7,10 @@ namespace mstch { std::string& ltrim(std::string& s); std::string& rtrim(std::string& s); std::string& trim(std::string& s); - std::string replace_all(std::string str, const std::string& from, const std::string& to); + std::string replace_all( + std::string str, + const std::string& from, + const std::string& to); std::string html_escape(std::string str); } diff --git a/src/visitor/render_node.cpp b/src/visitor/render_node.cpp index 1de510a..72945a1 100644 --- a/src/visitor/render_node.cpp +++ b/src/visitor/render_node.cpp @@ -3,7 +3,9 @@ using namespace mstch; -visitor::render_node::render_node(bool html_escaped): html_escaped(html_escaped) { +visitor::render_node::render_node(bool html_escaped): + html_escaped(html_escaped) +{ } std::string visitor::render_node::operator()(const boost::blank& blank) const { diff --git a/src/visitor/render_section.cpp b/src/visitor/render_section.cpp index bbc525a..2a35a6e 100644 --- a/src/visitor/render_section.cpp +++ b/src/visitor/render_section.cpp @@ -3,13 +3,17 @@ using namespace mstch; -visitor::render_section::render_section(render_context& context, const std::string& section): +visitor::render_section::render_section( + render_context& context, + const std::string& section): context(context), section(section) { } -std::string visitor::render_section::operator()(const boost::blank& blank) const { +std::string visitor::render_section::operator()( + const boost::blank& blank) const +{ return ""; }