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#include <type_traits>
15
16template<>
17struct std::char_traits<hi::grapheme> {
18 using char_type = hi::grapheme;
19 using int_type = std::make_signed_t<char_type::value_type>;
23 using comparison_category = std::strong_ordering;
24
25 static constexpr void assign(char_type& r, char_type const& a) noexcept
26 {
27 r = a;
28 }
29
30 static constexpr char_type *assign(char_type *p, std::size_t count, char_type a) noexcept
31 {
33 for (std::size_t i = 0; i != count; ++i) {
34 p[i] = a;
35 }
36 return p;
37 }
38
39 [[nodiscard]] static constexpr bool eq(char_type a, char_type b) noexcept
40 {
41 return a == b;
42 }
43
44 [[nodiscard]] static constexpr bool lt(char_type a, char_type b) noexcept
45 {
46 return a < b;
47 }
48
49 static constexpr char_type *move(char_type *dst, char_type const *src, std::size_t count) noexcept
50 {
53
54 if (src >= dst) {
55 for (std::size_t i = 0; i != count; ++i) {
56 dst[i] = src[i];
57 }
58 } else {
59 for (std::size_t i = count; i != 0; --i) {
60 dst[i - 1] = src[i - 1];
61 }
62 }
63 return dst;
64 }
65
66 static constexpr char_type *copy(char_type *dst, char_type const *src, std::size_t count) noexcept
67 {
70
71 for (std::size_t i = 0; i != count; ++i) {
72 dst[i] = src[i];
73 }
74 return dst;
75 }
76
77 static constexpr int compare(char_type const *s1, char_type const *s2, std::size_t count) noexcept
78 {
81
82 for (std::size_t i = 0; i != count; ++i) {
83 if (s1[i] != s2[i]) {
84 return s1[i] < s2[i] ? -1 : 1;
85 }
86 }
87 return 0;
88 }
89
90 static constexpr std::size_t length(char_type const *s) noexcept
91 {
93
94 std::size_t i = 0;
95 while (s[i] != '\0') {
96 ++i;
97 }
98 return i;
99 }
100
101 static constexpr char_type const *find(const char_type *p, std::size_t count, const char_type& ch) noexcept
102 {
104
105 for (std::size_t i = 0; i != count; ++i, ++p) {
106 if (*p == ch) {
107 return p;
108 }
109 }
110 return nullptr;
111 }
112
113 static constexpr char_type to_char_type(int_type c) noexcept
114 {
115 return c < 0 ? char_type{U'\ufffd'} : char_type{hi::intrinsic_t{}, hi::char_cast<char_type::value_type>(c)};
116 }
117
118 static constexpr int_type to_int_type(char_type c) noexcept
119 {
120 return hi::char_cast<int_type>(c.intrinsic());
121 }
122
123 static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept
124 {
125 return c1 == c2;
126 }
127
128 static constexpr int_type eof() noexcept
129 {
130 return -1;
131 }
132
133 static constexpr int_type not_eof(int_type e) noexcept
134 {
135 return e < 0 ? 0 : e;
136 }
137};
138
139namespace hi::inline v1 {
140
141using gstring = std::basic_string<grapheme>;
142using gstring_view = std::basic_string_view<grapheme>;
143
144namespace pmr {
145using gstring = std::pmr::basic_string<grapheme>;
146}
147
157[[nodiscard]] constexpr gstring
158to_gstring(std::u32string_view rhs, unicode_normalize_config config = unicode_normalize_config::NFC()) noexcept
159{
160 hilet normalized_string = unicode_normalize(rhs, config);
161
162 auto r = gstring{};
163 auto break_state = detail::grapheme_break_state{};
164 auto cluster = std::u32string{};
165
166 for (hilet code_point : normalized_string) {
167 if (detail::breaks_grapheme(code_point, break_state)) {
168 if (cluster.size() > 0) {
169 r += grapheme(composed_t{}, cluster);
170 }
171 cluster.clear();
172 }
173
174 cluster += code_point;
175 }
176 if (ssize(cluster) != 0) {
177 r += grapheme(composed_t{}, cluster);
178 }
179 return r;
180}
181
191[[nodiscard]] constexpr gstring
192to_gstring(std::string_view rhs, unicode_normalize_config config = unicode_normalize_config::NFC()) noexcept
193{
194 return to_gstring(to_u32string(rhs), config);
195}
196
206[[nodiscard]] constexpr gstring
207to_gstring(std::string const& rhs, unicode_normalize_config config = unicode_normalize_config::NFC()) noexcept
208{
209 return to_gstring(std::string_view{rhs}, config);
210}
211
217[[nodiscard]] constexpr std::string to_string(gstring_view rhs) noexcept
218{
219 auto r = std::string{};
220 r.reserve(rhs.size());
221 for (hilet c : rhs) {
222 r += to_string(c);
223 }
224 return r;
225}
226
232[[nodiscard]] constexpr std::wstring to_wstring(gstring_view rhs) noexcept
233{
234 auto r = std::wstring{};
235 r.reserve(rhs.size());
236 for (hilet c : rhs) {
237 r += to_wstring(c);
238 }
239 return r;
240}
241
247[[nodiscard]] constexpr std::u32string to_u32string(gstring_view rhs) noexcept
248{
249 auto r = std::u32string{};
250 r.reserve(rhs.size());
251 for (hilet c : rhs) {
252 r += to_u32string(c);
253 }
254 return r;
255}
256
262[[nodiscard]] constexpr std::string to_string(gstring const& rhs) noexcept
263{
264 return to_string(gstring_view{rhs});
265}
266
267} // namespace hi::inline v1
268
269template<>
270struct std::hash<hi::gstring> {
271 [[nodiscard]] std::size_t operator()(hi::gstring const& rhs) noexcept
272 {
273 auto r = std::hash<std::size_t>{}(rhs.size());
274 for (hilet c : rhs) {
275 r = hi::hash_mix_two(r, std::hash<hi::grapheme>{}(c));
276 }
277 return r;
278 }
279};
280
281template<>
282struct std::hash<hi::pmr::gstring> {
283 [[nodiscard]] std::size_t operator()(hi::pmr::gstring const& rhs) noexcept
284 {
285 auto r = std::hash<std::size_t>{}(rhs.size());
286 for (hilet c : rhs) {
287 r = hi::hash_mix_two(r, std::hash<hi::grapheme>{}(c));
288 }
289 return r;
290 }
291};
#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
DOXYGEN BUG.
Definition algorithm.hpp:13
constexpr gstring to_gstring(std::u32string_view rhs, unicode_normalize_config config=unicode_normalize_config::NFC()) noexcept
Convert a UTF-32 string-view to a grapheme-string.
Definition gstring.hpp:158
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:31
A grapheme-cluster, what a user thinks a character is.
Definition grapheme.hpp:44
Definition unicode_normalization.hpp:19
Tag used in constructors to set the intrinsic value of that object.
Definition utility.hpp:230
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)