diff options
Diffstat (limited to 'utility.h')
-rw-r--r-- | utility.h | 155 |
1 files changed, 153 insertions, 2 deletions
@@ -1,5 +1,8 @@ #pragma once +#include <stdint.h> +#include <stdexcept> + namespace flask { namespace black_magic @@ -13,7 +16,6 @@ namespace flask return i >= len ? throw OutOfRange(i, len) : i; } - // from http://akrzemi1.wordpress.com/2011/05/11/parsing-strings-at-compile-time-part-i/ class const_str { const char * const begin_; @@ -43,9 +45,158 @@ namespace flask return s[p] == '>' ? p : find_closing_tag(s, p+1); } - constexpr int count(const_str s, int i=0) + constexpr bool is_valid(const_str s, unsigned i = 0, int f = 0) + { + return + i == s.size() + ? f == 0 : + f < 0 || f >= 2 + ? false : + s[i] == '<' + ? is_valid(s, i+1, f+1) : + s[i] == '>' + ? is_valid(s, i+1, f-1) : + is_valid(s, i+1, f); + } + + constexpr int count(const_str s, unsigned i=0) { return i == s.size() ? 0 : s[i] == '<' ? 1+count(s,i+1) : count(s,i+1); } + + constexpr bool is_equ_n(const_str a, unsigned ai, const_str b, unsigned bi, unsigned n) + { + return + ai + n > a.size() || bi + n > b.size() + ? false : + n == 0 + ? true : + a[ai] != b[bi] + ? false : + is_equ_n(a,ai+1,b,bi+1,n-1); + } + + constexpr bool is_int(const_str s, unsigned i) + { + return is_equ_n(s, i, "<int>", 0, 5); + } + + constexpr bool is_uint(const_str s, unsigned i) + { + return is_equ_n(s, i, "<uint>", 0, 6); + } + + constexpr bool is_float(const_str s, unsigned i) + { + return is_equ_n(s, i, "<float>", 0, 7) || + is_equ_n(s, i, "<double>", 0, 8); + } + + constexpr bool is_str(const_str s, unsigned i) + { + return is_equ_n(s, i, "<str>", 0, 5); + } + + constexpr bool is_path(const_str s, unsigned i) + { + return is_equ_n(s, i, "<path>", 0, 6); + } + + constexpr uint64_t get_parameter_tag(const_str s, unsigned p = 0) + { + return + p == s.size() + ? 0 : + s[p] == '<' ? ( + is_int(s, p) + ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 1 : + is_uint(s, p) + ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 2 : + is_float(s, p) + ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 3 : + is_str(s, p) + ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 4 : + is_path(s, p) + ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 5 : + throw std::runtime_error("invalid parameter type") + ) : + get_parameter_tag(s, p+1); + } + + template <typename ... T> + struct S + { + template <typename U> + using push = S<U, T...>; + template <template<typename ... Args> class U> + using rebind = U<T...>; + }; +template <typename F, typename Set> + struct CallHelper; + template <typename F, typename ...Args> + struct CallHelper<F, S<Args...>> + { + template <typename F1, typename ...Args1, typename = + decltype(std::declval<F1>()(std::declval<Args1>()...)) + > + static char __test(int); + + template <typename ...> + static int __test(...); + + static constexpr bool value = sizeof(__test<F, Args...>(0)) == sizeof(char); + }; + + + template <int N> + struct single_tag_to_type + { + }; + + template <> + struct single_tag_to_type<1> + { + using type = int64_t; + }; + + template <> + struct single_tag_to_type<2> + { + using type = uint64_t; + }; + + template <> + struct single_tag_to_type<3> + { + using type = double; + }; + + template <> + struct single_tag_to_type<4> + { + using type = std::string; + }; + + template <> + struct single_tag_to_type<5> + { + using type = std::string; + }; + + + template <uint64_t Tag> + struct arguments + { + using subarguments = typename arguments<Tag/6>::type; + using type = + typename subarguments::template push<typename single_tag_to_type<Tag%6>::type>; + }; + + template <> + struct arguments<0> + { + using type = S<>; + }; + } } |