Serenity Operating System
at master 193 lines 4.2 kB view raw
1/* 2 * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/DeprecatedFlyString.h> 8#include <AK/FlyString.h> 9#include <AK/HashMap.h> 10#include <AK/Singleton.h> 11#include <AK/StringView.h> 12#include <AK/Utf8View.h> 13 14namespace AK { 15 16static auto& all_fly_strings() 17{ 18 static Singleton<HashMap<StringView, uintptr_t>> table; 19 return *table; 20} 21 22FlyString::FlyString() 23 : m_data(String {}.to_fly_string_data({})) 24{ 25} 26 27FlyString::~FlyString() 28{ 29 String::unref_fly_string_data({}, m_data); 30} 31 32ErrorOr<FlyString> FlyString::from_utf8(StringView string) 33{ 34 return FlyString { TRY(String::from_utf8(string)) }; 35} 36 37FlyString::FlyString(String const& string) 38{ 39 if (string.is_short_string()) { 40 m_data = string.to_fly_string_data({}); 41 return; 42 } 43 44 auto it = all_fly_strings().find(string.bytes_as_string_view()); 45 if (it == all_fly_strings().end()) { 46 m_data = string.to_fly_string_data({}); 47 48 all_fly_strings().set(string.bytes_as_string_view(), m_data); 49 string.did_create_fly_string({}); 50 } else { 51 m_data = it->value; 52 } 53 54 String::ref_fly_string_data({}, m_data); 55} 56 57FlyString& FlyString::operator=(String const& string) 58{ 59 *this = FlyString { string }; 60 return *this; 61} 62 63FlyString::FlyString(FlyString const& other) 64 : m_data(other.m_data) 65{ 66 String::ref_fly_string_data({}, m_data); 67} 68 69FlyString& FlyString::operator=(FlyString const& other) 70{ 71 if (this != &other) { 72 m_data = other.m_data; 73 String::ref_fly_string_data({}, m_data); 74 } 75 76 return *this; 77} 78 79FlyString::FlyString(FlyString&& other) 80 : m_data(other.m_data) 81{ 82 other.m_data = String {}.to_fly_string_data({}); 83} 84 85FlyString& FlyString::operator=(FlyString&& other) 86{ 87 m_data = other.m_data; 88 other.m_data = String {}.to_fly_string_data({}); 89 90 return *this; 91} 92 93bool FlyString::is_empty() const 94{ 95 return bytes_as_string_view().is_empty(); 96} 97 98unsigned FlyString::hash() const 99{ 100 return String::fly_string_data_to_hash({}, m_data); 101} 102 103FlyString::operator String() const 104{ 105 return to_string(); 106} 107 108String FlyString::to_string() const 109{ 110 return String::fly_string_data_to_string({}, m_data); 111} 112 113Utf8View FlyString::code_points() const 114{ 115 return Utf8View { bytes_as_string_view() }; 116} 117 118ReadonlyBytes FlyString::bytes() const 119{ 120 return bytes_as_string_view().bytes(); 121} 122 123StringView FlyString::bytes_as_string_view() const 124{ 125 return String::fly_string_data_to_string_view({}, m_data); 126} 127 128bool FlyString::operator==(FlyString const& other) const 129{ 130 return m_data == other.m_data; 131} 132 133bool FlyString::operator==(String const& other) const 134{ 135 if (m_data == other.to_fly_string_data({})) 136 return true; 137 138 return bytes_as_string_view() == other.bytes_as_string_view(); 139} 140 141bool FlyString::operator==(StringView string) const 142{ 143 return bytes_as_string_view() == string; 144} 145 146bool FlyString::operator==(char const* string) const 147{ 148 return bytes_as_string_view() == string; 149} 150 151void FlyString::did_destroy_fly_string_data(Badge<Detail::StringData>, StringView string_data) 152{ 153 all_fly_strings().remove(string_data); 154} 155 156uintptr_t FlyString::data(Badge<String>) const 157{ 158 return m_data; 159} 160 161size_t FlyString::number_of_fly_strings() 162{ 163 return all_fly_strings().size(); 164} 165 166DeprecatedFlyString FlyString::to_deprecated_fly_string() const 167{ 168 return DeprecatedFlyString(bytes_as_string_view()); 169} 170 171ErrorOr<FlyString> FlyString::from_deprecated_fly_string(DeprecatedFlyString const& deprecated_fly_string) 172{ 173 return FlyString::from_utf8(deprecated_fly_string.view()); 174} 175 176unsigned Traits<FlyString>::hash(FlyString const& fly_string) 177{ 178 return fly_string.hash(); 179} 180 181ErrorOr<void> Formatter<FlyString>::format(FormatBuilder& builder, FlyString const& fly_string) 182{ 183 return Formatter<StringView>::format(builder, fly_string.bytes_as_string_view()); 184} 185 186bool FlyString::equals_ignoring_ascii_case(FlyString const& other) const 187{ 188 if (*this == other) 189 return true; 190 return StringUtils::equals_ignoring_ascii_case(bytes_as_string_view(), other.bytes_as_string_view()); 191} 192 193}