3#include "magpie/data/CommonData.hpp"
15namespace magpie::routing {
20 std::array<char, N + 1> data{};
21 const size_t size = N;
23 constexpr FixedString(
const char (&str)[N + 1]) {
24 std::copy_n(str, N + 1, std::data(data));
26 constexpr explicit FixedString(
const ConstString& src);
28 constexpr explicit FixedString(
const char* begin) {
29 std::copy_n(begin, N, std::data(data));
32 constexpr char operator[](
size_t idx)
const {
34 throw std::runtime_error(
"Invalid string index");
36 return *(data.data() + idx);
40 constexpr auto c_str()
const ->
char const* {
return std::data(data); }
43template <std::
size_t N>
50 constexpr ConstString() {
55 constexpr ConstString(
const char (&str)[N]): str(str), size(N) {
56 static_assert(N >= 1,
"Invalid string");
58 constexpr ConstString(
const ConstString& other): str(other.str), size(other.size) {}
60 constexpr explicit ConstString(
const char* str,
size_t N): str(str), size(N) {
62 throw std::runtime_error(
"Invalid string");
66 template <
size_t N,
size_t Offset>
68 if (Offset + N >= size) {
69 throw std::runtime_error(
"offset and length is out of bounds");
74 constexpr void operator=(
const ConstString& rhs) {
76 this->size = rhs.size;
79 constexpr char operator[](
size_t idx)
const {
81 throw std::runtime_error(
"Invalid string index");
85 constexpr const char* end()
const {
return str + size; }
89constexpr ConstString FixedString<N>::toConstString()
const {
90 return ConstString((
const char*) std::data(data), N + 1);
93constexpr FixedString<N>::FixedString(
const ConstString& src) {
94 std::copy_n(src.str, N + 1, std::data(data));
98constexpr bool startsWithAtOffset(
const ConstString& source,
const ConstString& substring) {
99 if (substring.size > source.size - offset) {
103 for (
size_t i = 0; i < substring.size; ++i) {
104 if (source[i + offset] != substring[i]) {
111constexpr bool startsWithAtOffset(
const ConstString& source,
const ConstString& substring,
size_t offset) {
112 if (substring.size > source.size - offset) {
116 for (
size_t i = 0; i < substring.size; ++i) {
117 if (source[i + offset] != substring[i] && substring[i] !=
'\0') {
124template <FixedString source>
125constexpr size_t guessParams() {
127 for (
size_t i = 0; i < source.size; ++i) {
128 if (source[i] ==
'{') {
135template <FixedString s>
142 using type = int64_t;
143 static constexpr type convert(
const std::string_view& v) {
145 std::from_chars(v.data(), v.data() + v.size(), out);
152 using type = std::string_view;
153 static constexpr type convert(
const std::string_view& v) {
154 return v.back() ==
'/' ?
155 v.substr(0, v.size() - 1)
160constexpr static inline ConstString INT_VALUE(
"{int}", 6);
161constexpr static inline ConstString STRING_VALUE(
"{string}", 9);
163template <FixedString s,
size_t matched,
size_t params>
164constexpr void parse(std::array<ConstString, params>& out,
size_t i = 0) {
165 if constexpr (matched == params) {
172 constexpr auto constStr = s.toConstString();
173 if (startsWithAtOffset(constStr, INT_VALUE, i)) {
174 out.at(matched) = INT_VALUE;
175 parse<s, matched + 1, params>(out, i + 5);
176 }
else if (startsWithAtOffset(constStr, STRING_VALUE, i)) {
177 out.at(matched) = STRING_VALUE;
178 parse<s, matched + 1, params>(out, i + 8);
183 parse<s, matched, params>(out, i + 1);
188template <FixedString s, size_t matched = 0, size_t params = guessParams<s>()>
189constexpr std::array<ConstString, params> getParameterTypes() {
190 if constexpr (params == 0) {
191 return std::array<ConstString, params>{};
193 std::array<ConstString, params> out;
194 parse<s, matched, params>(out);
200template <FixedString s,
size_t matched,
size_t params>
201constexpr void parseForIndices(
202 std::array<std::pair<ConstString, size_t>, params>& out,
203 size_t slashIndex = 1,
206 if constexpr (matched == params) {
217 auto newSlashIndex = slashIndex + (s[i] ==
'/') * 2;
222 constexpr auto constStr = s.toConstString();
223 if (startsWithAtOffset(constStr, INT_VALUE, i)) {
224 std::get<matched>(out) = {INT_VALUE, slashIndex};
225 parseForIndices<s, matched + 1, params>(out, newSlashIndex, i + 5);
226 }
else if (startsWithAtOffset(constStr, STRING_VALUE, i)) {
227 std::get<matched>(out) = {STRING_VALUE, slashIndex};
228 parseForIndices<s, matched + 1, params>(out, newSlashIndex, i + 8);
233 parseForIndices<s, matched, params>(out, newSlashIndex, i + 1);
238template <FixedString s, size_t Size = guessParams<s>()>
239consteval auto getForwardableIndices() {
240 std::array<std::pair<ConstString, size_t>, Size> out;
241 parseForIndices<s, 0, Size>(out);
245template <FixedString s>
246consteval bool isValidPath() {
247 for (
size_t i = 0; i < s.size; ++i) {
249 if (i == 0 || s[i - 1] !=
'/') {
252 }
else if (s[i] ==
'}') {
253 if (i != s.size - 1 && s[i + 1] !=
'/') {
263 typename ReturnType = void,
268 static_assert(s[0] ==
'/',
"Invalid route: must start with /");
269 static_assert(isValidPath<s>(),
"Invalid route: each placeholder value must be a separate segment");
271 constexpr static auto typeArray = getParameterTypes<s>();
273 template <std::size_t... I>
274 static auto compileType(std::index_sequence<I...>)
275 ->
typename std::function<
285 using type =
decltype(
287 std::make_index_sequence<typeArray.size()>()
Definition Compile.hpp:46
Definition Compile.hpp:19
Definition Compile.hpp:266
Definition Compile.hpp:136