8 #include "arg_router/math.hpp"
12 #ifdef AR_ENABLE_CPP20_STRINGS
15 # include <string_view>
23 template <std::
size_t N>
24 class compile_time_string_storage
27 constexpr compile_time_string_storage() =
default;
32 constexpr compile_time_string_storage(std::array<char, N> str) : value(str) {}
35 constexpr compile_time_string_storage(std::span<const char, N> str)
37 std::copy(str.begin(), str.end(), value.begin());
41 constexpr compile_time_string_storage(
const char (&str)[N])
43 std::copy_n(&str[0], N, value.begin());
47 constexpr compile_time_string_storage(
char c) : value{c} {}
49 std::array<char, N> value;
55 class compile_time_string_storage<0>
59 constexpr std::size_t
size()
const {
return 0; }
60 constexpr
const char* data()
const {
return nullptr; }
61 constexpr
char operator[](std::size_t)
const {
return '\n'; }
64 constexpr compile_time_string_storage() =
default;
67 constexpr compile_time_string_storage(std::array<char, 0>) {}
70 constexpr compile_time_string_storage(std::span<const char, 0>) {}
73 constexpr compile_time_string_storage(
const char (&)[0]) {}
78 compile_time_string_storage()->compile_time_string_storage<0>;
79 compile_time_string_storage(
char)->compile_time_string_storage<1>;
94 template <detail::compile_time_
string_storage S = detail::compile_time_
string_storage<0>{}>
102 [[nodiscard]] constexpr
static std::size_t
size() noexcept {
return size_; }
108 [[nodiscard]] constexpr
static bool empty() noexcept {
return size() == 0; }
114 [[nodiscard]] constexpr
static std::string_view get() noexcept
116 return {S.value.data(),
size()};
125 template <detail::compile_time_
string_storage S2>
126 [[nodiscard]] constexpr
auto operator+([[maybe_unused]]
const str<S2>& other)
const noexcept
128 return []<std::size_t... LIs, std::size_t... RIs>(std::index_sequence<LIs...>,
129 std::index_sequence<RIs...>)
131 return str<std::array{S.value[LIs]..., S2.value[RIs]...,
'\0'}>{};
133 (std::make_index_sequence<
size()>{}, std::make_index_sequence<str<S2>::size()>{});
143 template <std::
size_t Pos, std::
size_t Count>
144 [[nodiscard]] constexpr
static auto substr() noexcept
146 static_assert((Pos + Count) < size_,
"Pos+Count must be less than string size");
148 return substr_impl<Pos>(std::make_index_sequence<Count>{});
155 template <
typename T>
158 template <detail::compile_time_
string_storage S2>
159 struct append<str<S2>> {
160 using type = std::decay_t<decltype(str{} + str<S2>{})>;
167 template <
typename T>
168 using append_t =
typename append<T>::type;
173 constexpr
static std::size_t calculate_size() noexcept
175 auto count = std::size_t{0};
177 if (S.value[count] ==
'\0') {
184 template <std::size_t Pos, std::size_t... Is>
185 constexpr
static auto substr_impl([[maybe_unused]] std::index_sequence<Is...> seq)
187 return str<std::array{S.value[Pos + Is]...,
'\0'}>{};
190 constexpr
static std::size_t size_ = calculate_size();
198 template <
typename S1,
typename S2>
199 using str_concat =
typename S1::template append_t<S2>;
206 template <std::
size_t N,
char C>
207 class create_sequence_cts
209 template <std::
size_t>
210 [[nodiscard]] constexpr
static char get() noexcept
215 template <std::size_t... Is>
216 [[nodiscard]] constexpr
static std::array<char, N> builder(
217 [[maybe_unused]] std::index_sequence<Is...> seq) noexcept
219 return {get<Is>()...};
223 using type = str<builder(std::make_index_sequence<N>{})>;
231 template <std::
size_t N,
char C>
238 template <auto Value>
239 struct convert_integral_to_cts {
241 static_assert(std::is_integral_v<decltype(Value)>,
"Value must be an integral");
243 template <
typename Str, auto NewValue>
244 [[nodiscard]] constexpr
static auto build() noexcept
247 constexpr
auto power10 = math::pow<10>(num_digits - 1);
248 constexpr
auto digit = NewValue / power10;
250 using digit_str = str<'0' + digit>;
252 if constexpr (num_digits != 1) {
253 constexpr
auto next_value = NewValue % power10;
254 return build<typename Str::template append_t<digit_str>, next_value>();
256 return typename Str::template append_t<digit_str>{};
260 using digit_str = decltype(build<str<>,
math::abs(Value)>());
263 using type = std::conditional_t<(Value < 0), str<'-'>::template append_t<digit_str>, digit_str>;
270 template <auto Value>
278 template <utility::detail::compile_time_
string_storage S>
279 using str = utility::str<S>;
287 template <
typename T>
288 struct is_compile_time_string_like : std::false_type {
292 struct is_compile_time_string_like<utility::str<S>> : std::true_type {
299 template <
typename T>
306 # define AR_STRING(tok) arg_router::utility::str<tok>
307 # define AR_STRING_SV(tok) arg_router::utility::str<std::span<const char, tok.size()>{tok}>
311 # include "arg_router/traits.hpp"
313 # include <boost/mp11/algorithm.hpp>
314 # include <boost/preprocessor/repetition/enum.hpp>
323 template <
char... Cs>
324 class compile_time_string;
330 template <
char... Cs>
335 using array_type = std::tuple<traits::integral_constant<Cs>...>;
341 [[nodiscard]] constexpr
static std::size_t
size() noexcept {
return sizeof...(Cs); }
347 [[nodiscard]] constexpr
static bool empty() noexcept {
return size() == 0; }
353 [[nodiscard]] constexpr
static std::string_view
get() noexcept
355 return {sv_.data(), sv_.size()};
362 template <
typename T>
365 template <
char... OtherCs>
374 template <
typename T>
383 template <
char... OtherCs>
391 constexpr
static auto sv_ = std::array<char,
sizeof...(Cs)>{Cs...};
399 template <std::
size_t N,
char C>
402 using seq = boost::mp11::mp_repeat_c<std::tuple<traits::integral_constant<C>>, N>;
404 template <
typename T>
408 template <
typename... Cs>
409 struct converter<std::tuple<Cs...>> {
414 using type =
typename converter<seq>::type;
422 template <std::
size_t N,
char C>
429 template <
typename T>
432 template <
template <
typename...>
typename Array,
typename... Cs>
441 template <
typename T>
448 template <auto Value>
451 static_assert(std::is_integral_v<decltype(Value)>,
"Value must be an integral");
453 template <
typename Str, auto NewValue>
454 [[nodiscard]] constexpr
static auto build() noexcept
457 constexpr
auto power10 = math::pow<10>(num_digits - 1);
458 constexpr
auto digit = NewValue / power10;
460 using digit_str =
typename Str::template append_t<compile_time_string<'0' + digit>>;
462 if constexpr (num_digits != 1) {
463 constexpr
auto next_value = NewValue % power10;
464 return build<digit_str, next_value>();
473 using type = std::conditional_t<(Value < 0),
482 template <auto Value>
489 [[nodiscard]] constexpr
char get(
const char (&str)[N], std::size_t i) noexcept
491 return i < N ? str[i] :
'\0';
494 [[nodiscard]] constexpr
char get(std::string_view str, std::size_t i) noexcept
496 return i < str.size() ? str[i] :
'\0';
499 [[nodiscard]] constexpr
char get(
char c, std::size_t i) noexcept
501 return i < 1 ? c :
'\0';
506 template <
char... Cs>
508 struct is_null_char {
509 template <
typename T>
510 using fn = std::is_same<std::integral_constant<char, '\0'>, T>;
514 boost::mp11::mp_remove_if_q<boost::mp11::mp_list_c<char, Cs...>, is_null_char>;
516 static_assert(std::tuple_size_v<strip_null> < AR_MAX_CTS_SIZE,
517 "Compile-time string limit reached, consider increasing AR_MAX_CTS_SIZE");
519 template <
char... StrippedCs>
520 [[nodiscard]] constexpr
static auto list_to_string(
521 [[maybe_unused]] boost::mp11::mp_list_c<char, StrippedCs...> chars) noexcept
526 using type = decltype(list_to_string(strip_null{}));
529 template <
char... Cs>
530 using builder_t =
typename builder<Cs...>::type;
540 template <
typename T>
544 template <
char... Cs>
552 template <
typename T>
557 # define AR_STR_CHAR(z, n, tok) arg_router::utility::cts_detail::get(tok, n)
559 # define AR_STR_N(n, tok) \
560 arg_router::utility::cts_detail::builder_t<BOOST_PP_ENUM(n, AR_STR_CHAR, tok)>
572 # define S_(tok) AR_STR_N(AR_MAX_CTS_SIZE, tok)
576 # define AR_STRING(tok) S_(tok)
577 # define AR_STRING_SV(tok) S_(tok)
std::tuple< traits::integral_constant< Cs >... > array_type
constexpr auto operator+([[maybe_unused]] const compile_time_string< OtherCs... > &other) const noexcept
constexpr static std::string_view get() noexcept
typename append< T >::type append_t
constexpr static bool empty() noexcept
constexpr static std::size_t size() noexcept
constexpr T num_digits(T value) noexcept
constexpr T abs(T value) noexcept
constexpr bool is_compile_time_string_like_v
constexpr std::size_t count(std::string_view str) noexcept
constexpr std::size_t size(std::string_view str) noexcept
typename create_sequence_cts< N, C >::type create_sequence_cts_t
typename convert_integral_to_cts< Value >::type convert_integral_to_cts_t
typename convert_to_cts< T >::type convert_to_cts_t
dynamic_string_view operator+(dynamic_string_view a, T &&b)