Files
Cpp-in-Embedded-Systems/Chapter17/cib/libs/stdx/ct_string.hpp
Amar Mahmutbegovic 526e6ec009 rename chapters
2025-02-09 13:11:21 +01:00

149 lines
4.6 KiB
C++

#pragma once
#if __cplusplus >= 202002L
#include <stdx/compiler.hpp>
#include <stdx/utility.hpp>
#include <array>
#include <cstddef>
#include <string_view>
#include <utility>
namespace stdx {
inline namespace v1 {
template <std::size_t N> struct ct_string {
CONSTEVAL ct_string() = default;
// NOLINTNEXTLINE(*-avoid-c-arrays, google-explicit-constructor)
CONSTEVAL explicit(false) ct_string(char const (&str)[N]) {
for (auto i = std::size_t{}; i < N; ++i) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-*)
value[i] = str[i];
}
}
CONSTEVAL explicit(true) ct_string(char const *str, std::size_t sz) {
for (auto i = std::size_t{}; i < sz; ++i) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-*)
value[i] = str[i];
}
}
CONSTEVAL explicit(true) ct_string(std::string_view str)
: ct_string{str.data(), str.size()} {}
[[nodiscard]] constexpr auto begin() LIFETIMEBOUND { return value.begin(); }
[[nodiscard]] constexpr auto end() LIFETIMEBOUND { return value.end() - 1; }
[[nodiscard]] constexpr auto begin() const LIFETIMEBOUND {
return value.begin();
}
[[nodiscard]] constexpr auto end() const LIFETIMEBOUND {
return value.end() - 1;
}
[[nodiscard]] constexpr auto rbegin() const LIFETIMEBOUND {
return ++value.rbegin();
}
[[nodiscard]] constexpr auto rend() const LIFETIMEBOUND {
return value.rend();
}
constexpr static std::integral_constant<std::size_t, N> capacity{};
constexpr static std::integral_constant<std::size_t, N - 1U> size{};
constexpr static std::integral_constant<bool, N == 1U> empty{};
constexpr explicit(true) operator std::string_view() const {
return std::string_view{value.data(), size()};
}
std::array<char, N> value{};
};
template <std::size_t N, std::size_t M>
[[nodiscard]] constexpr auto operator==(ct_string<N> const &lhs,
ct_string<M> const &rhs) -> bool {
return static_cast<std::string_view>(lhs) ==
static_cast<std::string_view>(rhs);
}
template <template <typename C, C...> typename T, char... Cs>
[[nodiscard]] CONSTEVAL auto ct_string_from_type(T<char, Cs...>) {
return ct_string<sizeof...(Cs) + 1U>{{Cs..., 0}};
}
template <ct_string S, template <typename C, C...> typename T>
[[nodiscard]] CONSTEVAL auto ct_string_to_type() {
return [&]<auto... Is>(std::index_sequence<Is...>) {
return T<char, std::get<Is>(S.value)...>{};
}(std::make_index_sequence<S.size()>{});
}
template <ct_string S, char C> [[nodiscard]] consteval auto split() {
constexpr auto it = [] {
for (auto i = S.value.cbegin(); i != S.value.cend(); ++i) {
if (*i == C) {
return i;
}
}
return S.value.cend();
}();
if constexpr (it == S.value.cend()) {
return std::pair{S, ct_string{""}};
} else {
constexpr auto prefix_size =
static_cast<std::size_t>(it - S.value.cbegin());
constexpr auto suffix_size = S.size() - prefix_size;
return std::pair{
ct_string<prefix_size + 1U>{S.value.cbegin(), prefix_size},
ct_string<suffix_size>{it + 1, suffix_size - 1U}};
}
}
template <std::size_t N, std::size_t M>
[[nodiscard]] constexpr auto
operator+(ct_string<N> const &lhs,
ct_string<M> const &rhs) -> ct_string<N + M - 1> {
ct_string<N + M - 1> ret{};
for (auto i = std::size_t{}; i < lhs.size(); ++i) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-*)
ret.value[i] = lhs.value[i];
}
for (auto i = std::size_t{}; i < rhs.size(); ++i) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-*)
ret.value[i + N - 1] = rhs.value[i];
}
return ret;
}
template <ct_string S> struct cts_t {
constexpr static auto value = S;
};
template <ct_string X, ct_string Y>
constexpr auto operator==(cts_t<X>, cts_t<Y>) -> bool {
return X == Y;
}
template <ct_string X, ct_string Y>
constexpr auto operator+(cts_t<X>, cts_t<Y>) {
return cts_t<X + Y>{};
}
namespace detail {
template <std::size_t N> struct ct_helper<ct_string<N>>;
} // namespace detail
template <ct_string Value> CONSTEVAL auto ct() { return cts_t<Value>{}; }
inline namespace literals {
inline namespace ct_string_literals {
template <ct_string S> CONSTEVAL auto operator""_cts() { return S; }
template <ct_string S> CONSTEVAL auto operator""_ctst() { return cts_t<S>{}; }
} // namespace ct_string_literals
} // namespace literals
} // namespace v1
} // namespace stdx
#endif