mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +00:00
AK: Support creating known short string literals at compile time
In cases where we know a string literal will fit in the short string storage, we can do so at compile time without needing to handle error propagation. If the provided string literal is too long, a compilation error will be emitted due to the failed VERIFY statement being a non- constant expression.
This commit is contained in:
parent
e634778679
commit
d48266a420
Notes:
sideshowbarker
2024-07-17 02:23:25 +09:00
Author: https://github.com/trflynn89 Commit: https://github.com/SerenityOS/serenity/commit/d48266a420 Pull-request: https://github.com/SerenityOS/serenity/pull/17102 Reviewed-by: https://github.com/alimpfard ✅ Reviewed-by: https://github.com/gmta ✅ Reviewed-by: https://github.com/linusg ✅
3 changed files with 45 additions and 16 deletions
|
@ -169,11 +169,6 @@ String::String(NonnullRefPtr<Detail::StringData> data)
|
|||
{
|
||||
}
|
||||
|
||||
String::String(ShortString short_string)
|
||||
: m_short_string(short_string)
|
||||
{
|
||||
}
|
||||
|
||||
String::String(String const& other)
|
||||
: m_data(other.m_data)
|
||||
{
|
||||
|
@ -207,7 +202,7 @@ String& String::operator=(String const& other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
String::~String()
|
||||
void String::destroy_string()
|
||||
{
|
||||
if (!is_short_string())
|
||||
m_data->unref();
|
||||
|
|
28
AK/String.h
28
AK/String.h
|
@ -37,7 +37,11 @@ public:
|
|||
String& operator=(String&&);
|
||||
String& operator=(String const&);
|
||||
|
||||
~String();
|
||||
constexpr ~String()
|
||||
{
|
||||
if (!is_constant_evaluated())
|
||||
destroy_string();
|
||||
}
|
||||
|
||||
// Creates an empty (zero-length) String.
|
||||
String();
|
||||
|
@ -45,6 +49,20 @@ public:
|
|||
// Creates a new String from a sequence of UTF-8 encoded code points.
|
||||
static ErrorOr<String> from_utf8(StringView);
|
||||
|
||||
// Creates a new String from a short sequence of UTF-8 encoded code points. If the provided string
|
||||
// does not fit in the short string storage, a compilation error will be emitted.
|
||||
static consteval String from_utf8_short_string(StringView string)
|
||||
{
|
||||
VERIFY(string.length() <= MAX_SHORT_STRING_BYTE_COUNT);
|
||||
|
||||
ShortString short_string;
|
||||
for (size_t i = 0; i < string.length(); ++i)
|
||||
short_string.storage[i] = string.characters_without_null_termination()[i];
|
||||
short_string.byte_count_and_short_string_flag = (string.length() << 1) | SHORT_STRING_FLAG;
|
||||
|
||||
return String { short_string };
|
||||
}
|
||||
|
||||
// Creates a new String by case-transforming this String. Using these methods require linking LibUnicode into your application.
|
||||
ErrorOr<String> to_lowercase(Optional<StringView> const& locale = {}) const;
|
||||
ErrorOr<String> to_uppercase(Optional<StringView> const& locale = {}) const;
|
||||
|
@ -160,7 +178,13 @@ private:
|
|||
};
|
||||
|
||||
explicit String(NonnullRefPtr<Detail::StringData>);
|
||||
explicit String(ShortString);
|
||||
|
||||
explicit constexpr String(ShortString short_string)
|
||||
: m_short_string(short_string)
|
||||
{
|
||||
}
|
||||
|
||||
void destroy_string();
|
||||
|
||||
union {
|
||||
ShortString m_short_string;
|
||||
|
|
|
@ -34,15 +34,25 @@ TEST_CASE(move_assignment)
|
|||
TEST_CASE(short_strings)
|
||||
{
|
||||
#ifdef AK_ARCH_64_BIT
|
||||
auto string = MUST(String::from_utf8("abcdefg"sv));
|
||||
EXPECT_EQ(string.is_short_string(), true);
|
||||
EXPECT_EQ(string.bytes().size(), 7u);
|
||||
EXPECT_EQ(string.bytes_as_string_view(), "abcdefg"sv);
|
||||
auto string1 = MUST(String::from_utf8("abcdefg"sv));
|
||||
EXPECT_EQ(string1.is_short_string(), true);
|
||||
EXPECT_EQ(string1.bytes().size(), 7u);
|
||||
EXPECT_EQ(string1.bytes_as_string_view(), "abcdefg"sv);
|
||||
|
||||
constexpr auto string2 = String::from_utf8_short_string("abcdefg"sv);
|
||||
EXPECT_EQ(string2.is_short_string(), true);
|
||||
EXPECT_EQ(string2.bytes().size(), 7u);
|
||||
EXPECT_EQ(string2, string1);
|
||||
#else
|
||||
auto string = MUST(String::from_utf8("abc"sv));
|
||||
EXPECT_EQ(string.is_short_string(), true);
|
||||
EXPECT_EQ(string.bytes().size(), 3u);
|
||||
EXPECT_EQ(string.bytes_as_string_view(), "abc"sv);
|
||||
auto string1 = MUST(String::from_utf8("abc"sv));
|
||||
EXPECT_EQ(string1.is_short_string(), true);
|
||||
EXPECT_EQ(string1.bytes().size(), 3u);
|
||||
EXPECT_EQ(string1.bytes_as_string_view(), "abc"sv);
|
||||
|
||||
constexpr auto string2 = String::from_utf8_short_string("abc"sv);
|
||||
EXPECT_EQ(string2.is_short_string(), true);
|
||||
EXPECT_EQ(string2.bytes().size(), 3u);
|
||||
EXPECT_EQ(string2, string1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue