AK: Extract some StringBase helpers for use in an outside class

This commit is contained in:
Timothy Flynn 2025-06-12 19:08:09 -04:00 committed by Tim Flynn
commit 5720d626ce
Notes: github-actions[bot] 2025-07-03 13:54:06 +00:00

View file

@ -14,6 +14,9 @@
namespace AK::Detail {
struct ShortString {
static constexpr ShortString create_empty();
static constexpr ShortString create_with_byte_count(size_t byte_count);
ReadonlyBytes bytes() const;
size_t byte_count() const;
@ -31,9 +34,13 @@ static_assert(sizeof(ShortString) == sizeof(StringData*));
class StringBase {
public:
// NOTE: If the least significant bit of the pointer is set, this is a short string.
static constexpr uintptr_t SHORT_STRING_FLAG = 1;
static constexpr unsigned SHORT_STRING_BYTE_COUNT_SHIFT_COUNT = 2;
// Creates an empty (zero-length) String.
constexpr StringBase()
: StringBase(ShortString { .byte_count_and_short_string_flag = SHORT_STRING_FLAG })
: StringBase(ShortString::create_empty())
{
}
@ -42,7 +49,7 @@ public:
constexpr StringBase(StringBase&& other)
: m_impl(other.m_impl)
{
other.m_impl = { .short_string = { .byte_count_and_short_string_flag = SHORT_STRING_FLAG } };
other.m_impl = { .short_string = ShortString::create_empty() };
}
StringBase& operator=(StringBase&&);
@ -108,10 +115,6 @@ private:
friend class ::AK::FlyString;
friend struct ::AK::Detail::ShortString;
// NOTE: If the least significant bit of the pointer is set, this is a short string.
static constexpr uintptr_t SHORT_STRING_FLAG = 1;
static constexpr unsigned SHORT_STRING_BYTE_COUNT_SHIFT_COUNT = 2;
explicit StringBase(NonnullRefPtr<Detail::StringData const>);
explicit constexpr StringBase(nullptr_t)
@ -131,8 +134,7 @@ private:
VERIFY(is_short_string());
VERIFY(byte_count <= MAX_SHORT_STRING_BYTE_COUNT);
m_impl = { .short_string = {} };
m_impl.short_string.byte_count_and_short_string_flag = (byte_count << SHORT_STRING_BYTE_COUNT_SHIFT_COUNT) | SHORT_STRING_FLAG;
m_impl = { .short_string = ShortString::create_with_byte_count(byte_count) };
return { m_impl.short_string.storage, byte_count };
}
@ -172,6 +174,19 @@ private:
} m_impl;
};
constexpr ShortString ShortString::create_empty()
{
return create_with_byte_count(0);
}
constexpr ShortString ShortString::create_with_byte_count(size_t byte_count)
{
ShortString string {};
string.byte_count_and_short_string_flag = (byte_count << StringBase::SHORT_STRING_BYTE_COUNT_SHIFT_COUNT) | StringBase::SHORT_STRING_FLAG;
return string;
}
inline ReadonlyBytes ShortString::bytes() const
{
return { storage, byte_count() };
@ -205,7 +220,7 @@ inline u32 StringBase::hash() const
inline size_t StringBase::byte_count() const
{
if (is_short_string())
return m_impl.short_string.byte_count_and_short_string_flag >> StringBase::SHORT_STRING_BYTE_COUNT_SHIFT_COUNT;
return m_impl.short_string.byte_count();
if (!m_impl.data)
return 0;
@ -235,7 +250,7 @@ inline StringBase& StringBase::operator=(StringBase&& other)
if (!is_short_string() && m_impl.data)
data_without_union_member_assertion()->unref();
m_impl = exchange(other.m_impl, { .short_string = { .byte_count_and_short_string_flag = SHORT_STRING_FLAG } });
m_impl = exchange(other.m_impl, { .short_string = ShortString::create_empty() });
return *this;
}