AK: Implement ShortString for big-endian

This commit is contained in:
Dennis Camera 2024-07-04 16:00:44 +02:00 committed by Andrew Kaster
parent b4d13d060a
commit b54a1c6284
Notes: sideshowbarker 2024-07-17 06:39:26 +09:00
2 changed files with 25 additions and 12 deletions

View File

@ -14,26 +14,29 @@ namespace AK::Detail {
class StringData;
static constexpr size_t MAX_SHORT_STRING_BYTE_COUNT = sizeof(StringData*) - 1;
static constexpr size_t MAX_SHORT_STRING_BYTE_COUNT = sizeof(StringData*) - sizeof(u8);
struct ShortString {
ReadonlyBytes bytes() const;
size_t byte_count() const;
// NOTE: This is the byte count shifted left 1 step and or'ed with a 1 (the SHORT_STRING_FLAG)
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
u8 byte_count_and_short_string_flag { 0 };
u8 storage[MAX_SHORT_STRING_BYTE_COUNT] = { 0 };
#else
u8 storage[MAX_SHORT_STRING_BYTE_COUNT] = { 0 };
u8 byte_count_and_short_string_flag { 0 };
#endif
};
static_assert(HostIsLittleEndian, "Order of fields in ShortString assumes LE.");
static_assert(sizeof(ShortString) >= sizeof(StringData*));
static_assert(__builtin_offsetof(ShortString, byte_count_and_short_string_flag) == 0);
static_assert(sizeof(ShortString) == sizeof(StringData*));
class StringBase {
public:
// Creates an empty (zero-length) String.
constexpr StringBase()
: StringBase(ShortString { SHORT_STRING_FLAG, {} })
: StringBase(ShortString { .byte_count_and_short_string_flag = SHORT_STRING_FLAG })
{
}

View File

@ -63,27 +63,37 @@ TEST_CASE(copy_assignment)
TEST_CASE(short_strings)
{
/** NOTE: make sure that the test strings' first character has an even ASCII code.
* This is important for the odd pointer address checks (this is to
* test if the ShortString structs are endian agnostic). */
#ifdef AK_ARCH_64_BIT
auto string1 = MUST(String::from_utf8("abcdefg"sv));
auto string1 = MUST(String::from_utf8("foo bar"sv));
EXPECT_EQ(string1.is_short_string(), true);
EXPECT_EQ(string1.bytes().size(), 7u);
EXPECT_EQ(string1.bytes_as_string_view(), "abcdefg"sv);
EXPECT_EQ(string1.bytes_as_string_view(), "foo bar"sv);
// check for odd "pointer" value, i.e. short string flag
EXPECT_EQ(*((uintptr_t*)&string1) % 2UL, 1U);
auto string2 = "abcdefg"_string;
auto string2 = "foo bar"_string;
EXPECT_EQ(string2.is_short_string(), true);
EXPECT_EQ(string2.bytes().size(), 7u);
EXPECT_EQ(string2, string1);
// check for odd "pointer" value, i.e. short string flag
EXPECT_EQ(*((uintptr_t*)&string2) % 2UL, 1U);
#else
auto string1 = MUST(String::from_utf8("abc"sv));
auto string1 = MUST(String::from_utf8("foo"sv));
EXPECT_EQ(string1.is_short_string(), true);
EXPECT_EQ(string1.bytes().size(), 3u);
EXPECT_EQ(string1.bytes_as_string_view(), "abc"sv);
EXPECT_EQ(string1.bytes_as_string_view(), "foo"sv);
// check for odd "pointer" value, i.e. short string flag
EXPECT_EQ(*((uintptr_t*)&string1) % 2U, 1U);
auto string2 = "abc"_string;
auto string2 = "foo"_string;
EXPECT_EQ(string2.is_short_string(), true);
EXPECT_EQ(string2.bytes().size(), 3u);
EXPECT_EQ(string2, string1);
// check for odd "pointer" value, i.e. short string flag
EXPECT_EQ(*((uintptr_t*)&string2) % 2U, 1U);
#endif
}