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 }
177 cluster.clear();
178 }
179
180 cluster += code_point;
181 }
182 if (ssize(cluster) != 0) {
183 r += grapheme(composed_t{}, cluster);
184 }
185 return r;
186}
187
197[[nodiscard]] constexpr gstring
198to_gstring(std::string_view rhs, unicode_normalize_config config = unicode_normalize_config::NFC()) noexcept
199{
200 return to_gstring(to_u32string(rhs), config);
201}
202
212[[nodiscard]] constexpr gstring
213to_gstring(std::string const& rhs, unicode_normalize_config config = unicode_normalize_config::NFC()) noexcept
214{
215 return to_gstring(std::string_view{rhs}, config);
216}
217
223[[nodiscard]] constexpr std::string to_string(gstring_view rhs) noexcept
224{
225 auto r = std::string{};
226 r.reserve(rhs.size());
227 for (hilet c : rhs) {
228 r += to_string(c);
229 }
230 return r;
231}
232
238[[nodiscard]] constexpr std::wstring to_wstring(gstring_view rhs) noexcept
239{
240 auto r = std::wstring{};
241 r.reserve(rhs.size());
242 for (hilet c : rhs) {
243 r += to_wstring(c);
244 }
245 return r;
246}
247
253[[nodiscard]] constexpr std::u32string to_u32string(gstring_view rhs) noexcept
254{
255 auto r = std::u32string{};
256 r.reserve(rhs.size());
257 for (hilet c : rhs) {
258 r += to_u32string(c);
259 }
260 return r;
261}
262
268[[nodiscard]] constexpr std::string to_string(gstring const& rhs) noexcept
269{
270 return to_string(gstring_view{rhs});
271}
272
273} // namespace hi::inline v1
274
275template<>
276struct std::hash<hi::gstring> {
277 [[nodiscard]] std::size_t operator()(hi::gstring const& rhs) noexcept
278 {
279 auto r = std::hash<std::size_t>{}(rhs.size());
280 for (hilet c : rhs) {
281 r = hi::hash_mix_two(r, std::hash<hi::grapheme>{}(c));
282 }
283 return r;
284 }
285};
286
287template<>
288struct std::hash<hi::pmr::gstring> {
289 [[nodiscard]] std::size_t operator()(hi::pmr::gstring const& rhs) noexcept
290 {
291 auto r = std::hash<std::size_t>{}(rhs.size());
292 for (hilet c : rhs) {
293 r = hi::hash_mix_two(r, std::hash<hi::grapheme>{}(c));
294 }
295 return r;
296 }
297};
#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)