c++ object support
This commit is contained in:
parent
812b4bdb41
commit
8f7210f95d
@ -12,8 +12,9 @@ namespace mstch {
|
|||||||
template<class N>
|
template<class N>
|
||||||
class object_t {
|
class object_t {
|
||||||
public:
|
public:
|
||||||
N at(const std::string &name) const {
|
const N& at(const std::string& name) const {
|
||||||
return (methods.at(name))();
|
cache[name] = (methods.at(name))();
|
||||||
|
return cache[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has(const std::string name) const {
|
bool has(const std::string name) const {
|
||||||
@ -21,14 +22,13 @@ namespace mstch {
|
|||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
template<class S>
|
template<class S>
|
||||||
void register_method(std::string name, S* sub, N(S::*method)()) {
|
void register_methods(S* sub, std::map<std::string,N(S::*)()> methods) {
|
||||||
this->methods.insert({name, std::bind(method, sub)});
|
for(auto& item: methods)
|
||||||
}
|
this->methods.insert({item.first, std::bind(item.second, sub)});
|
||||||
void register_method(std::string name, const N& node) {
|
|
||||||
this->methods.insert({name, [node](){return node;}});
|
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::map<std::string, std::function<N()>> methods;
|
std::map<std::string, std::function<N()>> methods;
|
||||||
|
mutable std::map<std::string, N> cache;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ set(SRC
|
|||||||
state/in_section.cpp
|
state/in_section.cpp
|
||||||
state/outside_section.cpp
|
state/outside_section.cpp
|
||||||
visitor/get_token.cpp
|
visitor/get_token.cpp
|
||||||
|
visitor/has_token.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
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
#include "state/outside_section.hpp"
|
#include "state/outside_section.hpp"
|
||||||
#include "visitor/get_token.hpp"
|
#include "visitor/get_token.hpp"
|
||||||
|
#include "visitor/has_token.hpp"
|
||||||
|
|
||||||
using namespace mstch;
|
using namespace mstch;
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ render_context::render_context(
|
|||||||
new state::outside_section));
|
new state::outside_section));
|
||||||
}
|
}
|
||||||
|
|
||||||
mstch::node render_context::find_node(
|
const mstch::node& render_context::find_node(
|
||||||
const std::string& token,
|
const std::string& token,
|
||||||
const std::deque<node>& current_nodes)
|
const std::deque<node>& current_nodes)
|
||||||
{
|
{
|
||||||
@ -43,14 +44,13 @@ mstch::node render_context::find_node(
|
|||||||
token.substr(token.rfind('.') + 1),
|
token.substr(token.rfind('.') + 1),
|
||||||
{find_node(token.substr(0, token.rfind('.')), current_nodes)});
|
{find_node(token.substr(0, token.rfind('.')), current_nodes)});
|
||||||
else
|
else
|
||||||
for (auto& node: current_nodes) {
|
for (auto& n: current_nodes)
|
||||||
auto ret = boost::apply_visitor(visitor::get_token(token, node), node);
|
if (boost::apply_visitor(visitor::has_token(token), n))
|
||||||
if(ret.first) return ret.second;
|
return boost::apply_visitor(visitor::get_token(token, n), n);
|
||||||
}
|
|
||||||
return null_node;
|
return null_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
mstch::node render_context::get_node(const std::string& token) {
|
const mstch::node& render_context::get_node(const std::string& token) {
|
||||||
return find_node(token, nodes);
|
return find_node(token, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ namespace mstch {
|
|||||||
render_context(
|
render_context(
|
||||||
const mstch::node& node,
|
const mstch::node& node,
|
||||||
const std::map<std::string,template_type>& partials);
|
const std::map<std::string,template_type>& partials);
|
||||||
mstch::node get_node(const std::string& token);
|
const mstch::node& get_node(const std::string& token);
|
||||||
std::string render(const template_type& templt);
|
std::string render(const template_type& templt);
|
||||||
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>
|
||||||
@ -34,7 +34,7 @@ namespace mstch {
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
static const mstch::node null_node;
|
static const mstch::node null_node;
|
||||||
mstch::node find_node(
|
const mstch::node& find_node(
|
||||||
const std::string& token,
|
const std::string& token,
|
||||||
const std::deque<node>& current_nodes);
|
const std::deque<node>& current_nodes);
|
||||||
const std::map<std::string,template_type>& partials;
|
const std::map<std::string,template_type>& partials;
|
||||||
|
@ -18,7 +18,7 @@ std::string state::in_inverted_section::render(
|
|||||||
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::string 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::push(ctx).render(section);
|
out = render_context::push(ctx).render(section);
|
||||||
ctx.set_state<outside_section>();
|
ctx.set_state<outside_section>();
|
||||||
|
@ -14,7 +14,7 @@ std::string state::in_section::render(render_context& ctx, const token& token) {
|
|||||||
switch(token.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) {
|
||||||
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(
|
||||||
|
@ -18,12 +18,11 @@ std::string state::outside_section::render(
|
|||||||
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: {
|
return boost::apply_visitor(visitor::render_node(flag::escape_html),
|
||||||
auto visitor = visitor::render_node((token.token_type() ==
|
ctx.get_node(token.content()));
|
||||||
token::type::variable)?flag::escape_html:flag::none);
|
case token::type::unescaped_variable:
|
||||||
auto node = ctx.get_node(token.content());
|
return boost::apply_visitor(visitor::render_node(flag::none),
|
||||||
return boost::apply_visitor(visitor, node);
|
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.content();
|
return token.content();
|
||||||
|
@ -8,36 +8,31 @@ get_token::get_token(const std::string& token, const mstch::node& node):
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool,node> get_token::operator()(const boost::blank& blank) const {
|
const mstch::node& get_token::operator()(const boost::blank& blank) const {
|
||||||
return {token == ".", node};
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool,node> get_token::operator()(const int& i) const {
|
const mstch::node& get_token::operator()(const int& i) const {
|
||||||
return {token == ".", node};
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool,node> get_token::operator()(const bool& b) const {
|
const mstch::node& get_token::operator()(const bool& b) const {
|
||||||
return {token == ".", node};
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool,node> get_token::operator()(const std::string& str) const {
|
const mstch::node& get_token::operator()(const std::string& str) const {
|
||||||
return {token == ".", node};
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool,node> get_token::operator()(const array& arr) const {
|
const mstch::node& get_token::operator()(const array& arr) const {
|
||||||
return {token == ".", node};
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool,node> get_token::operator()(const map& map) const {
|
const mstch::node& get_token::operator()(const map& map) const {
|
||||||
if(map.count(token) == 1)
|
return map.at(token);
|
||||||
return {true, map.at(token)};
|
|
||||||
else
|
|
||||||
return {false, node};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool,node> get_token::operator()(const std::shared_ptr<object>& obj) const {
|
const mstch::node& get_token::operator()(const std::shared_ptr<object>& obj) const {
|
||||||
if (obj->has(token))
|
return obj->at(token);
|
||||||
return {true, obj->at(token)};
|
|
||||||
else
|
|
||||||
return {false, node};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,19 +6,19 @@
|
|||||||
|
|
||||||
namespace mstch {
|
namespace mstch {
|
||||||
namespace visitor {
|
namespace visitor {
|
||||||
class get_token: public boost::static_visitor<std::pair<bool,mstch::node>> {
|
class get_token: public boost::static_visitor<const mstch::node&> {
|
||||||
public:
|
public:
|
||||||
get_token(const std::string& token, const mstch::node& node);
|
get_token(const std::string& token, const mstch::node& node);
|
||||||
std::pair<bool,mstch::node> operator()(const boost::blank& blank) const;
|
const mstch::node& operator()(const boost::blank& blank) const;
|
||||||
std::pair<bool,mstch::node> operator()(const int& i) const;
|
const mstch::node& operator()(const int& i) const;
|
||||||
std::pair<bool,mstch::node> operator()(const bool& b) const;
|
const mstch::node& operator()(const bool& b) const;
|
||||||
std::pair<bool,mstch::node> operator()(const std::string& str) const;
|
const mstch::node& operator()(const std::string& str) const;
|
||||||
std::pair<bool,mstch::node> operator()(const array& arr) const;
|
const mstch::node& operator()(const array& arr) const;
|
||||||
std::pair<bool,mstch::node> operator()(const map& map) const;
|
const mstch::node& operator()(const map& map) const;
|
||||||
std::pair<bool,mstch::node> operator()(const std::shared_ptr<object>& obj) const;
|
const mstch::node& operator()(const std::shared_ptr<object>& obj) const;
|
||||||
private:
|
private:
|
||||||
const std::string& token;
|
const std::string& token;
|
||||||
mstch::node node;
|
const mstch::node& node;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
35
src/visitor/has_token.cpp
Normal file
35
src/visitor/has_token.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "has_token.hpp"
|
||||||
|
|
||||||
|
using namespace mstch;
|
||||||
|
using namespace mstch::visitor;
|
||||||
|
|
||||||
|
has_token::has_token(const std::string& token): token(token) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_token::operator()(const boost::blank& blank) const {
|
||||||
|
return token == ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_token::operator()(const int& i) const {
|
||||||
|
return token == ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_token::operator()(const bool& b) const {
|
||||||
|
return token == ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_token::operator()(const std::string& str) const {
|
||||||
|
return token == ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_token::operator()(const array& arr) const {
|
||||||
|
return token == ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_token::operator()(const map& map) const {
|
||||||
|
return map.count(token) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_token::operator()(const std::shared_ptr<object>& obj) const {
|
||||||
|
return obj->has(token);
|
||||||
|
}
|
23
src/visitor/has_token.hpp
Normal file
23
src/visitor/has_token.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <boost/variant/static_visitor.hpp>
|
||||||
|
#include <boost/blank.hpp>
|
||||||
|
#include "mstch/mstch.hpp"
|
||||||
|
|
||||||
|
namespace mstch {
|
||||||
|
namespace visitor {
|
||||||
|
class has_token: public boost::static_visitor<bool> {
|
||||||
|
public:
|
||||||
|
has_token(const std::string& token);
|
||||||
|
bool operator()(const boost::blank& blank) const;
|
||||||
|
bool operator()(const int& i) const;
|
||||||
|
bool operator()(const bool& b) const;
|
||||||
|
bool operator()(const std::string& str) const;
|
||||||
|
bool operator()(const array& arr) const;
|
||||||
|
bool operator()(const map& map) const;
|
||||||
|
bool operator()(const std::shared_ptr<object>& obj) const;
|
||||||
|
private:
|
||||||
|
const std::string& token;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
class comments: public mstch::object {
|
class comments: public mstch::object {
|
||||||
public:
|
public:
|
||||||
comments() {
|
comments() {
|
||||||
register_method("title", this, &comments::title);
|
register_methods(this, {{"title", &comments::title}});
|
||||||
}
|
}
|
||||||
|
|
||||||
mstch::node title() {
|
mstch::node title() {
|
||||||
|
@ -1,48 +1,68 @@
|
|||||||
class complex_item: public mstch::object {
|
class complex_item: public mstch::object {
|
||||||
private:
|
private:
|
||||||
const std::string name;
|
std::string m_name;
|
||||||
const bool current;
|
bool m_current;
|
||||||
const std::string url;
|
std::string m_url;
|
||||||
public:
|
public:
|
||||||
complex_item(const std::string& name, bool current, const std::string& url):
|
complex_item(const std::string& name, bool current, const std::string& url):
|
||||||
name{name}, current{current}, url{url}
|
m_name{name}, m_current{current}, m_url{url}
|
||||||
{
|
{
|
||||||
register_method("name", {name});
|
register_methods(this, {
|
||||||
register_method("current", {current});
|
{"name", &complex_item::name}, {"current", &complex_item::current},
|
||||||
register_method("url", {url});
|
{"url", &complex_item::url}, {"link", &complex_item::link}
|
||||||
register_method("link", this, &complex_item::link);
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
mstch::node current() {
|
||||||
|
return m_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
mstch::node url() {
|
||||||
|
return m_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
mstch::node name() {
|
||||||
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
mstch::node link() {
|
mstch::node link() {
|
||||||
return !current;
|
return !m_current;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class complex: public mstch::object {
|
class complex: public mstch::object {
|
||||||
private:
|
private:
|
||||||
const std::string header;
|
std::string m_header;
|
||||||
const mstch::array item;
|
mstch::array m_item;
|
||||||
public:
|
public:
|
||||||
complex():
|
complex():
|
||||||
header{"Colors"},
|
m_header{"Colors"},
|
||||||
item{
|
m_item{
|
||||||
std::make_shared<complex_item>("red", true, "#Red"),
|
std::make_shared<complex_item>("red", true, "#Red"),
|
||||||
std::make_shared<complex_item>("green", false, "#Green"),
|
std::make_shared<complex_item>("green", false, "#Green"),
|
||||||
std::make_shared<complex_item>("blue", false, "#Blue")
|
std::make_shared<complex_item>("blue", false, "#Blue")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
register_method("header", {header});
|
register_methods(this, {
|
||||||
register_method("item", {item});
|
{"header", &complex::header}, {"item", &complex::item},
|
||||||
register_method("list", this, &complex::list);
|
{"list", &complex::list}, {"empty", &complex::empty}
|
||||||
register_method("empty", this, &complex::empty);
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
mstch::node header() {
|
||||||
|
return m_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
mstch::node item() {
|
||||||
|
return m_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
mstch::node list() {
|
mstch::node list() {
|
||||||
return item.size() != 0;
|
return m_item.size() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mstch::node empty() {
|
mstch::node empty() {
|
||||||
return item.size() == 0;
|
return m_item.size() == 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,18 +1,27 @@
|
|||||||
class dot_notation_price: public mstch::object {
|
class dot_notation_price: public mstch::object {
|
||||||
private:
|
private:
|
||||||
const int value;
|
int m_value;
|
||||||
const mstch::map currency;
|
mstch::map m_currency;
|
||||||
public:
|
public:
|
||||||
dot_notation_price():
|
dot_notation_price():
|
||||||
value{200}, currency{{"symbol", std::string{"$"}}, {"name", std::string{"USD"}}}
|
m_value{200}, m_currency{{"symbol", std::string{"$"}}, {"name", std::string{"USD"}}}
|
||||||
{
|
{
|
||||||
register_method("value", {value});
|
register_methods(this, {
|
||||||
register_method("vat", this, &dot_notation_price::vat);
|
{"value", &dot_notation_price::value},
|
||||||
register_method("currency", {currency});
|
{"vat", &dot_notation_price::vat},
|
||||||
|
{"currency", &dot_notation_price::currency}});
|
||||||
|
}
|
||||||
|
|
||||||
|
mstch::node value() {
|
||||||
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
mstch::node vat() {
|
mstch::node vat() {
|
||||||
return static_cast<int>(value * 0.2);
|
return static_cast<int>(m_value * 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
mstch::node currency() {
|
||||||
|
return m_currency;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
class escaped: public mstch::object {
|
class escaped: public mstch::object {
|
||||||
public:
|
public:
|
||||||
escaped() {
|
escaped() {
|
||||||
register_method("title", this, &escaped::title);
|
register_methods(this, {
|
||||||
register_method("entities", this, &escaped::entities);
|
{"title", &escaped::title}, {"entities", &escaped::entities}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
mstch::node title() {
|
mstch::node title() {
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
class nested_higher_order_sections: public mstch::object {
|
class nested_higher_order_sections: public mstch::object {
|
||||||
public:
|
public:
|
||||||
nested_higher_order_sections() {
|
nested_higher_order_sections() {
|
||||||
register_method("bold", this, &nested_higher_order_sections::bold);
|
register_methods(this, {
|
||||||
register_method("person", this, &nested_higher_order_sections::person);
|
{"bold", &nested_higher_order_sections::bold},
|
||||||
|
{"person", &nested_higher_order_sections::person}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
mstch::node bold() {
|
mstch::node bold() {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
class partial_template: public mstch::object {
|
class partial_template: public mstch::object {
|
||||||
public:
|
public:
|
||||||
partial_template() {
|
partial_template() {
|
||||||
register_method("title", this, &partial_template::title);
|
register_methods(this, {
|
||||||
register_method("again", this, &partial_template::again);
|
{"title", &partial_template::title},
|
||||||
|
{"again", &partial_template::again}});
|
||||||
}
|
}
|
||||||
|
|
||||||
mstch::node title() {
|
mstch::node title() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
class section_functions_in_partials: public mstch::object {
|
class section_functions_in_partials: public mstch::object {
|
||||||
public:
|
public:
|
||||||
section_functions_in_partials() {
|
section_functions_in_partials() {
|
||||||
register_method("bold", this, §ion_functions_in_partials::bold);
|
register_methods(this, {{"bold", §ion_functions_in_partials::bold}});
|
||||||
}
|
}
|
||||||
|
|
||||||
mstch::node bold() {
|
mstch::node bold() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
class unescaped: public mstch::object {
|
class unescaped: public mstch::object {
|
||||||
public:
|
public:
|
||||||
unescaped() {
|
unescaped() {
|
||||||
register_method("title", this, &unescaped::title);
|
register_methods(this, {{"title", &unescaped::title}});
|
||||||
}
|
}
|
||||||
|
|
||||||
mstch::node title() {
|
mstch::node title() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user