#pragma once #include #include namespace flask { namespace black_magic { struct OutOfRange { OutOfRange(unsigned pos, unsigned length) {} }; constexpr unsigned requires_in_range( unsigned i, unsigned len ) { return i >= len ? throw OutOfRange(i, len) : i; } class const_str { const char * const begin_; unsigned size_; public: template< unsigned N > constexpr const_str( const char(&arr)[N] ) : begin_(arr), size_(N - 1) { static_assert( N >= 1, "not a string literal"); } constexpr char operator[]( unsigned i ) const { return requires_in_range(i, size_), begin_[i]; } constexpr operator const char *() const { return begin_; } constexpr unsigned size() const { return size_; } }; constexpr unsigned find_closing_tag(const_str s, unsigned p) { return s[p] == '>' ? p : find_closing_tag(s, p+1); } 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, "", 0, 5); } constexpr bool is_uint(const_str s, unsigned i) { return is_equ_n(s, i, "", 0, 6); } constexpr bool is_float(const_str s, unsigned i) { return is_equ_n(s, i, "", 0, 7) || is_equ_n(s, i, "", 0, 8); } constexpr bool is_str(const_str s, unsigned i) { return is_equ_n(s, i, "", 0, 5); } constexpr bool is_path(const_str s, unsigned i) { return is_equ_n(s, i, "", 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 struct S { template using push = S; template class U> using rebind = U; }; template struct CallHelper; template struct CallHelper> { template ()(std::declval()...)) > static char __test(int); template static int __test(...); static constexpr bool value = sizeof(__test(0)) == sizeof(char); }; template 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 struct arguments { using subarguments = typename arguments::type; using type = typename subarguments::template push::type>; }; template <> struct arguments<0> { using type = S<>; }; } }