HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
grapheme.hpp
1// Copyright Take Vos 2019-2021.
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 "../required.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
63 constexpr explicit grapheme(char32_t code_point) noexcept : _value(truncate<value_type>(code_point))
64 {
65 hi_axiom(code_point <= 0x10ffff);
66 }
67
68 constexpr explicit grapheme(char ascii_char) noexcept : _value(truncate<value_type>(ascii_char))
69 {
70 hi_axiom(ascii_char >= 0 and ascii_char <= 0x7f);
71 }
72
75 constexpr grapheme& operator=(char32_t code_point) noexcept
76 {
77 _value = truncate<value_type>(code_point);
78 return *this;
79 }
80
83 constexpr grapheme& operator=(char ascii_char) noexcept
84 {
85 hi_axiom(ascii_char >= 0 and ascii_char <= 0x7f);
86 _value = truncate<value_type>(ascii_char);
87 return *this;
88 }
89
94 explicit grapheme(std::u32string_view code_points) noexcept;
95
100 explicit grapheme(composed_t, std::u32string_view code_points) noexcept;
101
104 [[nodiscard]] static constexpr grapheme eof() noexcept
105 {
106 grapheme r;
107 r._value = 0x1f'ffff;
108 return r;
109 }
110
113 constexpr void clear() noexcept
114 {
115 _value = 0x1f'ffff;
116 }
117
120 [[nodiscard]] constexpr bool empty() const noexcept
121 {
122 return _value == 0x1f'ffff;
123 }
124
127 constexpr operator bool() const noexcept
128 {
129 return not empty();
130 }
131
139 [[nodiscard]] bool valid() const noexcept;
140
141 [[nodiscard]] std::u32string const &long_grapheme() const noexcept
142 {
143 hi_axiom(_value >= 0x10'0000 and _value < 0x1f'ffff);
144 return detail::long_graphemes[_value - 0x11'0000];
145 }
146
149 [[nodiscard]] constexpr std::size_t size() const noexcept
150 {
151 if (_value == 0x1f'ffff) {
152 return 0;
153
154 } else if (_value <= 0x10'ffff) {
155 return 1;
156
157 } else {
158 return long_grapheme().size();
159 }
160 }
161
168 [[nodiscard]] constexpr char32_t operator[](size_t i) const noexcept
169 {
170 hi_axiom(i < size());
171
172 if (_value <= 0x10'ffff) {
173 return truncate<char32_t>(_value);
174 } else {
175 return long_grapheme()[i];
176 }
177 }
178
186 template<size_t I>
187 [[nodiscard]] friend constexpr char32_t get(grapheme const& rhs) noexcept
188 {
189 hi_axiom(I < rhs.size());
190
191 if (rhs._value <= 0x10'ffff) {
192 return rhs._value;
193 } else {
194 return rhs.long_grapheme()[I];
195 }
196 }
197
200 [[nodiscard]] constexpr std::u32string composed() const noexcept
201 {
202 if (_value <= 0x10'ffff) {
203 return std::u32string{truncate<char32_t>(_value)};
204 } else {
205 return long_grapheme();
206 }
207 }
208
211 [[nodiscard]] std::u32string decomposed() const noexcept;
212
215 [[nodiscard]] friend constexpr bool operator==(grapheme const&, grapheme const&) noexcept = default;
216
219 [[nodiscard]] friend constexpr std::strong_ordering operator<=>(grapheme const& lhs, grapheme const& rhs) noexcept
220 {
221 return lhs.decomposed() <=> rhs.decomposed();
222 }
223
224 [[nodiscard]] friend constexpr bool operator==(grapheme const& lhs, char32_t const& rhs) noexcept
225 {
226 return lhs == grapheme{rhs};
227 }
228
229 [[nodiscard]] friend constexpr std::strong_ordering operator<=>(grapheme const& lhs, char32_t const& rhs) noexcept
230 {
231 return lhs <=> grapheme{rhs};
232 }
233
234 [[nodiscard]] friend constexpr bool operator==(grapheme const& lhs, char const& rhs) noexcept
235 {
236 return lhs == grapheme{rhs};
237 }
238
239 [[nodiscard]] friend constexpr std::strong_ordering operator<=>(grapheme const& lhs, char const& rhs) noexcept
240 {
241 return lhs <=> grapheme{rhs};
242 }
243
244 [[nodiscard]] friend std::string to_string(grapheme const& rhs) noexcept
245 {
246 return hi::to_string(rhs.composed());
247 }
248
249 [[nodiscard]] friend std::u32string to_u32string(grapheme const& rhs) noexcept
250 {
251 return rhs.composed();
252 }
253};
254
255} // namespace hi::inline v1
256
257template<>
258struct std::hash<hi::grapheme> {
259 [[nodiscard]] std::size_t operator()(hi::grapheme const& rhs) const noexcept
260 {
261 return std::hash<hi::grapheme::value_type>{}(rhs._value);
262 }
263};
264
This file includes required definitions.
STL namespace.
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:120
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:168
static constexpr grapheme eof() noexcept
Create empty grapheme / end-of-file.
Definition grapheme.hpp:104
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:113
constexpr grapheme & operator=(char ascii_char) noexcept
Encode a single code-point.
Definition grapheme.hpp:83
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:200
constexpr grapheme & operator=(char32_t code_point) noexcept
Encode a single code-point.
Definition grapheme.hpp:75
constexpr std::size_t size() const noexcept
Return the number of code-points encoded in the grapheme.
Definition grapheme.hpp:149
friend constexpr char32_t get(grapheme const &rhs) noexcept
Get the code-point at the given index.
Definition grapheme.hpp:187
T operator()(T... args)
Definition datum.hpp:2458
T to_string(T... args)