HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
fixed_string.hpp
1// Copyright Take Vos 2021-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "utility.hpp"
8#include "cast.hpp"
9#include "assert.hpp"
10#include <string>
11#include <string_view>
12#include <format>
13#include <array>
14#include <ranges>
15
16namespace hi::inline v1 {
17
35template<size_t N>
37 using value_type = char;
38
39 std::array<char, N> _str = {};
40
41 constexpr fixed_string() noexcept = default;
42 constexpr fixed_string(fixed_string const&) noexcept = default;
43 constexpr fixed_string(fixed_string&&) noexcept = default;
44 constexpr fixed_string& operator=(fixed_string const&) noexcept = default;
45 constexpr fixed_string& operator=(fixed_string&&) noexcept = default;
46
47 template<std::size_t O>
48 constexpr fixed_string(char const (&str)[O]) noexcept
49 requires((O - 1) == N)
50 {
51 for (auto i = 0_uz; i != (O - 1); ++i) {
52 _str[i] = str[i];
53 }
54 }
55
58 template<std::invocable F>
59 constexpr fixed_string(F const& f) noexcept
60 {
61 auto str = f();
62
63 hi_assert(str.size() == N);
64 for (auto i = 0_uz; i != str.size(); ++i) {
65 _str[i] = char_cast<char>(str[i]);
66 }
67 }
68
69 constexpr operator std::string_view() const noexcept
70 {
71 return std::string_view{_str.data(), size()};
72 }
73
74 constexpr operator std::string() const noexcept
75 {
76 return std::string{_str.data(), size()};
77 }
78
79 [[nodiscard]] constexpr std::size_t size() const noexcept
80 {
81 return N;
82 }
83
84 [[nodiscard]] constexpr bool empty() const noexcept
85 {
86 return N == 0;
87 }
88
89 template<size_t I>
90 [[nodiscard]] constexpr friend char& get(fixed_string& a) noexcept
91 {
92 return std::get<I>(a._str);
93 }
94
95 template<size_t I>
96 [[nodiscard]] constexpr friend char const& get(fixed_string const& a) noexcept
97 {
98 return std::get<I>(a._str);
99 }
100
101 [[nodiscard]] constexpr char& operator[](size_t index) noexcept
102 {
103#ifndef NDEBUG
104 if (not(index < N)) {
106 }
107#endif
108 return _str[index];
109 }
110
111 [[nodiscard]] constexpr char const& operator[](size_t index) const noexcept
112 {
113#ifndef NDEBUG
114 if (not(index < N)) {
116 }
117#endif
118 return _str[index];
119 }
120
121 [[nodiscard]] constexpr auto begin() noexcept
122 {
123 return _str.begin();
124 }
125
126 [[nodiscard]] constexpr auto end() noexcept
127 {
128 return _str.begin() + size();
129 }
130
131 [[nodiscard]] constexpr bool operator==(fixed_string const& rhs) const noexcept = default;
132 [[nodiscard]] constexpr auto operator<=>(fixed_string const& rhs) const noexcept = default;
133
134 template<size_t O>
135 [[nodiscard]] constexpr bool operator==(fixed_string<O> const& rhs) const noexcept
136 requires(O != N)
137 {
138 return false;
139 }
140
141 template<size_t O>
142 [[nodiscard]] constexpr auto operator<=>(fixed_string<O> const& rhs) const noexcept
143 requires(O != N)
144 {
145 return static_cast<std::string_view>(*this) <=> static_cast<std::string_view>(rhs);
146 }
147
148 [[nodiscard]] constexpr bool operator==(std::string_view rhs) const noexcept
149 {
150 return static_cast<std::string_view>(*this) == rhs;
151 }
152
153 [[nodiscard]] constexpr auto operator<=>(std::string_view rhs) const noexcept
154 {
155 return static_cast<std::string_view>(*this) <=> rhs;
156 }
157
158 [[nodiscard]] constexpr bool operator==(std::string const& rhs) const noexcept
159 {
160 return static_cast<std::string_view>(*this) == rhs;
161 }
162
163 [[nodiscard]] constexpr auto operator<=>(std::string const& rhs) const noexcept
164 {
165 return static_cast<std::string_view>(*this) <=> rhs;
166 }
167
168 [[nodiscard]] constexpr bool operator==(char const *rhs) const noexcept
169 {
170 return static_cast<std::string_view>(*this) == rhs;
171 }
172
173 [[nodiscard]] constexpr auto operator<=>(char const *rhs) const noexcept
174 {
175 return static_cast<std::string_view>(*this) <=> rhs;
176 }
177
178 template<size_t O>
179 [[nodiscard]] constexpr bool operator==(char const (&rhs)[O]) const noexcept
180 {
181 return *this == fixed_string<O - 1>(rhs);
182 }
183
184 template<size_t O>
185 [[nodiscard]] constexpr auto operator<=>(char const (&rhs)[O]) const noexcept
186 {
187 return *this <=> fixed_string<O - 1>(rhs);
188 }
189
192 template<size_t R>
193 [[nodiscard]] constexpr auto operator+(fixed_string<R> const& rhs) const noexcept
194 {
195 auto r = fixed_string<N + R>{};
196 auto dst_i = 0_uz;
197 for (auto src_i = 0_uz; src_i != N; ++src_i, ++dst_i) {
198 r[dst_i] = (*this)[src_i];
199 }
200 for (auto src_i = 0_uz; src_i != R; ++src_i, ++dst_i) {
201 r[dst_i] = rhs[src_i];
202 }
203
204 return r;
205 }
206
207 template<size_t R>
208 [[nodiscard]] constexpr auto operator+(char const (&rhs)[R]) const noexcept
209 {
210 return *this + fixed_string<R - 1>(rhs);
211 }
212
217 template<size_t R>
218 [[nodiscard]] constexpr auto operator/(fixed_string<R> const& rhs) const noexcept
219 {
220 constexpr auto has_dot = N != 0 and R != 0 ? 1_uz : 0_uz;
222
223 auto dst_i = 0_uz;
224 for (auto src_i = 0_uz; src_i != N; ++src_i, ++dst_i) {
225 r[dst_i] = (*this)[src_i];
226 }
227
228 if (has_dot) {
229 r[dst_i++] = '/';
230 }
231
232 for (auto src_i = 0_uz; src_i != R; ++src_i, ++dst_i) {
233 r[dst_i] = rhs[src_i];
234 }
235
236 return r;
237 }
238
239 template<size_t R>
240 [[nodiscard]] constexpr auto operator/(char const (&rhs)[R]) const noexcept
241 {
242 return *this / fixed_string<R - 1>(rhs);
243 }
244};
245
246template<fixed_string Tag>
247[[nodiscard]] consteval uint32_t fourcc() noexcept
248{
249 static_assert(Tag.size() == 4, "fourcc must get a 4 character fixed_string");
250
251 return (static_cast<uint32_t>(get<0>(Tag)) << 24) | (static_cast<uint32_t>(get<1>(Tag)) << 16) |
252 (static_cast<uint32_t>(get<2>(Tag)) << 8) | static_cast<uint32_t>(get<3>(Tag));
253}
254
255template<fixed_string Tag>
256consteval uint32_t operator"" _fcc()
257{
258 return fourcc<Tag>();
259}
260
261template<std::size_t N>
262fixed_string(char const (&str)[N]) -> fixed_string<N - 1>;
263
264template<std::invocable F>
265fixed_string(F const& f) -> fixed_string<std::ranges::size(F{}())>;
266
272template<std::size_t L, std::size_t R>
273[[deprecated("msvc-bug-10291680")]] [[nodiscard]] constexpr auto join_path(fixed_string<L> const &lhs, fixed_string<R> const &rhs) noexcept
274{
275 return lhs / rhs;
276}
277
283template<std::size_t L, std::size_t R>
284[[deprecated("msvc-bug-10291680")]] [[nodiscard]] constexpr auto join_path(fixed_string<L> const& lhs, char const (&rhs)[R]) noexcept
285{
286 return lhs / rhs;
287}
288
289#define hi_to_fixed_string(x) \
290 ::hi::fixed_string \
291 { \
292 [] { \
293 return x; \
294 } \
295 }
296
297} // namespace hi::inline v1
298
299template<std::size_t N, typename CharT>
300struct std::formatter<hi::fixed_string<N>, CharT> : std::formatter<std::string_view, CharT> {
301 constexpr auto format(hi::fixed_string<N> const& t, auto& fc)
302 {
303 return std::formatter<std::string_view, CharT>::format(static_cast<std::string_view>(t), fc);
304 }
305};
Utilities to assert and bound check.
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:199
Utilities used by the HikoGUI library itself.
DOXYGEN BUG.
Definition algorithm.hpp:13
constexpr auto join_path(fixed_string< L > const &lhs, fixed_string< R > const &rhs) noexcept
lhs / rhs
Definition fixed_string.hpp:273
geometry/margins.hpp
Definition cache.hpp:11
A string which may be used as a none-type template parameter.
Definition fixed_string.hpp:36
constexpr auto operator/(fixed_string< R > const &rhs) const noexcept
Join two strings with a slash '/'.
Definition fixed_string.hpp:218
constexpr fixed_string(F const &f) noexcept
Create a fixed string from function returning a string-like.
Definition fixed_string.hpp:59
constexpr auto operator+(fixed_string< R > const &rhs) const noexcept
Append two strings.
Definition fixed_string.hpp:193
T begin(T... args)
T data(T... args)
T end(T... args)
T terminate(T... args)