mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 08:24:58 +00:00
AK: Implement FlyString for the new String class
This implements a FlyString that will de-duplicate String instances. The FlyString will store the raw encoded data of the String instance: If the String is a short string, FlyString holds the String::ShortString bytes; otherwise FlyString holds a pointer to the Detail::StringData. FlyString itself does not know about String's storage or how to refcount its Detail::StringData. It defers to String to implement these details.
This commit is contained in:
parent
f49a65cb28
commit
1d4f287582
8 changed files with 445 additions and 1 deletions
169
AK/FlyString.cpp
Normal file
169
AK/FlyString.cpp
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/FlyString.h>
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/Singleton.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <AK/Utf8View.h>
|
||||
|
||||
namespace AK {
|
||||
|
||||
static auto& all_fly_strings()
|
||||
{
|
||||
static Singleton<HashMap<StringView, uintptr_t>> table;
|
||||
return *table;
|
||||
}
|
||||
|
||||
FlyString::FlyString()
|
||||
: m_data(String {}.to_fly_string_data({}))
|
||||
{
|
||||
}
|
||||
|
||||
FlyString::~FlyString()
|
||||
{
|
||||
String::unref_fly_string_data({}, m_data);
|
||||
}
|
||||
|
||||
ErrorOr<FlyString> FlyString::from_utf8(StringView string)
|
||||
{
|
||||
return FlyString { TRY(String::from_utf8(string)) };
|
||||
}
|
||||
|
||||
FlyString::FlyString(String const& string)
|
||||
{
|
||||
if (string.is_short_string()) {
|
||||
m_data = string.to_fly_string_data({});
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = all_fly_strings().find(string.bytes_as_string_view());
|
||||
if (it == all_fly_strings().end()) {
|
||||
m_data = string.to_fly_string_data({});
|
||||
|
||||
all_fly_strings().set(string.bytes_as_string_view(), m_data);
|
||||
string.did_create_fly_string({});
|
||||
} else {
|
||||
m_data = it->value;
|
||||
}
|
||||
|
||||
String::ref_fly_string_data({}, m_data);
|
||||
}
|
||||
|
||||
FlyString::FlyString(FlyString const& other)
|
||||
: m_data(other.m_data)
|
||||
{
|
||||
String::ref_fly_string_data({}, m_data);
|
||||
}
|
||||
|
||||
FlyString& FlyString::operator=(FlyString const& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_data = other.m_data;
|
||||
String::ref_fly_string_data({}, m_data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FlyString::FlyString(FlyString&& other)
|
||||
: m_data(other.m_data)
|
||||
{
|
||||
other.m_data = String {}.to_fly_string_data({});
|
||||
}
|
||||
|
||||
FlyString& FlyString::operator=(FlyString&& other)
|
||||
{
|
||||
m_data = other.m_data;
|
||||
other.m_data = String {}.to_fly_string_data({});
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool FlyString::is_empty() const
|
||||
{
|
||||
return bytes_as_string_view().is_empty();
|
||||
}
|
||||
|
||||
unsigned FlyString::hash() const
|
||||
{
|
||||
return bytes_as_string_view().hash();
|
||||
}
|
||||
|
||||
FlyString::operator String() const
|
||||
{
|
||||
return to_string();
|
||||
}
|
||||
|
||||
String FlyString::to_string() const
|
||||
{
|
||||
return String::fly_string_data_to_string({}, m_data);
|
||||
}
|
||||
|
||||
Utf8View FlyString::code_points() const
|
||||
{
|
||||
return Utf8View { bytes_as_string_view() };
|
||||
}
|
||||
|
||||
ReadonlyBytes FlyString::bytes() const
|
||||
{
|
||||
return bytes_as_string_view().bytes();
|
||||
}
|
||||
|
||||
StringView FlyString::bytes_as_string_view() const
|
||||
{
|
||||
return String::fly_string_data_to_string_view({}, m_data);
|
||||
}
|
||||
|
||||
bool FlyString::operator==(FlyString const& other) const
|
||||
{
|
||||
return m_data == other.m_data;
|
||||
}
|
||||
|
||||
bool FlyString::operator==(String const& other) const
|
||||
{
|
||||
if (m_data == other.to_fly_string_data({}))
|
||||
return true;
|
||||
|
||||
return bytes_as_string_view() == other.bytes_as_string_view();
|
||||
}
|
||||
|
||||
bool FlyString::operator==(StringView string) const
|
||||
{
|
||||
return bytes_as_string_view() == string;
|
||||
}
|
||||
|
||||
bool FlyString::operator==(char const* string) const
|
||||
{
|
||||
return bytes_as_string_view() == string;
|
||||
}
|
||||
|
||||
void FlyString::did_destroy_fly_string_data(Badge<Detail::StringData>, StringView string_data)
|
||||
{
|
||||
all_fly_strings().remove(string_data);
|
||||
}
|
||||
|
||||
uintptr_t FlyString::data(Badge<String>) const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
size_t FlyString::number_of_fly_strings()
|
||||
{
|
||||
return all_fly_strings().size();
|
||||
}
|
||||
|
||||
unsigned Traits<FlyString>::hash(FlyString const& fly_string)
|
||||
{
|
||||
return fly_string.bytes_as_string_view().hash();
|
||||
}
|
||||
|
||||
ErrorOr<void> Formatter<FlyString>::format(FormatBuilder& builder, FlyString const& fly_string)
|
||||
{
|
||||
return Formatter<StringView>::format(builder, fly_string.bytes_as_string_view());
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue