#pragma once #include "nlohmann/json.hpp" #include #include #include #include #include #include #include #include namespace crow { namespace black_magic { struct OutOfRange { OutOfRange(unsigned /*pos*/, unsigned /*length*/) {} }; constexpr unsigned requiresInRange(unsigned i, unsigned len) { return i >= len ? throw OutOfRange(i, len) : i; } class ConstStr { const char* const beginPtr; unsigned sizeUint; public: template constexpr ConstStr(const char (&arr)[N]) : beginPtr(arr), sizeUint(N - 1) { static_assert(N >= 1, "not a string literal"); } constexpr char operator[](unsigned i) const { requiresInRange(i, sizeUint); return beginPtr[i]; } constexpr operator const char*() const { return beginPtr; } constexpr const char* begin() const { return beginPtr; } constexpr const char* end() const { return beginPtr + sizeUint; } constexpr unsigned size() const { return sizeUint; } }; constexpr unsigned findClosingTag(ConstStr s, unsigned p) { return s[p] == '>' ? p : findClosingTag(s, p + 1); } constexpr bool isValid(ConstStr s, unsigned i = 0, int f = 0) { return i == s.size() ? f == 0 : f < 0 || f >= 2 ? false : s[i] == '<' ? isValid(s, i + 1, f + 1) : s[i] == '>' ? isValid(s, i + 1, f - 1) : isValid(s, i + 1, f); } constexpr bool isEquN(ConstStr a, unsigned ai, ConstStr b, unsigned bi, unsigned n) { return ai + n > a.size() || bi + n > b.size() ? false : n == 0 ? true : a[ai] != b[bi] ? false : isEquN(a, ai + 1, b, bi + 1, n - 1); } constexpr bool isInt(ConstStr s, unsigned i) { return isEquN(s, i, "", 0, 5); } constexpr bool isUint(ConstStr s, unsigned i) { return isEquN(s, i, "", 0, 6); } constexpr bool isFloat(ConstStr s, unsigned i) { return isEquN(s, i, "", 0, 7) || isEquN(s, i, "", 0, 8); } constexpr bool isStr(ConstStr s, unsigned i) { return isEquN(s, i, "", 0, 5) || isEquN(s, i, "", 0, 8); } constexpr bool isPath(ConstStr s, unsigned i) { return isEquN(s, i, "", 0, 6); } template constexpr int getParameterTag() { if constexpr (std::is_same_v) { return 1; } if constexpr (std::is_same_v) { return 1; } if constexpr (std::is_same_v) { return 1; } if constexpr (std::is_same_v) { return 1; } if constexpr (std::is_same_v) { return 1; } if constexpr (std::is_same_v) { return 2; } if constexpr (std::is_same_v) { return 2; } if constexpr (std::is_same_v) { return 2; } if constexpr (std::is_same_v) { return 2; } if constexpr (std::is_same_v) { return 2; } if constexpr (std::is_same_v) { return 3; } if constexpr (std::is_same_v) { return 4; } return 0; } template struct compute_parameter_tag_from_args_list; template <> struct compute_parameter_tag_from_args_list<> { static constexpr int value = 0; }; template struct compute_parameter_tag_from_args_list { static constexpr int subValue = compute_parameter_tag_from_args_list::value; static constexpr int value = getParameterTag::type>() ? subValue * 6 + getParameterTag::type>() : subValue; }; static inline bool isParameterTagCompatible(uint64_t a, uint64_t b) { if (a == 0) { return b == 0; } if (b == 0) { return a == 0; } uint64_t sa = a % 6; uint64_t sb = a % 6; if (sa == 5) { sa = 4; } if (sb == 5) { sb = 4; } if (sa != sb) { return false; } return isParameterTagCompatible(a / 6, b / 6); } static inline unsigned findClosingTagRuntime(const char* s, unsigned p) { return s[p] == 0 ? throw std::runtime_error("unmatched tag <") : s[p] == '>' ? p : findClosingTagRuntime(s, p + 1); } static inline uint64_t getParameterTagRuntime(const char* s, unsigned p = 0) { return s[p] == 0 ? 0 : s[p] == '<' ? (std::strncmp(s + p, "", 5) == 0 ? getParameterTagRuntime( s, findClosingTagRuntime(s, p)) * 6 + 1 : std::strncmp(s + p, "", 6) == 0 ? getParameterTagRuntime( s, findClosingTagRuntime(s, p)) * 6 + 2 : (std::strncmp(s + p, "", 7) == 0 || std::strncmp(s + p, "", 8) == 0) ? getParameterTagRuntime( s, findClosingTagRuntime(s, p)) * 6 + 3 : (std::strncmp(s + p, "", 5) == 0 || std::strncmp(s + p, "", 8) == 0) ? getParameterTagRuntime( s, findClosingTagRuntime( s, p)) * 6 + 4 : std::strncmp(s + p, "", 6) == 0 ? getParameterTagRuntime( s, findClosingTagRuntime( s, p)) * 6 + 5 : throw std::runtime_error( "invalid parameter " "type")) : getParameterTagRuntime(s, p + 1); } constexpr uint64_t get_parameter_tag(ConstStr s, unsigned p = 0) { return p == s.size() ? 0 : s[p] == '<' ? (isInt(s, p) ? get_parameter_tag(s, findClosingTag(s, p)) * 6 + 1 : isUint(s, p) ? get_parameter_tag(s, findClosingTag(s, p)) * 6 + 2 : isFloat(s, p) ? get_parameter_tag( s, findClosingTag(s, p)) * 6 + 3 : isStr(s, p) ? get_parameter_tag( s, findClosingTag(s, p)) * 6 + 4 : isPath(s, p) ? get_parameter_tag( s, findClosingTag( 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 using push_back = S; template