From edae25d41d89564a21e0e0a11b4cde2287ba889e Mon Sep 17 00:00:00 2001 From: Pixel Date: Fri, 25 Nov 2011 00:06:34 -0800 Subject: Adding a simple 'Mustache' template processor in C++. --- includes/SimpleMustache.h | 98 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 includes/SimpleMustache.h (limited to 'includes/SimpleMustache.h') diff --git a/includes/SimpleMustache.h b/includes/SimpleMustache.h new file mode 100644 index 0000000..d98b5eb --- /dev/null +++ b/includes/SimpleMustache.h @@ -0,0 +1,98 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace Balau { + +class SimpleMustache { + public: + + class Context { + public: + class Proxy { + public: + Context & operator[](const char * str); + Context & operator=(const char * str); + Context & operator=(bool b); + private: + Proxy(Context * parent, ssize_t idx) : m_parent(parent), m_idx(idx) { } + Context * m_parent; + ssize_t m_idx; + friend class Context; + }; + + Context() : m_type(CONTEXTLIST), m_root(true) { } + ~Context() { empty(); } + Proxy operator[](ssize_t idx) { ensureList(); return Proxy(this, idx); } + Context & operator[](const char * str); + Context & operator=(const char * str) { + empty(); + m_type = STRING; + m_str = str; + } + Context & operator=(bool b) { + empty(); + m_type = BOOLSEC; + m_bool = b; + } + private: + enum ContextType { + UNKNOWN, + STRING, + BOOLSEC, + CONTEXTLIST, + LAMBDA, + } m_type; + Context(ContextType type) : m_type(type), m_root(false) { } + Context(Context & c) { Assert(false); } + Context & operator=(Context & c) { Assert(false); } + String m_str; + bool m_bool; + typedef std::map SubContext; + typedef std::vector ContextList; + ContextList m_contextList; + bool m_root; + + void empty(bool skipFirst = false); + void ensureList(bool single = false); + + friend class Proxy; + friend class SimpleMustache; + }; + + void setTemplate(IO h); + void setTemplate(const uint8_t * str, ssize_t s = -1) { + if (s < 0) + s = strlen((const char *) str); + IO b(new Buffer(str, s)); + setTemplate(b); + } + void setTemplate(const char * str, ssize_t s = -1) { setTemplate((const uint8_t *) str, s); } + void setTemplate(const String & str) { setTemplate((const uint8_t *) str.to_charp(), str.strlen()); } + void render(IO h, Context * ctx) { Assert(ctx); render_r(h, ctx, "", m_fragments.begin(), false, -1); } + void empty() { while (!m_fragments.empty()) { delete m_fragments.front(); m_fragments.pop_front(); } } + ~SimpleMustache() { empty(); } + private: + struct Fragment { + enum { + UNKNOWN, + STRING, + VARIABLE, + NOESCAPE, + SECTION, + INVERTED, + END_SECTION, + } type; + String str; // contains either the string, the variable name, or the sections names. + }; + typedef std::list Fragments; + Fragments m_fragments; + + Fragments::iterator render_r(IO h, Context * ctx, const String & endSection, Fragments::iterator begin, bool noWrite, int forceIdx); + String escape(const String & s) { return s; } +}; + +}; -- cgit v1.2.3