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 <string>
8#include <string_view>
9#include <format>
10#include <array>
11#include <ranges>
12#include "../macros.hpp"
13#include "assert.hpp"
14#include "cast.hpp"
15#include "debugger.hpp"
16#include "exception.hpp"
17#include "misc.hpp"
18
19hi_export_module(hikogui.utility.fixed_string);
20
21hi_export namespace hi { inline namespace v1 {
22
40template<size_t N>
42 using value_type = char;
43
44 std::array<char, N> _str = {};
45
46 constexpr fixed_string() noexcept = default;
47 constexpr fixed_string(fixed_string const&) noexcept = default;
48 constexpr fixed_string(fixed_string&&) noexcept = default;
49 constexpr fixed_string& operator=(fixed_string const&) noexcept = default;
50 constexpr fixed_string& operator=(fixed_string&&) noexcept = default;
51
52 template<std::size_t O>
53 constexpr fixed_string(char const (&str)[O]) noexcept
54 requires((O - 1) == N)
55 {
56 for (auto i = 0_uz; i != (O - 1); ++i) {
57 _str[i] = str[i];
58 }
59 }
60
63 template<std::invocable F>
64 constexpr fixed_string(F const& f) noexcept
65 {
66 auto str = f();
67
68 hi_assert(str.size() == N);
69 for (auto i = 0_uz; i != str.size(); ++i) {
70 _str[i] = char_cast<char>(str[i]);
71 }
72 }
73
74 constexpr operator std::string_view() const noexcept
75 {
76 return std::string_view{_str.data(), size()};
77 }
78
79 constexpr operator std::string() const noexcept
80 {
81 return std::string{_str.data(), size()};
82 }
83
84 [[nodiscard]] constexpr std::size_t size() const noexcept
85 {
86 return N;
87 }
88
89 [[nodiscard]] constexpr bool empty() const noexcept
90 {
91 return N == 0;
92 }
93
94 template<size_t I>
95 [[nodiscard]] constexpr friend char& get(fixed_string& a) noexcept
96 {
97 return std::get<I>(a._str);
98 }
99
100 template<size_t I>
101 [[nodiscard]] constexpr friend char const& get(fixed_string const& a) noexcept
102 {
103 return std::get<I>(a._str);
104 }
105
106 [[nodiscard]] constexpr char& operator[](size_t index) noexcept
107 {
108#ifndef NDEBUG
109 if (not(index < N)) {
111 }
112#endif
113 return _str[index];
114 }
115
116 [[nodiscard]] constexpr char const& operator[](size_t index) const noexcept
117 {
118#ifndef NDEBUG
119 if (not(index < N)) {
121 }
122#endif
123 return _str[index];
124 }
125
126 [[nodiscard]] constexpr auto begin() noexcept
127 {
128 return _str.begin();
129 }
130
131 [[nodiscard]] constexpr auto end() noexcept
132 {
133 return _str.begin() + size();
134 }
135
136 [[nodiscard]] constexpr bool operator==(fixed_string const& rhs) const noexcept = default;
137 [[nodiscard]] constexpr auto operator<=>(fixed_string const& rhs) const noexcept = default;
138
139 template<size_t O>
140 [[nodiscard]] constexpr bool operator==(fixed_string<O> const& rhs) const noexcept
141 requires(O != N)
142 {
143 return false;
144 }
145
146 template<size_t O>
147 [[nodiscard]] constexpr auto operator<=>(fixed_string<O> const& rhs) const noexcept
148 requires(O != N)
149 {
150 return static_cast<std::string_view>(*this) <=> static_cast<std::string_view>(rhs);
151 }
152
153 [[nodiscard]] constexpr bool operator==(std::string_view rhs) const noexcept
154 {
155 return static_cast<std::string_view>(*this) == rhs;
156 }
157
158 [[nodiscard]] constexpr auto operator<=>(std::string_view rhs) const noexcept
159 {
160 return static_cast<std::string_view>(*this) <=> rhs;
161 }
162
163 [[nodiscard]] constexpr bool operator==(std::string const& rhs) const noexcept
164 {
165 return static_cast<std::string_view>(*this) == rhs;
166 }
167
168 [[nodiscard]] constexpr auto operator<=>(std::string const& rhs) const noexcept
169 {
170 return static_cast<std::string_view>(*this) <=> rhs;
171 }
172
173 [[nodiscard]] constexpr bool operator==(char const *rhs) const noexcept
174 {
175 return static_cast<std::string_view>(*this) == rhs;
176 }
177
178 [[nodiscard]] constexpr auto operator<=>(char const *rhs) const noexcept
179 {
180 return static_cast<std::string_view>(*this) <=> rhs;
181 }
182
183 template<size_t O>
184 [[nodiscard]] constexpr bool operator==(char const (&rhs)[O]) const noexcept
185 {
186 return *this == fixed_string<O - 1>(rhs);
187 }
188
189 template<size_t O>
190 [[nodiscard]] constexpr auto operator<=>(char const (&rhs)[O]) const noexcept
191 {
192 return *this <=> fixed_string<O - 1>(rhs);
193 }
194
197 template<size_t R>
198 [[nodiscard]] constexpr auto operator+(fixed_string<R> const& rhs) const noexcept
199 {
200 auto r = fixed_string<N + R>{};
201 auto dst_i = 0_uz;
202 for (auto src_i = 0_uz; src_i != N; ++src_i, ++dst_i) {
203 r[dst_i] = (*this)[src_i];
204 }
205 for (auto src_i = 0_uz; src_i != R; ++src_i, ++dst_i) {
206 r[dst_i] = rhs[src_i];
207 }
208
209 return r;
210 }
211
212 template<size_t R>
213 [[nodiscard]] constexpr auto operator+(char const (&rhs)[R]) const noexcept
214 {
215 return *this + fixed_string<R - 1>(rhs);
216 }
217
222 template<size_t R>
223 [[nodiscard]] constexpr auto operator/(fixed_string<R> const& rhs) const noexcept
224 {
225 constexpr auto has_dot = N != 0 and R != 0 ? 1_uz : 0_uz;
227
228 auto dst_i = 0_uz;
229 for (auto src_i = 0_uz; src_i != N; ++src_i, ++dst_i) {
230 r[dst_i] = (*this)[src_i];
231 }
232
233 if (has_dot) {
234 r[dst_i++] = '/';
235 }
236
237 for (auto src_i = 0_uz; src_i != R; ++src_i, ++dst_i) {
238 r[dst_i] = rhs[src_i];
239 }
240
241 return r;
242 }
243
244 template<size_t R>
245 [[nodiscard]] constexpr auto operator/(char const (&rhs)[R]) const noexcept
246 {
247 return *this / fixed_string<R - 1>(rhs);
248 }
249};
250
251template<fixed_string Tag>
252[[nodiscard]] consteval uint32_t fourcc() noexcept
253{
254 static_assert(Tag.size() == 4, "fourcc must get a 4 character fixed_string");
255
256 return (static_cast<uint32_t>(get<0>(Tag)) << 24) | (static_cast<uint32_t>(get<1>(Tag)) << 16) |
257 (static_cast<uint32_t>(get<2>(Tag)) << 8) | static_cast<uint32_t>(get<3>(Tag));
258}
259
260template<fixed_string Tag>
261consteval uint32_t operator"" _fcc()
262{
263 return fourcc<Tag>();
264}
265
266template<std::size_t N>
267fixed_string(char const (&str)[N]) -> fixed_string<N - 1>;
268
269template<std::invocable F>
270fixed_string(F const& f) -> fixed_string<std::ranges::size(F{}())>;
271
272#define hi_to_fixed_string(x) \
273 ::hi::fixed_string \
274 { \
275 [] { \
276 return x; \
277 } \
278 }
279
280}} // namespace hi::inline v1
281
282hi_export template<std::size_t N, typename CharT>
283struct std::formatter<hi::fixed_string<N>, CharT> : std::formatter<std::string_view, CharT> {
284 constexpr auto format(hi::fixed_string<N> const& t, auto& fc) const
285 {
286 return std::formatter<std::string_view, CharT>::format(static_cast<std::string_view>(t), fc);
287 }
288};
Utilities to assert and bound check.
Functions for casting values between types savely.
DOXYGEN BUG.
Definition algorithm.hpp:16
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
A string which may be used as a none-type template parameter.
Definition fixed_string.hpp:41
constexpr auto operator/(fixed_string< R > const &rhs) const noexcept
Join two strings with a slash '/'.
Definition fixed_string.hpp:223
constexpr fixed_string(F const &f) noexcept
Create a fixed string from function returning a string-like.
Definition fixed_string.hpp:64
constexpr auto operator+(fixed_string< R > const &rhs) const noexcept
Append two strings.
Definition fixed_string.hpp:198
T begin(T... args)
T data(T... args)
T terminate(T... args)