HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
grapheme.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 "../utility.hpp"
8#include "../strings.hpp"
9#include "../unfair_mutex.hpp"
10#include "../cast.hpp"
11#include "../stable_set.hpp"
12#include <cstdint>
13#include <string>
14#include <string_view>
15#include <cstddef>
16#include <memory>
17#include <vector>
18#include <algorithm>
19#include <bit>
20
21namespace hi::inline v1 {
22namespace detail {
23
24inline auto long_graphemes = ::hi::stable_set<std::u32string>{};
25
26} // namespace detail
27
28struct composed_t {};
29
41struct grapheme {
42 using value_type = uint32_t;
43
53 value_type _value;
54
55 constexpr grapheme() noexcept = default;
56 constexpr grapheme(grapheme const&) noexcept = default;
57 constexpr grapheme(grapheme&&) noexcept = default;
58 constexpr grapheme& operator=(grapheme const&) noexcept = default;
59 constexpr grapheme& operator=(grapheme&&) noexcept = default;
60
61 constexpr grapheme(nullptr_t) noexcept : _value(0x1f'ffff) {}
62
65 constexpr explicit grapheme(char32_t code_point) noexcept : _value(truncate<value_type>(code_point))
66 {
67 hi_axiom(code_point <= 0x10ffff);
68 }
69
70 constexpr explicit grapheme(char ascii_char) noexcept : _value(truncate<value_type>(ascii_char))
71 {
72 hi_axiom(ascii_char >= 0 and ascii_char <= 0x7f);
73 }
74
77 constexpr grapheme& operator=(char32_t code_point) noexcept
78 {
79 _value = truncate<value_type>(code_point);
80 return *this;
81 }
82
85 constexpr grapheme& operator=(char ascii_char) noexcept
86 {
87 hi_axiom(ascii_char >= 0 and ascii_char <= 0x7f);
88 _value = truncate<value_type>(ascii_char);
89 return *this;
90 }
91
96 explicit grapheme(std::u32string_view code_points) noexcept;
97
102 explicit grapheme(composed_t, std::u32string_view code_points) noexcept;
103
106 [[nodiscard]] static constexpr grapheme eof() noexcept
107 {
108 grapheme r;
109 r._value = 0x1f'ffff;
110 return r;
111 }
112
115 constexpr void clear() noexcept
116 {
117 _value = 0x1f'ffff;
118 }
119
122 [[nodiscard]] constexpr bool empty() const noexcept
123 {
124 return _value == 0x1f'ffff;
125 }
126
129 constexpr operator bool() const noexcept
130 {
131 return not empty();
132 }
133
141 [[nodiscard]] bool valid() const noexcept;
142
143 [[nodiscard]] std::u32string const& long_grapheme() const noexcept
144 {
145 hi_axiom(_value >= 0x10'0000 and _value < 0x1f'ffff);
146 return detail::long_graphemes[_value - 0x11'0000];
147 }
148
151 [[nodiscard]] constexpr std::size_t size() const noexcept
152 {
153 if (_value == 0x1f'ffff) {
154 return 0;
155
156 } else if (_value <= 0x10'ffff) {
157 return 1;
158
159 } else {
160 return long_grapheme().size();
161 }
162 }
163
170 [[nodiscard]] constexpr char32_t operator[](size_t i) const noexcept
171 {
172 hi_axiom(i < size());
173
174 if (_value <= 0x10'ffff) {
175 return truncate<char32_t>(_value);
176 } else {
177 return long_grapheme()[i];
178 }
179 }
180
188 template<size_t I>
189 [[nodiscard]] friend constexpr char32_t get(grapheme const& rhs) noexcept
190 {
191 hi_axiom(I < rhs.size());
192
193 if (rhs._value <= 0x10'ffff) {
194 return rhs._value;
195 } else {
196 return rhs.long_grapheme()[I];
197 }
198 }
199
202 [[nodiscard]] constexpr std::u32string composed() const noexcept
203 {
204 if (_value <= 0x10'ffff) {
205 return std::u32string{truncate<char32_t>(_value)};
206 } else {
207 return long_grapheme();
208 }
209 }
210
213 [[nodiscard]] std::u32string decomposed() const noexcept;
214
217 [[nodiscard]] friend constexpr bool operator==(grapheme const&, grapheme const&) noexcept = default;
218
221 [[nodiscard]] friend constexpr std::strong_ordering operator<=>(grapheme const& lhs, grapheme const& rhs) noexcept
222 {
223 return lhs.decomposed() <=> rhs.decomposed();
224 }
225
226 [[nodiscard]] friend constexpr bool operator==(grapheme const& lhs, char32_t const& rhs) noexcept
227 {
228 return lhs == grapheme{rhs};
229 }
230
231 [[nodiscard]] friend constexpr std::strong_ordering operator<=>(grapheme const& lhs, char32_t const& rhs) noexcept
232 {
233 return lhs <=> grapheme{rhs};
234 }
235
236 [[nodiscard]] friend constexpr bool operator==(grapheme const& lhs, char const& rhs) noexcept
237 {
238 return lhs == grapheme{rhs};
239 }
240
241 [[nodiscard]] friend constexpr std::strong_ordering operator<=>(grapheme const& lhs, char const& rhs) noexcept
242 {
243 return lhs <=> grapheme{rhs};
244 }
245
246 [[nodiscard]] friend std::string to_string(grapheme const& rhs) noexcept
247 {
248 return hi::to_string(rhs.composed());
249 }
250
251 [[nodiscard]] friend std::u32string to_u32string(grapheme const& rhs) noexcept
252 {
253 return rhs.composed();
254 }
255};
256
257} // namespace hi::inline v1
258
259template<>
260struct std::hash<hi::grapheme> {
261 [[nodiscard]] std::size_t operator()(hi::grapheme const& rhs) const noexcept
262 {
263 return std::hash<hi::grapheme::value_type>{}(rhs._value);
264 }
265};
Utilities used by the HikoGUI library itself.
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
@ grapheme
The gui_event has grapheme data.
STL namespace.
DOXYGEN BUG.
Definition algorithm.hpp:15
The HikoGUI namespace.
Definition ascii.hpp:19
Definition grapheme.hpp:28
A grapheme-cluster, what a user thinks a character is.
Definition grapheme.hpp:41
std::u32string decomposed() const noexcept
Get a list of code-point normalized to NFD.
constexpr bool empty() const noexcept
Check if the grapheme is empty.
Definition grapheme.hpp:122
bool valid() const noexcept
Check if the grapheme is valid.
constexpr char32_t operator[](size_t i) const noexcept
Get the code-point at the given index.
Definition grapheme.hpp:170
static constexpr grapheme eof() noexcept
Create empty grapheme / end-of-file.
Definition grapheme.hpp:106
grapheme(composed_t, std::u32string_view code_points) noexcept
Encode a grapheme from a list of code-points.
constexpr void clear() noexcept
Clear the grapheme.
Definition grapheme.hpp:115
constexpr grapheme(char32_t code_point) noexcept
Encode a single code-point.
Definition grapheme.hpp:65
constexpr grapheme & operator=(char ascii_char) noexcept
Encode a single code-point.
Definition grapheme.hpp:85
value_type _value
A pointer to a grapheme.
Definition grapheme.hpp:53
grapheme(std::u32string_view code_points) noexcept
Encode a grapheme from a list of code-points.
constexpr std::u32string composed() const noexcept
Get a list of code-point normalized to NFC.
Definition grapheme.hpp:202
constexpr grapheme & operator=(char32_t code_point) noexcept
Encode a single code-point.
Definition grapheme.hpp:77
constexpr std::size_t size() const noexcept
Return the number of code-points encoded in the grapheme.
Definition grapheme.hpp:151
friend constexpr char32_t get(grapheme const &rhs) noexcept
Get the code-point at the given index.
Definition grapheme.hpp:189
T operator()(T... args)
T to_string(T... args)