#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace crow { namespace black_magic { template constexpr uint64_t 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 computeParameterTagFromArgsList; template <> struct computeParameterTagFromArgsList<> { static constexpr int value = 0; }; template struct computeParameterTagFromArgsList { static constexpr int subValue = computeParameterTagFromArgsList::value; static constexpr int value = getParameterTag::type>() != 0 ? subValue * 6 + getParameterTag::type>() : subValue; }; inline bool isParameterTagCompatible(uint64_t a, uint64_t b) { while (true) { 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; } a /= 6; b /= 6; } return false; } constexpr inline uint64_t getParameterTag(std::string_view url) { uint64_t tagValue = 0; size_t urlSegmentIndex = std::string_view::npos; size_t paramIndex = 0; for (size_t urlIndex = 0; urlIndex < url.size(); urlIndex++) { char character = url[urlIndex]; if (character == '<') { if (urlSegmentIndex != std::string_view::npos) { return 0; } urlSegmentIndex = urlIndex; } if (character == '>') { if (urlSegmentIndex == std::string_view::npos) { return 0; } std::string_view tag = url.substr(urlSegmentIndex, urlIndex + 1 - urlSegmentIndex); // Note, this is a really lame way to do std::pow(6, paramIndex) // std::pow doesn't work in constexpr in clang. // Ideally in the future we'd move this to use a power of 2 packing // (probably 8 instead of 6) so that these just become bit shifts uint64_t insertIndex = 1; for (size_t unused = 0; unused < paramIndex; unused++) { insertIndex *= 6; } if (tag == "") { tagValue += insertIndex * 1; } if (tag == "") { tagValue += insertIndex * 2; } if (tag == "" || tag == "") { tagValue += insertIndex * 3; } if (tag == "" || tag == "") { tagValue += insertIndex * 4; } if (tag == "") { tagValue += insertIndex * 5; } paramIndex++; urlSegmentIndex = std::string_view::npos; } } if (urlSegmentIndex != std::string_view::npos) { return 0; } return tagValue; } template struct S { template using push = S; template using push_back = S; template