diff --git a/include/mstch/mstch.hpp b/include/mstch/mstch.hpp index 483cf4e..124af02 100644 --- a/include/mstch/mstch.hpp +++ b/include/mstch/mstch.hpp @@ -8,55 +8,64 @@ #include namespace mstch { - namespace internal { - template - class object_t { - public: - const N& at(const std::string& name) const { - cache[name] = (methods.at(name))(); - return cache[name]; - } +namespace internal { - bool has(const std::string name) const { - return methods.count(name); - } - protected: - template - void register_methods(S* s, std::map methods) { - for(auto& i: methods) - this->methods.insert({i.first, std::bind(i.second, s)}); - } - private: - std::map> methods; - mutable std::map cache; - }; - } +template +class object_t { + public: + const N& at(const std::string& name) const { + cache[name] = (methods.at(name))(); + return cache[name]; + } - using renderer = std::function; - class lambda { - public: - lambda(std::function fun): fun(fun) { - } + bool has(const std::string name) const { + return methods.count(name); + } - std::string operator()(const std::string& text, renderer renderer) const { - return fun(text, renderer); - } - private: - std::function fun; - }; + protected: + template + void register_methods(S* s, std::map methods) { + for(auto& item: methods) + this->methods.insert({item.first, std::bind(item.second, s)}); + } - using node = boost::make_recursive_variant< - boost::blank, std::string, int, bool, lambda, - std::shared_ptr>, - std::map, - std::vector>::type; - using object = internal::object_t; - using map = std::map; - using array = std::vector; + private: + std::map> methods; + mutable std::map cache; +}; + +} + +using renderer = std::function; + +class lambda { + public: + lambda(std::function fun): + fun(fun) + { + } + + std::string operator()(const std::string& text, renderer renderer) const { + return fun(text, renderer); + } + + private: + std::function fun; +}; + +using node = boost::make_recursive_variant< + boost::blank, std::string, int, bool, lambda, + std::shared_ptr>, + std::map, + std::vector>::type; +using object = internal::object_t; +using map = std::map; +using array = std::vector; + +std::string render( + const std::string& tmplt, + const node& root, + const std::map& partials = + std::map()); - std::string render( - const std::string& tmplt, - const node& root, - const std::map& partials = - std::map()); } diff --git a/src/state/in_section.cpp b/src/state/in_section.cpp index 64d881b..c676af7 100644 --- a/src/state/in_section.cpp +++ b/src/state/in_section.cpp @@ -6,33 +6,28 @@ using namespace mstch; state::in_section::in_section(type type, const std::string& section_name): - m_type(type), section_name(section_name), skipped_openings(0) + m_type(type), section_name(section_name), skipped_openings(0) { } std::string state::in_section::render(render_context& ctx, const token& token) { - if(token.token_type() == token::type::section_close) { - if(token.name() == section_name && skipped_openings == 0) { - auto& node = ctx.get_node(section_name); - std::string out; - if(m_type == type::normal) { - if (!boost::apply_visitor(visitor::is_node_empty(), node)) - out = boost::apply_visitor( - visitor::render_section(ctx, section), node); - } else if(m_type == type::inverted) { - if (boost::apply_visitor(visitor::is_node_empty(), node)) - out = render_context::push(ctx).render(section); - } - ctx.set_state(); - return out; - } else { - skipped_openings--; - } - } else if(token.token_type() == token::type::inverted_section_open || - token.token_type() == token::type::section_open) - { - skipped_openings++; - } - section << token; - return ""; + if(token.token_type() == token::type::section_close) + if(token.name() == section_name && skipped_openings == 0) { + auto& sn = ctx.get_node(section_name); + std::string out; + if(m_type == type::normal && + !boost::apply_visitor(visitor::is_node_empty(), sn)) + out = boost::apply_visitor(visitor::render_section(ctx, section), sn); + else if(m_type == type::inverted && + boost::apply_visitor(visitor::is_node_empty(), sn)) + out = render_context::push(ctx).render(section); + ctx.set_state(); + return out; + } else + skipped_openings--; + else if(token.token_type() == token::type::inverted_section_open || + token.token_type() == token::type::section_open) + skipped_openings++; + section << token; + return ""; } diff --git a/src/template_type.cpp b/src/template_type.cpp index 3406ddb..795428d 100644 --- a/src/template_type.cpp +++ b/src/template_type.cpp @@ -44,7 +44,10 @@ void template_type::tokenize(const std::string& t) { if (*it == delim_end[del_pos] && ++del_pos == delim_end.size()) { pstate = parse_state::start; tokens.push_back({{tok_start, tok_end}}); - tokens.push_back({{tok_end, it + 1}, delim_start.size(), delim_end.size()}); + tokens.push_back( + {{tok_end, it + 1}, + delim_start.size(), + delim_end.size()}); tok_start = it + 1; } else { pstate = parse_state::start; diff --git a/src/token.cpp b/src/token.cpp index bef2102..abb3b93 100644 --- a/src/token.cpp +++ b/src/token.cpp @@ -15,20 +15,20 @@ token::type token::token_info(char c) { } } -token::token(const std::string& str, std::size_t skip_left, std::size_t skip_right): +token::token(const std::string& str, std::size_t left, std::size_t right): m_raw(str), m_eol(false), m_ws_only(false) { - if(skip_left != 0 && skip_right != 0) { - if(str[skip_left] == '{' && str[str.size() - skip_right - 1] == '}') { + if(left != 0 && right != 0) { + if(str[left] == '{' && str[str.size() - right - 1] == '}') { m_type = type::unescaped_variable; - m_name = {first_not_ws(str.begin() + skip_left + 1, str.end() - skip_right), - first_not_ws(str.rbegin() + 1 + skip_right, str.rend() - skip_left) + 1}; + m_name = {first_not_ws(str.begin() + left + 1, str.end() - right), + first_not_ws(str.rbegin() + 1 + right, str.rend() - left) + 1}; } else { - auto first = first_not_ws(str.begin() + skip_left, str.end() - skip_right); + auto first = first_not_ws(str.begin() + left, str.end() - right); m_type = token_info(*first); if(m_type != type::variable) - first = first_not_ws(first + 1, str.end() - skip_right); - m_name = {first, first_not_ws(str.rbegin() + skip_right, str.rend() - skip_left) + 1}; + first = first_not_ws(first + 1, str.end() - right); + m_name = {first, first_not_ws(str.rbegin() + right, str.rend() - left) + 1}; } } else { m_type = type::text; diff --git a/src/token.hpp b/src/token.hpp index f57b5c3..d3b56ea 100644 --- a/src/token.hpp +++ b/src/token.hpp @@ -9,7 +9,7 @@ namespace mstch { text, variable, section_open, section_close, inverted_section_open, unescaped_variable, comment, partial }; - token(const std::string& str, std::size_t skip_left = 0, std::size_t skip_right = 0); + token(const std::string& str, std::size_t left = 0, std::size_t right = 0); type token_type() const { return m_type; }; const std::string& raw() const { return m_raw; }; const std::string& name() const { return m_name; }; diff --git a/src/visitor/get_token.hpp b/src/visitor/get_token.hpp index 5e0654d..99c0b24 100644 --- a/src/visitor/get_token.hpp +++ b/src/visitor/get_token.hpp @@ -5,33 +5,36 @@ #include "mstch/mstch.hpp" namespace mstch { - namespace visitor { - class get_token: public boost::static_visitor { - public: - get_token(const std::string& token, const mstch::node& node): - token(token), node(node) - { - } +namespace visitor { - template inline - const mstch::node& operator()(const T& t) const { - return node; - } - private: - const std::string& token; - const mstch::node& node; - }; +class get_token: public boost::static_visitor { + public: + get_token(const std::string& token, const mstch::node& node): + token(token), node(node) + { + } - template<> inline - const mstch::node& get_token::operator()(const map& m) const { - return m.at(token); - } + template + inline const mstch::node& operator()(const T& t) const { + return node; + } - template<> inline - const mstch::node& get_token::operator()>( - const std::shared_ptr& obj) const - { - return obj->at(token); - } - } + private: + const std::string& token; + const mstch::node& node; +}; + +template<> +inline const mstch::node& get_token::operator()(const map& map) const { + return map.at(token); +} + +template<> +inline const mstch::node& get_token::operator()>( + const std::shared_ptr& object) const +{ + return object->at(token); +} + +} } diff --git a/src/visitor/has_token.hpp b/src/visitor/has_token.hpp index d504058..81d26ba 100644 --- a/src/visitor/has_token.hpp +++ b/src/visitor/has_token.hpp @@ -5,30 +5,32 @@ #include "mstch/mstch.hpp" namespace mstch { - namespace visitor { - class has_token: public boost::static_visitor { - public: - has_token(const std::string& token): token(token) { - } +namespace visitor { - template inline - bool operator()(const T& t) const { - return token == "."; - } - private: - const std::string& token; - }; +class has_token: public boost::static_visitor { + public: + has_token(const std::string& token): token(token) { + } - template<> inline - bool has_token::operator()(const map& m) const { - return m.count(token) == 1; - } + template + inline bool operator()(const T& t) const { + return token == "."; + } +private: + const std::string& token; +}; - template<> inline - bool has_token::operator()>( - const std::shared_ptr& obj) const - { - return obj->has(token); - } - } +template<> +inline bool has_token::operator()(const map& map) const { + return map.count(token) == 1; +} + +template<> +inline bool has_token::operator()>( + const std::shared_ptr& object) const +{ + return object->has(token); +} + +} } diff --git a/src/visitor/is_node_empty.hpp b/src/visitor/is_node_empty.hpp index a303218..64e88a3 100644 --- a/src/visitor/is_node_empty.hpp +++ b/src/visitor/is_node_empty.hpp @@ -2,45 +2,48 @@ #include #include + #include "mstch/mstch.hpp" namespace mstch { - namespace visitor { - class is_node_empty: public boost::static_visitor { - public: - template inline - bool operator()(const T& t) const { - return false; - } - }; +namespace visitor { - template<> inline - bool is_node_empty::operator()( - const boost::blank& blank) const - { - return true; - } +class is_node_empty: public boost::static_visitor { + public: + template inline + bool operator()(const T& t) const { + return false; + } +}; - template<> inline - bool is_node_empty::operator()(const int& i) const { - return i == 0; - } - - template<> inline - bool is_node_empty::operator()(const bool& b) const { - return !b; - } - - template<> inline - bool is_node_empty::operator()( - const std::string& str) const - { - return str == ""; - } - - template<> inline - bool is_node_empty::operator()(const array& arr) const { - return arr.size() == 0; - } - } +template<> +inline bool is_node_empty::operator()( + const boost::blank& blank) const +{ + return true; +} + +template<> +inline bool is_node_empty::operator()(const int& val) const { + return val == 0; +} + +template<> +inline bool is_node_empty::operator()(const bool& val) const { + return !val; +} + +template<> +inline bool is_node_empty::operator()( + const std::string& val) const +{ + return val == ""; +} + +template<> +inline bool is_node_empty::operator()(const array& array) const { + return array.size() == 0; +} + +} } diff --git a/src/visitor/render_node.hpp b/src/visitor/render_node.hpp index 34ddc7e..2cb245e 100644 --- a/src/visitor/render_node.hpp +++ b/src/visitor/render_node.hpp @@ -2,43 +2,47 @@ #include #include + #include "mstch/mstch.hpp" #include "utils.hpp" namespace mstch { - namespace visitor { - class render_node: public boost::static_visitor { - public: - enum class flag { - none, escape_html - }; +namespace visitor { - render_node(flag p_flag = flag::none): m_flag(p_flag) { - } +class render_node: public boost::static_visitor { + public: + enum class flag { + none, escape_html + }; - template inline - std::string operator()(const T& t) const { - return ""; - } - private: - flag m_flag; - }; + render_node(flag p_flag = flag::none): m_flag(p_flag) { + } - template<> inline - std::string render_node::operator()(const int& i) const { - return std::to_string(i); - } + template + inline std::string operator()(const T& t) const { + return ""; + } - template<> inline - std::string render_node::operator()(const bool& b) const { - return b?"true":"false"; - } + private: + flag m_flag; +}; - template<> inline - std::string render_node::operator()( - const std::string& str) const - { - return (m_flag == flag::escape_html)?html_escape(str):str; - } - } +template<> +inline std::string render_node::operator()(const int& val) const { + return std::to_string(val); +} + +template<> inline +std::string render_node::operator()(const bool& val) const { + return val?"true":"false"; +} + +template<> +inline std::string render_node::operator()( + const std::string& val) const +{ + return (m_flag == flag::escape_html)?html_escape(val):val; +} + +} } diff --git a/src/visitor/render_section.hpp b/src/visitor/render_section.hpp index 9c2b72d..ef2b8b8 100644 --- a/src/visitor/render_section.hpp +++ b/src/visitor/render_section.hpp @@ -2,53 +2,57 @@ #include #include + #include "render_context.hpp" #include "mstch/mstch.hpp" namespace mstch { - namespace visitor { - class render_section: public boost::static_visitor { - public: - enum class flag { none, keep_array }; - render_section( - render_context& ctx, - const template_type& section, - flag p_flag = flag::none): - ctx(ctx), section(section), m_flag(p_flag) - { - } +namespace visitor { - template inline - std::string operator()(const T& t) const { - return render_context::push(ctx, t).render(section); - } - private: - render_context& ctx; - const template_type& section; - flag m_flag; - }; +class render_section: public boost::static_visitor { + public: + enum class flag { none, keep_array }; + render_section( + render_context& ctx, + const template_type& section, + flag p_flag = flag::none): + ctx(ctx), section(section), m_flag(p_flag) + { + } - template<> inline - std::string render_section::operator()(const lambda& lam) const { - return ""; - /*std::string section_str; - for(auto& token: section) - section_str += token.raw(); - return lam(section_str, [this](const std::string& str) { - return ctx.render(template_type{str}); - });*/ - } + template + inline std::string operator()(const T& t) const { + return render_context::push(ctx, t).render(section); + } - template<> inline - std::string render_section::operator()(const array& arr) const { - std::string out; - if(m_flag == flag::keep_array) - out += render_context::push(ctx, arr).render(section); - else - for (auto& i: arr) - out += boost::apply_visitor( - render_section(ctx, section, flag::keep_array), i); - return out; - } - } +private: + render_context& ctx; + const template_type& section; + flag m_flag; +}; + +template<> +inline std::string render_section::operator()(const lambda& fun) const { + return ""; + /*std::string section_str; + for(auto& token: section) + section_str += token.raw(); + return lam(section_str, [this](const std::string& str) { + return ctx.render(template_type{str}); + });*/ +} + +template<> +inline std::string render_section::operator()(const array& array) const { + std::string out; + if(m_flag == flag::keep_array) + out += render_context::push(ctx, array).render(section); + else + for (auto& item: array) + out += boost::apply_visitor( + render_section(ctx, section, flag::keep_array), item); + return out; +} + +} }