51 if (other.has_pointer()) {
52 value = create_pointer(other.get_pointer()->
data(), other.size());
61 if (other.has_pointer()) {
62 value = create_pointer(other.get_pointer()->
data(), other.size());
82 explicit grapheme(std::u32string_view codePoints)
noexcept;
84 explicit grapheme(
char32_t codePoint) noexcept :
grapheme(std::u32string_view{&codePoint, 1}) {}
95 grapheme &operator=(std::u32string_view codePoints)
noexcept
101 grapheme &operator=(
char32_t codePoint)
noexcept
107 grapheme &operator+=(
char32_t codePoint)
noexcept;
112 return {get_pointer()->
data(), size()};
115 auto tmp = value >> 1;
116 for (
size_t i = 0; i < 3; i++, tmp >>= 21) {
117 if (
auto codePoint =
static_cast<char32_t>(tmp & 0x1f'ffff)) {
127 operator bool()
const noexcept
132 [[nodiscard]]
size_t hash()
const noexcept
135 for (
ssize_t i = 0; i != std::ssize(*
this); ++i) {
141 [[nodiscard]]
size_t size()
const noexcept
146 auto tmp = value >> 1;
148 for (i = 0; i < 3; i++, tmp >>= 21) {
149 if ((tmp & 0x1f'ffff) == 0) {
157 [[nodiscard]]
char32_t front()
const noexcept
166 [[nodiscard]]
char32_t operator[](
size_t i)
const noexcept
169 tt_axiom(i < std::tuple_size_v<long_grapheme>);
170 return (*get_pointer())[i];
174 return (value >> ((i * 21) + 1)) & 0x1f'ffff;
182 for (
ssize_t i = 0; i != std::ssize(*
this); ++i) {
210 return tt::to_string(g.NFC());
213 [[nodiscard]]
friend std::u8string to_u8string(grapheme
const &g)
noexcept
215 return tt::to_u8string(g.NFC());
220 return lhs << to_string(rhs);
224 [[nodiscard]]
bool has_pointer() const noexcept
226 return (value & 1) == 0;
229 [[nodiscard]]
static uint64_t create_pointer(
char32_t const *data,
size_t size)
noexcept
231 tt_assert(size <= std::tuple_size<long_grapheme>::value);
233 auto ptr =
new long_grapheme();
234 memcpy(ptr->data(), data, size);
236 auto iptr =
reinterpret_cast<ptrdiff_t
>(ptr);
237 auto uptr =
static_cast<uint64_t
>(iptr << 16) >> 16;
238 return (size << 48) | uptr;
241 [[nodiscard]] long_grapheme *get_pointer() const noexcept
243 auto uptr = (value << 16);
244 auto iptr =
static_cast<ptrdiff_t
>(uptr) >> 16;
245 return std::launder(
reinterpret_cast<long_grapheme *
>(iptr));
248 void delete_pointer() noexcept
251 delete get_pointer();
255 [[nodiscard]]
friend bool operator<(grapheme
const &a, grapheme
const &b)
noexcept
257 ttlet length =
std::min(std::ssize(a), std::ssize(b));
259 for (ssize_t i = 0; i != length; ++i) {
264 return std::ssize(a) < std::ssize(b);
267 [[nodiscard]]
friend bool operator==(grapheme
const &a, grapheme
const &b)
noexcept
269 if (a.value == b.value) {
273 if (std::ssize(a) != std::ssize(b)) {
277 for (ssize_t i = 0; i != std::ssize(a); ++i) {
285 [[nodiscard]]
friend bool operator!=(grapheme
const &a, grapheme
const &b)
noexcept
290 [[nodiscard]]
friend bool operator==(grapheme
const &lhs,
char32_t const &rhs)
noexcept
292 return (std::ssize(lhs) == 1) && (lhs[0] == rhs);
295 [[nodiscard]]
friend bool operator!=(grapheme
const &lhs,
char32_t const &rhs)
noexcept
297 return !(lhs == rhs);
300 [[nodiscard]]
friend bool operator==(grapheme
const &lhs,
char const &rhs)
noexcept
302 return lhs ==
static_cast<char32_t>(rhs);
305 [[nodiscard]]
friend bool operator!=(grapheme
const &lhs,
char const &rhs)
noexcept
307 return !(lhs == rhs);