]> Creatis software - cpPlugins.git/blob - lib/mstch/mstch.hpp
Moved to version 1.0
[cpPlugins.git] / lib / mstch / mstch.hpp
1 #pragma once
2
3 #include <vector>
4 #include <map>
5 #include <string>
6 #include <memory>
7 #include <functional>
8
9 #include <boost/variant.hpp>
10
11 namespace mstch {
12
13 struct config {
14   static std::function<std::string(const std::string&)> escape;
15 };
16
17 namespace internal {
18
19 template<class N>
20 class object_t {
21  public:
22   const N& at(const std::string& name) const {
23     cache[name] = (methods.at(name))();
24     return cache[name];
25   }
26
27   bool has(const std::string name) const {
28     return methods.count(name) != 0;
29   }
30
31  protected:
32   template<class S>
33   void register_methods(S* s, std::map<std::string,N(S::*)()> methods) {
34     for(auto& item: methods)
35       this->methods.insert({item.first, std::bind(item.second, s)});
36   }
37
38  private:
39   std::map<std::string, std::function<N()>> methods;
40   mutable std::map<std::string, N> cache;
41 };
42
43 template<class T, class N>
44 class is_fun {
45  private:
46   using not_fun = char;
47   using fun_without_args = char[2];
48   using fun_with_args = char[3];
49   template <typename U, U> struct really_has;
50   template <typename C> static fun_without_args& test(
51       really_has<N(C::*)() const, &C::operator()>*);
52   template <typename C> static fun_with_args& test(
53       really_has<N(C::*)(const std::string&) const,
54       &C::operator()>*);
55   template <typename> static not_fun& test(...);
56
57  public:
58   static bool const no_args = sizeof(test<T>(0)) == sizeof(fun_without_args);
59   static bool const has_args = sizeof(test<T>(0)) == sizeof(fun_with_args);
60 };
61
62 template<class N>
63 using node_renderer = std::function<std::string(const N& n)>;
64
65 template<class N>
66 class lambda_t {
67  public:
68   template<class F>
69   lambda_t(F f, typename std::enable_if<is_fun<F, N>::no_args>::type* = 0):
70       fun([f](node_renderer<N> renderer, const std::string&) {
71         return renderer(f());
72       })
73   {
74   }
75
76   template<class F>
77   lambda_t(F f, typename std::enable_if<is_fun<F, N>::has_args>::type* = 0):
78       fun([f](node_renderer<N> renderer, const std::string& text) {
79         return renderer(f(text));
80       })
81   {
82   }
83
84   std::string operator()(node_renderer<N> renderer,
85       const std::string& text = "") const
86   {
87     return fun(renderer, text);
88   }
89
90  private:
91   std::function<std::string(node_renderer<N> renderer, const std::string&)> fun;
92 };
93
94 }
95
96 using node = boost::make_recursive_variant<
97     std::nullptr_t, std::string, int, double, bool,
98     internal::lambda_t<boost::recursive_variant_>,
99     std::shared_ptr<internal::object_t<boost::recursive_variant_>>,
100     std::map<const std::string, boost::recursive_variant_>,
101     std::vector<boost::recursive_variant_>>::type;
102 using object = internal::object_t<node>;
103 using lambda = internal::lambda_t<node>;
104 using map = std::map<const std::string, node>;
105 using array = std::vector<node>;
106
107 std::string render(
108     const std::string& tmplt,
109     const node& root,
110     const std::map<std::string,std::string>& partials =
111         std::map<std::string,std::string>());
112
113 }