HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
gstring.hpp
1// Copyright Take Vos 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 "grapheme.hpp"
8#include "unicode_normalization.hpp"
9#include "unicode_grapheme_cluster_break.hpp"
10#include "../utility/module.hpp"
11#include "../strings.hpp"
12#include <vector>
13#include <string>
14
15template<>
16struct std::char_traits<hi::grapheme> {
17 using char_type = hi::grapheme;
18 using int_type = int32_t;
22 using comparison_category = std::strong_ordering;
23
24 static constexpr void assign(char_type& r, char_type const& a) noexcept
25 {
26 r = a;
27 }
28
29 static constexpr char_type *assign(char_type *p, std::size_t count, char_type a) noexcept
30 {
32 for (std::size_t i = 0; i != count; ++i) {
33 p[i] = a;
34 }
35 return p;
36 }
37
38 [[nodiscard]] static constexpr bool eq(char_type a, char_type b) noexcept
39 {
40 return a == b;
41 }
42
43 [[nodiscard]] static constexpr bool lt(char_type a, char_type b) noexcept
44 {
45 return a < b;
46 }
47
48 static constexpr char_type *move(char_type *dst, char_type const *src, std::size_t count) noexcept
49 {
52
53 if (src >= dst) {
54 for (std::size_t i = 0; i != count; ++i) {
55 dst[i] = src[i];
56 }
57 } else {
58 for (std::size_t i = count; i != 0; --i) {
59 dst[i - 1] = src[i - 1];
60 }
61 }
62 return dst;
63 }
64
65 static constexpr char_type *copy(char_type *dst, char_type const *src, std::size_t count) noexcept
66 {
69
70 for (std::size_t i = 0; i != count; ++i) {
71 dst[i] = src[i];
72 }
73 return dst;
74 }
75
76 static constexpr int compare(char_type const *s1, char_type const *s2, std::size_t count) noexcept
77 {
80
81 for (std::size_t i = 0; i != count; ++i) {
82 if (s1[i] != s2[i]) {
83 return s1[i] < s2[i] ? -1 : 1;
84 }
85 }
86 return 0;
87 }
88
89 static constexpr std::size_t length(char_type const *s) noexcept
90 {
92
93 std::size_t i = 0;
94 while (s[i] != '\0') {
95 ++i;
96 }
97 return i;
98 }
99
100 static constexpr char_type const *find(const char_type *p, std::size_t count, const char_type& ch) noexcept
101 {
103
104 for (std::size_t i = 0; i != count; ++i, ++p) {
105 if (*p == ch) {
106 return p;
107 }
108 }
109 return nullptr;
110 }
111
112 static constexpr char_type to_char_type(int_type c) noexcept
113 {
114 auto tmp = hi::char_cast<char_type::value_type>(c);
115 if (tmp > 0x1f'ffff) {
116 tmp = 0;
117 }
118 return char_type{hi::intrinsic_t{}, tmp};
119 }
120
121 static constexpr int_type to_int_type(char_type c) noexcept
122 {
123 return hi::char_cast<int_type>(c.intrinsic());
124 }
125
126 static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept
127 {
128 return c1 == c2;
129 }
130
131 static constexpr int_type eof() noexcept
132 {
133 return -1;
134 }
135
136 static constexpr int_type not_eof(int_type e) noexcept
137 {
138 if (e < 0) {
139 e = 0;
140 }
141 return e;
142 }
143};
144
145namespace hi::inline v1 {
146
147using gstring = std::basic_string<grapheme>;
148using gstring_view = std::basic_string_view<grapheme>;
149
150namespace pmr {
151using gstring = std::pmr::basic_string<grapheme>;
152}
153
163[[nodiscard]] constexpr gstring
164to_gstring(std::u32string_view rhs, unicode_normalize_config config = unicode_normalize_config::NFC()) noexcept
165{
166 hilet normalized_string = unicode_normalize(rhs, config);
167
168 auto r = gstring{};
169 auto break_state = detail::grapheme_break_state{};
170 auto cluster = std::u32string{};
171
172 for (hilet code_point : normalized_string) {
173 if (detail::breaks_grapheme(code_point, break_state)) {
174 if (cluster.size() > 0) {
175 r += grapheme(composed_t{}, cluster);
176 hi_axiom(r.back().valid());
177 }
178 cluster.clear();
179 }
180
181 cluster += code_point;
182 }
183 if (ssize(cluster) != 0) {
184 r += grapheme(composed_t{}, cluster);
185 hi_assert(r.back().valid());
186 }
187 return r;
188}
189
199[[nodiscard]] constexpr gstring
200to_gstring(std::string_view rhs, unicode_normalize_config config = unicode_normalize_config::NFC()) noexcept
201{
202 return to_gstring(to_u32string(rhs), config);
203}
204
214[[nodiscard]] constexpr gstring
215to_gstring(std::string const& rhs, unicode_normalize_config config = unicode_normalize_config::NFC()) noexcept
216{
217 return to_gstring(std::string_view{rhs}, config);
218}
219
225[[nodiscard]] constexpr std::string to_string(gstring_view rhs) noexcept
226{
227 auto r = std::string{};
228 r.reserve(rhs.size());
229 for (hilet c : rhs) {
230 r += to_string(c);
231 }
232 return r;
233}
234
240[[nodiscard]] constexpr std::wstring to_wstring(gstring_view rhs) noexcept
241{
242 auto r = std::wstring{};
243 r.reserve(rhs.size());
244 for (hilet c : rhs) {
245 r += to_wstring(c);
246 }
247 return r;
248}
249
255[[nodiscard]] constexpr std::u32string to_u32string(gstring_view rhs) noexcept
256{
257 auto r = std::u32string{};
258 r.reserve(rhs.size());
259 for (hilet c : rhs) {
260 r += to_u32string(c);
261 }
262 return r;
263}
264
270[[nodiscard]] constexpr std::string to_string(gstring const& rhs) noexcept
271{
272 return to_string(gstring_view{rhs});
273}
274
275} // namespace hi::inline v1
276
277template<>
278struct std::hash<hi::gstring> {
279 [[nodiscard]] std::size_t operator()(hi::gstring const& rhs) noexcept
280 {
281 auto r = std::hash<std::size_t>{}(rhs.size());
282 for (hilet c : rhs) {
283 r = hi::hash_mix_two(r, std::hash<hi::grapheme>{}(c));
284 }
285 return r;
286 }
287};
288
289template<>
290struct std::hash<hi::pmr::gstring> {
291 [[nodiscard]] std::size_t operator()(hi::pmr::gstring const& rhs) noexcept
292 {
293 auto r = std::hash<std::size_t>{}(rhs.size());
294 for (hilet c : rhs) {
295 r = hi::hash_mix_two(r, std::hash<hi::grapheme>{}(c));
296 }
297 return r;
298 }
299};
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:199
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253
#define hi_axiom_not_null(expression,...)
Assert if an expression is not nullptr.
Definition assert.hpp:272
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
constexpr std::string to_string(std::u32string_view rhs) noexcept
Conversion from UTF-32 to UTF-8.
Definition to_string.hpp:215
constexpr std::u32string to_u32string(std::u32string_view rhs) noexcept
Identity conversion from UTF-32 to UTF-32.
Definition to_string.hpp:23
constexpr std::wstring to_wstring(std::u32string_view rhs) noexcept
Conversion from UTF-32 to wide-string (UTF-16/32).
Definition to_string.hpp:155
DOXYGEN BUG.
Definition algorithm.hpp:13
constexpr std::u32string unicode_normalize(std::u32string_view text, unicode_normalize_config config=unicode_normalize_config::NFC()) noexcept
Convert text to a Unicode composed normal form.
Definition unicode_normalization.hpp:303
geometry/margins.hpp
Definition cache.hpp:11
Definition grapheme.hpp:29
A grapheme-cluster, what a user thinks a character is.
Definition grapheme.hpp:42
Definition unicode_normalization.hpp:19
Tag used in constructors to set the intrinsic value of that object.
Definition utility.hpp:242
T assign(T... args)
T eq(T... args)
T compare(T... args)
T copy(T... args)
T count(T... args)
T eof(T... args)
T eq_int_type(T... args)
T find(T... args)
T length(T... args)
T move(T... args)
T not_eof(T... args)
T operator()(T... args)
T reserve(T... args)
T size(T... args)
T to_char_type(T... args)
T to_int_type(T... args)