1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-09-14 19:36:17 +00:00

AK+Everywhere: Remove the null state of DeprecatedString

This commit removes DeprecatedString's "null" state, and replaces all
its users with one of the following:
- A normal, empty DeprecatedString
- Optional<DeprecatedString>

Note that null states of DeprecatedFlyString/StringView/etc are *not*
affected by this commit. However, DeprecatedString::empty() is now
considered equal to a null StringView.
This commit is contained in:
Ali Mohammad Pur 2023-10-10 15:00:58 +03:30 committed by Ali Mohammad Pur
parent daf6d8173c
commit aeee98b3a1
189 changed files with 597 additions and 652 deletions

View file

@ -38,8 +38,6 @@ void DeprecatedFlyString::did_destroy_impl(Badge<StringImpl>, StringImpl& impl)
DeprecatedFlyString::DeprecatedFlyString(DeprecatedString const& string)
{
if (string.is_null())
return;
if (string.impl()->is_fly()) {
m_impl = string.impl();
return;
@ -60,7 +58,7 @@ DeprecatedFlyString::DeprecatedFlyString(StringView string)
if (string.is_null())
return;
auto it = fly_impls().find(string.hash(), [&](auto& candidate) {
return string == candidate;
return string == *candidate;
});
if (it == fly_impls().end()) {
auto new_string = string.to_deprecated_string();

View file

@ -28,6 +28,9 @@ bool DeprecatedString::operator==(DeprecatedString const& other) const
bool DeprecatedString::operator==(StringView other) const
{
if (other.is_null())
return is_empty();
return view() == other;
}
@ -55,9 +58,7 @@ bool DeprecatedString::copy_characters_to_buffer(char* buffer, size_t buffer_siz
DeprecatedString DeprecatedString::isolated_copy() const
{
if (!m_impl)
return {};
if (!m_impl->length())
if (m_impl->length() == 0)
return empty();
char* buffer;
auto impl = StringImpl::create_uninitialized(length(), buffer);
@ -69,7 +70,6 @@ DeprecatedString DeprecatedString::substring(size_t start, size_t length) const
{
if (!length)
return DeprecatedString::empty();
VERIFY(m_impl);
VERIFY(!Checked<size_t>::addition_would_overflow(start, length));
VERIFY(start + length <= m_impl->length());
return { characters() + start, length };
@ -77,14 +77,12 @@ DeprecatedString DeprecatedString::substring(size_t start, size_t length) const
DeprecatedString DeprecatedString::substring(size_t start) const
{
VERIFY(m_impl);
VERIFY(start <= length());
return { characters() + start, length() - start };
}
StringView DeprecatedString::substring_view(size_t start, size_t length) const
{
VERIFY(m_impl);
VERIFY(!Checked<size_t>::addition_would_overflow(start, length));
VERIFY(start + length <= m_impl->length());
return { characters() + start, length };
@ -92,7 +90,6 @@ StringView DeprecatedString::substring_view(size_t start, size_t length) const
StringView DeprecatedString::substring_view(size_t start) const
{
VERIFY(m_impl);
VERIFY(start <= length());
return { characters() + start, length() - start };
}
@ -157,8 +154,6 @@ Vector<StringView> DeprecatedString::split_view(char const separator, SplitBehav
ByteBuffer DeprecatedString::to_byte_buffer() const
{
if (!m_impl)
return {};
// FIXME: Handle OOM failure.
return ByteBuffer::copy(bytes()).release_value_but_fixme_should_propagate_errors();
}
@ -379,21 +374,17 @@ DeprecatedString escape_html_entities(StringView html)
}
DeprecatedString::DeprecatedString(DeprecatedFlyString const& string)
: m_impl(string.impl())
: m_impl(*string.impl())
{
}
DeprecatedString DeprecatedString::to_lowercase() const
{
if (!m_impl)
return {};
return m_impl->to_lowercase();
}
DeprecatedString DeprecatedString::to_uppercase() const
{
if (!m_impl)
return {};
return m_impl->to_uppercase();
}
@ -414,6 +405,9 @@ DeprecatedString DeprecatedString::invert_case() const
bool DeprecatedString::operator==(char const* cstring) const
{
if (!cstring)
return is_empty();
return view() == cstring;
}
@ -438,7 +432,7 @@ ErrorOr<DeprecatedString> DeprecatedString::from_utf8(ReadonlyBytes bytes)
{
if (!Utf8View(bytes).validate())
return Error::from_string_literal("DeprecatedString::from_utf8: Input was not valid UTF-8");
return DeprecatedString { StringImpl::create(bytes) };
return DeprecatedString { *StringImpl::create(bytes) };
}
}

View file

@ -40,10 +40,13 @@ class DeprecatedString {
public:
~DeprecatedString() = default;
DeprecatedString() = default;
DeprecatedString()
: m_impl(StringImpl::the_empty_stringimpl())
{
}
DeprecatedString(StringView view)
: m_impl(StringImpl::create(view.characters_without_null_termination(), view.length()))
: m_impl(*StringImpl::create(view.characters_without_null_termination(), view.length()))
{
}
@ -55,20 +58,21 @@ public:
DeprecatedString(DeprecatedString&& other)
: m_impl(move(other.m_impl))
{
other.m_impl = StringImpl::the_empty_stringimpl();
}
DeprecatedString(char const* cstring, ShouldChomp shouldChomp = NoChomp)
: m_impl(StringImpl::create(cstring, shouldChomp))
: m_impl(*StringImpl::create(cstring, shouldChomp))
{
}
DeprecatedString(char const* cstring, size_t length, ShouldChomp shouldChomp = NoChomp)
: m_impl(StringImpl::create(cstring, length, shouldChomp))
: m_impl(*StringImpl::create(cstring, length, shouldChomp))
{
}
explicit DeprecatedString(ReadonlyBytes bytes, ShouldChomp shouldChomp = NoChomp)
: m_impl(StringImpl::create(bytes, shouldChomp))
: m_impl(*StringImpl::create(bytes, shouldChomp))
{
}
@ -77,18 +81,8 @@ public:
{
}
DeprecatedString(StringImpl const* impl)
: m_impl(impl)
{
}
DeprecatedString(RefPtr<StringImpl const>&& impl)
: m_impl(move(impl))
{
}
DeprecatedString(NonnullRefPtr<StringImpl const>&& impl)
: m_impl(move(impl))
: m_impl(*move(impl))
{
}
@ -174,31 +168,25 @@ public:
[[nodiscard]] StringView substring_view(size_t start, size_t length) const;
[[nodiscard]] StringView substring_view(size_t start) const;
[[nodiscard]] bool is_null() const { return !m_impl; }
[[nodiscard]] ALWAYS_INLINE bool is_empty() const { return length() == 0; }
[[nodiscard]] ALWAYS_INLINE size_t length() const { return m_impl ? m_impl->length() : 0; }
// Includes NUL-terminator, if non-nullptr.
[[nodiscard]] ALWAYS_INLINE char const* characters() const { return m_impl ? m_impl->characters() : nullptr; }
[[nodiscard]] ALWAYS_INLINE size_t length() const { return m_impl->length(); }
// Includes NUL-terminator.
[[nodiscard]] ALWAYS_INLINE char const* characters() const { return m_impl->characters(); }
[[nodiscard]] bool copy_characters_to_buffer(char* buffer, size_t buffer_size) const;
[[nodiscard]] ALWAYS_INLINE ReadonlyBytes bytes() const
{
if (m_impl) {
return m_impl->bytes();
}
return {};
return m_impl->bytes();
}
[[nodiscard]] ALWAYS_INLINE char const& operator[](size_t i) const
{
VERIFY(!is_null());
return (*m_impl)[i];
}
[[nodiscard]] ALWAYS_INLINE u8 byte_at(size_t i) const
{
VERIFY(!is_null());
return bit_cast<u8>((*m_impl)[i]);
}
@ -251,22 +239,15 @@ public:
return *this;
}
DeprecatedString& operator=(nullptr_t)
template<OneOf<ReadonlyBytes, Bytes> T>
DeprecatedString& operator=(T bytes)
{
m_impl = nullptr;
return *this;
}
DeprecatedString& operator=(ReadonlyBytes bytes)
{
m_impl = StringImpl::create(bytes);
m_impl = *StringImpl::create(bytes);
return *this;
}
[[nodiscard]] u32 hash() const
{
if (!m_impl)
return 0;
return m_impl->hash();
}
@ -323,7 +304,7 @@ public:
}
private:
RefPtr<StringImpl const> m_impl;
NonnullRefPtr<StringImpl const> m_impl;
};
template<>

View file

@ -129,7 +129,7 @@ StringView GenericLexer::consume_quoted_string(char escape_char)
}
#ifndef KERNEL
DeprecatedString GenericLexer::consume_and_unescape_string(char escape_char)
Optional<DeprecatedString> GenericLexer::consume_and_unescape_string(char escape_char)
{
auto view = consume_quoted_string(escape_char);
if (view.is_null())

View file

@ -119,7 +119,7 @@ public:
StringView consume_until(StringView);
StringView consume_quoted_string(char escape_char = 0);
#ifndef KERNEL
DeprecatedString consume_and_unescape_string(char escape_char = '\\');
Optional<DeprecatedString> consume_and_unescape_string(char escape_char = '\\');
#endif
enum class UnicodeEscapeError {

View file

@ -132,8 +132,6 @@ ErrorOr<JsonValue> JsonParser::parse_object()
break;
ignore_while(is_space);
auto name = TRY(consume_and_unescape_string());
if (name.is_null())
return Error::from_string_literal("JsonParser: Expected object property name");
ignore_while(is_space);
if (!consume_specific(':'))
return Error::from_string_literal("JsonParser: Expected ':'");

View file

@ -174,13 +174,9 @@ JsonValue::JsonValue(double value)
JsonValue::JsonValue(DeprecatedString const& value)
{
if (value.is_null()) {
m_type = Type::Null;
} else {
m_type = Type::String;
m_value.as_string = const_cast<StringImpl*>(value.impl());
m_value.as_string->ref();
}
m_type = Type::String;
m_value.as_string = const_cast<StringImpl*>(value.impl());
m_value.as_string->ref();
}
JsonValue::JsonValue(StringView value)

View file

@ -90,9 +90,6 @@ bool LexicalPath::is_child_of(LexicalPath const& possible_parent) const
DeprecatedString LexicalPath::canonicalized_path(DeprecatedString path)
{
if (path.is_null())
return {};
// NOTE: We never allow an empty m_string, if it's empty, we just set it to '.'.
if (path.is_empty())
return ".";

View file

@ -47,9 +47,6 @@ NonnullRefPtr<StringImpl const> StringImpl::create_uninitialized(size_t length,
RefPtr<StringImpl const> StringImpl::create(char const* cstring, size_t length, ShouldChomp should_chomp)
{
if (!cstring)
return nullptr;
if (should_chomp) {
while (length) {
char last_ch = cstring[length - 1];
@ -72,10 +69,7 @@ RefPtr<StringImpl const> StringImpl::create(char const* cstring, size_t length,
RefPtr<StringImpl const> StringImpl::create(char const* cstring, ShouldChomp shouldChomp)
{
if (!cstring)
return nullptr;
if (!*cstring)
if (!cstring || !*cstring)
return the_empty_stringimpl();
return create(cstring, strlen(cstring), shouldChomp);
@ -88,8 +82,6 @@ RefPtr<StringImpl const> StringImpl::create(ReadonlyBytes bytes, ShouldChomp sho
RefPtr<StringImpl const> StringImpl::create_lowercased(char const* cstring, size_t length)
{
if (!cstring)
return nullptr;
if (!length)
return the_empty_stringimpl();
char* buffer;
@ -101,8 +93,6 @@ RefPtr<StringImpl const> StringImpl::create_lowercased(char const* cstring, size
RefPtr<StringImpl const> StringImpl::create_uppercased(char const* cstring, size_t length)
{
if (!cstring)
return nullptr;
if (!length)
return the_empty_stringimpl();
char* buffer;

View file

@ -178,12 +178,12 @@ bool StringView::equals_ignoring_ascii_case(StringView other) const
#ifndef KERNEL
DeprecatedString StringView::to_lowercase_string() const
{
return StringImpl::create_lowercased(characters_without_null_termination(), length());
return StringImpl::create_lowercased(characters_without_null_termination(), length()).release_nonnull();
}
DeprecatedString StringView::to_uppercase_string() const
{
return StringImpl::create_uppercased(characters_without_null_termination(), length());
return StringImpl::create_uppercased(characters_without_null_termination(), length()).release_nonnull();
}
DeprecatedString StringView::to_titlecase_string() const

View file

@ -191,13 +191,11 @@ URL URL::create_with_file_scheme(DeprecatedString const& path, DeprecatedString
URL url;
url.set_scheme("file"_string);
// NOTE: If the hostname is localhost (or null, which implies localhost), it should be set to the empty string.
// This is because a file URL always needs a non-null hostname.
url.set_host(hostname.is_null() || hostname == "localhost" ? String {} : String::from_deprecated_string(hostname).release_value_but_fixme_should_propagate_errors());
url.set_host(hostname == "localhost" ? String {} : String::from_deprecated_string(hostname).release_value_but_fixme_should_propagate_errors());
url.set_paths(lexical_path.parts());
if (path.ends_with('/'))
url.append_slash();
if (!fragment.is_null())
if (!fragment.is_empty())
url.set_fragment(String::from_deprecated_string(fragment).release_value_but_fixme_should_propagate_errors());
return url;
}
@ -208,14 +206,12 @@ URL URL::create_with_help_scheme(DeprecatedString const& path, DeprecatedString
URL url;
url.set_scheme("help"_string);
// NOTE: If the hostname is localhost (or null, which implies localhost), it should be set to the empty string.
// This is because a file URL always needs a non-null hostname.
url.set_host(hostname.is_null() || hostname == "localhost" ? String {} : String::from_deprecated_string(hostname).release_value_but_fixme_should_propagate_errors());
url.set_host(hostname == "localhost" ? String {} : String::from_deprecated_string(hostname).release_value_but_fixme_should_propagate_errors());
url.set_paths(lexical_path.parts());
if (path.ends_with('/'))
url.append_slash();
if (!fragment.is_null())
if (!fragment.is_empty())
url.set_fragment(String::from_deprecated_string(fragment).release_value_but_fixme_should_propagate_errors());
return url;
}