From e7700e16ee1214c6eb18615c95e218bb497193b5 Mon Sep 17 00:00:00 2001 From: Dan Klishch Date: Sat, 28 Oct 2023 17:50:24 -0400 Subject: [PATCH] AK: Forward substring creation with shared superstring to StringBase --- AK/String.cpp | 6 +----- AK/String.h | 5 +++++ AK/StringBase.cpp | 21 +++++++++++++++++++++ AK/StringBase.h | 5 +++++ AK/StringInternals.h | 2 ++ 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/AK/String.cpp b/AK/String.cpp index 50667bf7e4d..5f1aa2232a4 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -252,11 +252,7 @@ ErrorOr String::substring_from_byte_offset(size_t start) const ErrorOr String::substring_from_byte_offset_with_shared_superstring(size_t start, size_t byte_count) const { - if (!byte_count) - return String {}; - if (byte_count <= MAX_SHORT_STRING_BYTE_COUNT) - return String::from_utf8(bytes_as_string_view().substring_view(start, byte_count)); - return String { TRY(Detail::StringData::create_substring(*m_data, start, byte_count)) }; + return String { TRY(StringBase::substring_from_byte_offset_with_shared_superstring(start, byte_count)) }; } ErrorOr String::substring_from_byte_offset_with_shared_superstring(size_t start) const diff --git a/AK/String.h b/AK/String.h index f7cc70523b4..cba273ac984 100644 --- a/AK/String.h +++ b/AK/String.h @@ -196,6 +196,11 @@ public: private: using ShortString = Detail::ShortString; + + explicit constexpr String(StringBase&& base) + : StringBase(move(base)) + { + } }; template<> diff --git a/AK/StringBase.cpp b/AK/StringBase.cpp index dfb357db652..e0199a1028e 100644 --- a/AK/StringBase.cpp +++ b/AK/StringBase.cpp @@ -70,6 +70,13 @@ u32 StringBase::hash() const return m_data->hash(); } +size_t StringBase::byte_count() const +{ + if (is_short_string()) + return m_short_string.byte_count_and_short_string_flag >> 1; + return m_data->byte_count(); +} + bool StringBase::operator==(StringBase const& other) const { if (is_short_string()) @@ -88,6 +95,20 @@ ErrorOr StringBase::replace_with_uninitialized_buffer(size_t byte_count) return Bytes { buffer, byte_count }; } +ErrorOr StringBase::substring_from_byte_offset_with_shared_superstring(size_t start, size_t length) const +{ + VERIFY(start + length <= byte_count()); + + if (length == 0) + return StringBase {}; + if (length <= MAX_SHORT_STRING_BYTE_COUNT) { + StringBase result; + bytes().slice(start, length).copy_to(result.replace_with_uninitialized_short_string(length)); + return result; + } + return StringBase { TRY(Detail::StringData::create_substring(*m_data, start, length)) }; +} + void StringBase::destroy_string() { if (!is_short_string()) diff --git a/AK/StringBase.h b/AK/StringBase.h index 86d4b7709e1..f403d7785f5 100644 --- a/AK/StringBase.h +++ b/AK/StringBase.h @@ -64,6 +64,7 @@ public: // NOTE: There is no guarantee about null-termination. [[nodiscard]] ReadonlyBytes bytes() const; [[nodiscard]] u32 hash() const; + [[nodiscard]] size_t byte_count() const; [[nodiscard]] bool operator==(StringBase const&) const; @@ -100,6 +101,10 @@ protected: callback(buffer); } + // This is not a trivial operation with storage, so it does not belong here. Unfortunately, it + // is impossible to implement it without access to StringData. + ErrorOr substring_from_byte_offset_with_shared_superstring(size_t start, size_t byte_count) const; + union { ShortString m_short_string; Detail::StringData const* m_data { nullptr }; diff --git a/AK/StringInternals.h b/AK/StringInternals.h index 39d0217f86f..3a544fdd5cb 100644 --- a/AK/StringInternals.h +++ b/AK/StringInternals.h @@ -59,6 +59,8 @@ public: bool is_fly_string() const { return m_is_fly_string; } void set_fly_string(bool is_fly_string) const { m_is_fly_string = is_fly_string; } + size_t byte_count() const { return m_byte_count; } + private: explicit StringData(size_t byte_count); StringData(StringData const& superstring, size_t start, size_t byte_count);