aboutsummaryrefslogtreecommitdiffstats
path: root/utility.h
diff options
context:
space:
mode:
Diffstat (limited to 'utility.h')
-rw-r--r--utility.h155
1 files changed, 153 insertions, 2 deletions
diff --git a/utility.h b/utility.h
index 8499532..2f3d84a 100644
--- a/utility.h
+++ b/utility.h
@@ -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<>;
+ };
+
}
}