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());
217 return lhs << to_string(rhs);
221 [[nodiscard]]
bool has_pointer() const noexcept
223 return (value & 1) == 0;
226 [[nodiscard]]
static uint64_t create_pointer(
char32_t const *data,
size_t size)
noexcept
228 tt_assert(size <= std::tuple_size<long_grapheme>::value);
230 auto ptr =
new long_grapheme();
231 memcpy(ptr->data(), data, size);
233 auto iptr =
reinterpret_cast<ptrdiff_t
>(ptr);
234 auto uptr =
static_cast<uint64_t
>(iptr << 16) >> 16;
235 return (size << 48) | uptr;
238 [[nodiscard]] long_grapheme *get_pointer() const noexcept
240 auto uptr = (value << 16);
241 auto iptr =
static_cast<ptrdiff_t
>(uptr) >> 16;
242 return std::launder(
reinterpret_cast<long_grapheme *
>(iptr));
245 void delete_pointer() noexcept
248 delete get_pointer();
252 [[nodiscard]]
friend bool operator<(grapheme
const &a, grapheme
const &b)
noexcept
254 ttlet length =
std::min(std::ssize(a), std::ssize(b));
256 for (ssize_t i = 0; i != length; ++i) {
261 return std::ssize(a) < std::ssize(b);
264 [[nodiscard]]
friend bool operator==(grapheme
const &a, grapheme
const &b)
noexcept
266 if (a.value == b.value) {
270 if (std::ssize(a) != std::ssize(b)) {
274 for (ssize_t i = 0; i != std::ssize(a); ++i) {
282 [[nodiscard]]
friend bool operator!=(grapheme
const &a, grapheme
const &b)
noexcept
287 [[nodiscard]]
friend bool operator==(grapheme
const &lhs,
char32_t const &rhs)
noexcept
289 return (std::ssize(lhs) == 1) && (lhs[0] == rhs);
292 [[nodiscard]]
friend bool operator!=(grapheme
const &lhs,
char32_t const &rhs)
noexcept
294 return !(lhs == rhs);
297 [[nodiscard]]
friend bool operator==(grapheme
const &lhs,
char const &rhs)
noexcept
299 return lhs ==
static_cast<char32_t>(rhs);
302 [[nodiscard]]
friend bool operator!=(grapheme
const &lhs,
char const &rhs)
noexcept
304 return !(lhs == rhs);