50 tt_axiom(&other !=
this);
52 if (other.has_pointer()) {
53 value = create_pointer(other.get_pointer()->data(), other.size());
59 tt_return_on_self_assignment(other);
62 if (other.has_pointer()) {
63 value = create_pointer(other.get_pointer()->data(), other.size());
70 tt_axiom(&other !=
this);
84 explicit grapheme(std::u32string_view codePoints)
noexcept;
86 explicit grapheme(
char32_t codePoint) noexcept :
grapheme(std::u32string_view{&codePoint, 1}) {}
97 grapheme &operator=(std::u32string_view codePoints)
noexcept
103 grapheme &operator=(
char32_t codePoint)
noexcept
109 grapheme &operator+=(
char32_t codePoint)
noexcept;
114 return {get_pointer()->
data(), size()};
117 auto tmp = value >> 1;
118 for (
size_t i = 0; i < 3; i++, tmp >>= 21) {
119 if (
auto codePoint =
static_cast<char32_t>(tmp & 0x1f'ffff)) {
129 operator bool()
const noexcept
134 [[nodiscard]]
size_t hash()
const noexcept
137 for (
ssize_t i = 0; i != std::ssize(*
this); ++i) {
143 [[nodiscard]]
size_t size()
const noexcept
148 auto tmp = value >> 1;
150 for (i = 0; i < 3; i++, tmp >>= 21) {
151 if ((tmp & 0x1f'ffff) == 0) {
159 [[nodiscard]]
char32_t front()
const noexcept
168 [[nodiscard]]
char32_t operator[](
size_t i)
const noexcept
171 tt_axiom(i < std::tuple_size_v<long_grapheme>);
172 return (*get_pointer())[i];
176 return (value >> ((i * 21) + 1)) & 0x1f'ffff;
184 for (
ssize_t i = 0; i != std::ssize(*
this); ++i) {
212 return tt::to_string(g.NFC());
215 [[nodiscard]]
friend std::u8string to_u8string(grapheme
const &g)
noexcept
217 return tt::to_u8string(g.NFC());
222 return lhs << to_string(rhs);
226 [[nodiscard]]
bool has_pointer() const noexcept
228 return (value & 1) == 0;
231 [[nodiscard]]
static uint64_t create_pointer(
char32_t const *data,
size_t size)
noexcept
233 tt_assert(size <= std::tuple_size<long_grapheme>::value);
235 auto ptr =
new long_grapheme();
236 memcpy(ptr->data(), data, size);
238 auto iptr =
reinterpret_cast<ptrdiff_t
>(ptr);
239 auto uptr =
static_cast<uint64_t
>(iptr << 16) >> 16;
240 return (size << 48) | uptr;
243 [[nodiscard]] long_grapheme *get_pointer() const noexcept
245 auto uptr = (value << 16);
246 auto iptr =
static_cast<ptrdiff_t
>(uptr) >> 16;
247 return std::launder(
reinterpret_cast<long_grapheme *
>(iptr));
250 void delete_pointer() noexcept
253 delete get_pointer();
257 [[nodiscard]]
friend bool operator<(grapheme
const &a, grapheme
const &b)
noexcept
259 ttlet length =
std::min(std::ssize(a), std::ssize(b));
261 for (ssize_t i = 0; i != length; ++i) {
266 return std::ssize(a) < std::ssize(b);
269 [[nodiscard]]
friend bool operator==(grapheme
const &a, grapheme
const &b)
noexcept
271 if (a.value == b.value) {
275 if (std::ssize(a) != std::ssize(b)) {
279 for (ssize_t i = 0; i != std::ssize(a); ++i) {
287 [[nodiscard]]
friend bool operator!=(grapheme
const &a, grapheme
const &b)
noexcept
292 [[nodiscard]]
friend bool operator==(grapheme
const &lhs,
char32_t const &rhs)
noexcept
294 return (std::ssize(lhs) == 1) && (lhs[0] == rhs);
297 [[nodiscard]]
friend bool operator!=(grapheme
const &lhs,
char32_t const &rhs)
noexcept
299 return !(lhs == rhs);
302 [[nodiscard]]
friend bool operator==(grapheme
const &lhs,
char const &rhs)
noexcept
304 return lhs ==
static_cast<char32_t>(rhs);
307 [[nodiscard]]
friend bool operator!=(grapheme
const &lhs,
char const &rhs)
noexcept
309 return !(lhs == rhs);