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 "unicode_db_non_starter.hpp"
8#include "../required.hpp"
9#include "../strings.hpp"
10#include <cstdint>
11#include <string>
12#include <cstddef>
13
14namespace hi::inline v1 {
15
34struct grapheme {
35 using value_type = uint64_t;
36
45 value_type value;
46
47 constexpr grapheme() noexcept = default;
48 constexpr grapheme(grapheme const &) noexcept = default;
49 constexpr grapheme(grapheme &&) noexcept = default;
50 constexpr grapheme &operator=(grapheme const &) noexcept = default;
51 constexpr grapheme &operator=(grapheme &&) noexcept = default;
52
55 constexpr explicit grapheme(char32_t code_point) noexcept : value((static_cast<value_type>(code_point) << 43) | 1) {}
56
59 constexpr grapheme &operator=(char32_t code_point) noexcept
60 {
61 value = (static_cast<value_type>(code_point) << 43) | 1;
62 return *this;
63 }
64
67 constexpr explicit grapheme(char code_point) noexcept : value((static_cast<value_type>(code_point) << 43) | 1) {}
68
71 constexpr grapheme &operator=(char code_point) noexcept
72 {
73 value = (static_cast<value_type>(code_point) << 43) | 1;
74 return *this;
75 }
76
81 explicit grapheme(std::u32string_view code_points) noexcept;
82
87 grapheme &operator=(std::u32string_view code_points) noexcept;
88
93 [[nodiscard]] static grapheme from_composed(std::u32string_view code_points) noexcept;
94
97 [[nodiscard]] static constexpr grapheme eof() noexcept
98 {
99 grapheme r;
100 r.value = 0;
101 return r;
102 }
103
106 constexpr void clear() noexcept
107 {
108 value = 0;
109 }
110
113 [[nodiscard]] constexpr bool empty() const noexcept
114 {
115 return value == 0;
116 }
117
120 constexpr operator bool() const noexcept
121 {
122 return not empty();
123 }
124
132 [[nodiscard]] bool valid() const noexcept;
133
136 [[nodiscard]] constexpr std::size_t size() const noexcept
137 {
138 hilet size_ = value & 0x7;
139 return size_ <= 5 ? size_ : 5;
140 }
141
144 [[nodiscard]] constexpr bool overlong() const noexcept
145 {
146 return (value & 0x7) == 6;
147 }
148
155 [[nodiscard]] constexpr char32_t operator[](size_t i) const noexcept
156 {
157 hi_axiom(i < size());
158
159 if (i == 0) {
160 return static_cast<char32_t>(value >> 43);
161
162 } else {
163 hilet shift = (4 - i) * 10 + 3;
164 return detail::unicode_db_non_starter_table[(value >> shift) & 0x3ff];
165 }
166 }
167
175 template<size_t I>
176 [[nodiscard]] friend constexpr char32_t get(grapheme const &rhs) noexcept
177 {
178 if constexpr (I == 0) {
179 return static_cast<char32_t>(rhs.value >> 43);
180
181 } else {
182 constexpr auto shift = (4 - I) * 10 + 3;
183 return detail::unicode_db_non_starter_table[(rhs.value >> shift) & 0x3ff];
184 }
185 }
186
189 [[nodiscard]] constexpr std::u32string composed() const noexcept
190 {
191 auto r = std::u32string{};
192 r.reserve(size());
193 for (std::size_t i = 0; i != size(); ++i) {
194 r += (*this)[i];
195 }
196 return r;
197 }
198
201 [[nodiscard]] std::u32string decomposed() const noexcept;
202
205 [[nodiscard]] friend constexpr bool operator==(grapheme const &a, grapheme const &b) noexcept = default;
206
209 [[nodiscard]] friend constexpr std::strong_ordering operator<=>(grapheme const &a, grapheme const &b) noexcept = default;
210
211 [[nodiscard]] friend constexpr bool operator==(grapheme const &lhs, char32_t const &rhs) noexcept
212 {
213 return lhs == grapheme{rhs};
214 }
215
216 [[nodiscard]] friend constexpr std::strong_ordering operator<=>(grapheme const &lhs, char32_t const &rhs) noexcept
217 {
218 return lhs <=> grapheme{rhs};
219 }
220
221 [[nodiscard]] friend constexpr bool operator==(grapheme const &lhs, char const &rhs) noexcept
222 {
223 return lhs == grapheme{rhs};
224 }
225
226 [[nodiscard]] friend constexpr std::strong_ordering operator<=>(grapheme const &lhs, char const &rhs) noexcept
227 {
228 return lhs <=> grapheme{rhs};
229 }
230
231 [[nodiscard]] friend std::string to_string(grapheme const &rhs) noexcept
232 {
233 return hi::to_string(rhs.composed());
234 }
235
236 [[nodiscard]] friend std::u32string to_u32string(grapheme const &rhs) noexcept
237 {
238 return rhs.composed();
239 }
240};
241
242} // namespace hi::inline v1
243
244template<>
245struct std::hash<hi::grapheme> {
246 [[nodiscard]] std::size_t operator()(hi::grapheme const &rhs) const noexcept
247 {
248 return std::hash<hi::grapheme::value_type>{}(rhs.value);
249 }
250};
This file includes required definitions.
#define hilet
Invariant should be the default for variables.
Definition required.hpp:23
STL namespace.
A grapheme, what a user thinks a character is.
Definition grapheme.hpp:34
static grapheme from_composed(std::u32string_view code_points) noexcept
Encode a grapheme from a list of NFKC-normalized code-points.
std::u32string decomposed() const noexcept
Get a list of code-point normalized to NFD.
value_type value
[63:43] Starter code-point 0.
Definition grapheme.hpp:45
constexpr bool empty() const noexcept
Check if the grapheme is empty.
Definition grapheme.hpp:113
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:155
static constexpr grapheme eof() noexcept
Create empty grapheme / end-of-file.
Definition grapheme.hpp:97
constexpr void clear() noexcept
Clear the grapheme.
Definition grapheme.hpp:106
constexpr grapheme & operator=(char code_point) noexcept
Encode a single code-point.
Definition grapheme.hpp:71
grapheme & operator=(std::u32string_view code_points) noexcept
Encode a grapheme from a list of code-points.
constexpr grapheme(char code_point) noexcept
Encode a single code-point.
Definition grapheme.hpp:67
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:189
constexpr bool overlong() const noexcept
Check if the grapheme was initialized with more than 4 combining characters.
Definition grapheme.hpp:144
constexpr grapheme & operator=(char32_t code_point) noexcept
Encode a single code-point.
Definition grapheme.hpp:59
friend constexpr char32_t get(grapheme const &rhs) noexcept
Get the code-point at the given index.
Definition grapheme.hpp:176
T operator()(T... args)
T reserve(T... args)
T to_string(T... args)