Skip to content

Commit

Permalink
AK: Implement ShortString for big-endian
Browse files Browse the repository at this point in the history
  • Loading branch information
sideeffect42 authored and Dennis Camera committed Jul 10, 2024
1 parent 648b36f commit 46e5bcc
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 12 deletions.
13 changes: 8 additions & 5 deletions AK/StringBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 })
{
}

Expand Down
24 changes: 17 additions & 7 deletions Tests/AK/TestString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down

0 comments on commit 46e5bcc

Please sign in to comment.