-
Notifications
You must be signed in to change notification settings - Fork 6
/
ct_string.hpp
128 lines (109 loc) · 4.03 KB
/
ct_string.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#pragma once
#if __cplusplus >= 202002L
#include <stdx/compiler.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.cbegin(), 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;
}
inline namespace literals {
inline namespace ct_string_literals {
template <typename T, T... Cs> CONSTEVAL auto operator""_cts() {
return ct_string<sizeof...(Cs) + 1U>{{Cs..., 0}};
}
} // namespace ct_string_literals
} // namespace literals
} // namespace v1
} // namespace stdx
#endif