diff --git a/include/crow/json.h b/include/crow/json.h index d53dee275..17e4b4aa5 100644 --- a/include/crow/json.h +++ b/include/crow/json.h @@ -88,6 +88,7 @@ namespace crow String, List, Object, + Function }; inline const char* get_type_str(type t) { @@ -98,6 +99,7 @@ namespace crow case type::List: return "List"; case type::String: return "String"; case type::Object: return "Object"; + case type::Function: return "Function"; default: return "Unknown"; } } @@ -771,6 +773,7 @@ namespace crow os << '}'; } break; + case type::Function: os << "custom function"; break; } return os; } @@ -1236,6 +1239,7 @@ namespace crow } num; ///< Value if type is a number. std::string s; ///< Value if type is a string. std::unique_ptr> l; ///< Value if type is a list. + std::function f; //Value if type is a function (C++ lambda) #ifdef CROW_JSON_USE_MAP std::unique_ptr> o; #else @@ -1264,6 +1268,7 @@ namespace crow case type::Null: case type::False: case type::True: + case type::Function: return; case type::Number: nt = r.nt(); @@ -1330,6 +1335,8 @@ namespace crow #endif o->insert(r.o->begin(), r.o->end()); return; + case type::Function: + f = r.f; } } @@ -1457,7 +1464,7 @@ namespace crow return *this; } - wvalue& operator=(const char* str) + wvalue& operator = (const char* str) { reset(); t_ = type::String; @@ -1465,7 +1472,7 @@ namespace crow return *this; } - wvalue& operator=(const std::string& str) + wvalue& operator = (const std::string& str) { reset(); t_ = type::String; @@ -1473,7 +1480,7 @@ namespace crow return *this; } - wvalue& operator=(std::vector&& v) + wvalue& operator = (std::vector&& v) { if (t_ != type::List) reset(); @@ -1491,7 +1498,7 @@ namespace crow } template - wvalue& operator=(const std::vector& v) + wvalue& operator = (const std::vector& v) { if (t_ != type::List) reset(); @@ -1508,6 +1515,14 @@ namespace crow return *this; } + wvalue& operator = (std::function&& func) + { + reset(); + t_ = type::Function; + f = std::move(func); + return *this; + } + wvalue& operator[](unsigned index) { if (t_ != type::List) @@ -1555,6 +1570,13 @@ namespace crow return result; } + std::string execute(std::string txt = "") const //Not using reference because it cannot be used with a default rvalue + { + if (t_ != type::Function) + return ""; + return f(txt); + } + /// If the wvalue is a list, it returns the length of the list, otherwise it returns 1. std::size_t size() const { @@ -1600,6 +1622,8 @@ namespace crow } return sum+2; } + case type::Function: + return 0; } return 1; } @@ -1685,6 +1709,8 @@ namespace crow out.push_back('}'); } break; + case type::Function: + out += "custom function"; break; } } diff --git a/include/crow/mustache.h b/include/crow/mustache.h index 5be8db737..54dca14e8 100644 --- a/include/crow/mustache.h +++ b/include/crow/mustache.h @@ -45,13 +45,13 @@ namespace crow int end; int pos; ActionType t; - Action(ActionType t, size_t start, size_t end, size_t pos = 0) + Action(ActionType t, size_t start, size_t end, size_t pos = 0) : start(static_cast(start)), end(static_cast(end)), pos(static_cast(pos)), t(t) {} }; /// A mustache template object. - class template_t + class template_t { public: template_t(std::string body) @@ -215,8 +215,14 @@ namespace crow else out += ctx.s; break; + case json::type::Function: + if (action.t == ActionType::Tag) + escape(ctx.execute(), out); + else + out += ctx.execute(); + break; default: - throw std::runtime_error("not implemented tag type" + boost::lexical_cast(static_cast(ctx.t()))); + throw std::runtime_error(std::string("not implemented tag type: ") + json::get_type_str(ctx.t())); } } break; @@ -341,7 +347,7 @@ namespace crow std::string tag_close = "}}"; std::vector blockPositions; - + size_t current = 0; while(1) {