mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 09:00:22 +00:00
AK: Implement StringView::to_{lower,upper}case_string
This patch refactors StringImpl::to_{lower,upper}case to use the new static methods StringImpl::create_{lower,upper}cased if they have to use to create a new StringImpl. This allows implementing StringView's to_{lower,upper}case_string using the same methods. It also replaces the usage of hand-written to_ascii_lowercase() and similar methods with those from CharacterTypes.h.
This commit is contained in:
parent
5ce9305c5f
commit
3ea65200d8
Notes:
sideshowbarker
2024-07-18 11:06:25 +09:00
Author: https://github.com/MaxWipfli Commit: https://github.com/SerenityOS/serenity/commit/3ea65200d82 Pull-request: https://github.com/SerenityOS/serenity/pull/8368 Reviewed-by: https://github.com/alimpfard Reviewed-by: https://github.com/trflynn89
4 changed files with 41 additions and 36 deletions
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/CharacterTypes.h>
|
||||
#include <AK/FlyString.h>
|
||||
#include <AK/HashTable.h>
|
||||
#include <AK/Memory.h>
|
||||
|
@ -90,60 +91,48 @@ RefPtr<StringImpl> StringImpl::create(ReadonlyBytes bytes, ShouldChomp shouldCho
|
|||
return StringImpl::create(reinterpret_cast<const char*>(bytes.data()), bytes.size(), shouldChomp);
|
||||
}
|
||||
|
||||
static inline bool is_ascii_lowercase(char c)
|
||||
RefPtr<StringImpl> StringImpl::create_lowercased(char const* cstring, size_t length)
|
||||
{
|
||||
return c >= 'a' && c <= 'z';
|
||||
if (!cstring)
|
||||
return nullptr;
|
||||
if (!length)
|
||||
return the_empty_stringimpl();
|
||||
char* buffer;
|
||||
auto impl = create_uninitialized(length, buffer);
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
buffer[i] = (char)to_ascii_lowercase(cstring[i]);
|
||||
return impl;
|
||||
}
|
||||
|
||||
static inline bool is_ascii_uppercase(char c)
|
||||
RefPtr<StringImpl> StringImpl::create_uppercased(char const* cstring, size_t length)
|
||||
{
|
||||
return c >= 'A' && c <= 'Z';
|
||||
}
|
||||
|
||||
static inline char to_ascii_lowercase(char c)
|
||||
{
|
||||
if (is_ascii_uppercase(c))
|
||||
return c | 0x20;
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline char to_ascii_uppercase(char c)
|
||||
{
|
||||
if (is_ascii_lowercase(c))
|
||||
return c & ~0x20;
|
||||
return c;
|
||||
if (!cstring)
|
||||
return nullptr;
|
||||
if (!length)
|
||||
return the_empty_stringimpl();
|
||||
char* buffer;
|
||||
auto impl = create_uninitialized(length, buffer);
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
buffer[i] = (char)to_ascii_uppercase(cstring[i]);
|
||||
return impl;
|
||||
}
|
||||
|
||||
NonnullRefPtr<StringImpl> StringImpl::to_lowercase() const
|
||||
{
|
||||
for (size_t i = 0; i < m_length; ++i) {
|
||||
if (!is_ascii_lowercase(characters()[i]))
|
||||
goto slow_path;
|
||||
if (is_ascii_upper_alpha(characters()[i]))
|
||||
return create_lowercased(characters(), m_length).release_nonnull();
|
||||
}
|
||||
return const_cast<StringImpl&>(*this);
|
||||
|
||||
slow_path:
|
||||
char* buffer;
|
||||
auto lowercased = create_uninitialized(m_length, buffer);
|
||||
for (size_t i = 0; i < m_length; ++i)
|
||||
buffer[i] = to_ascii_lowercase(characters()[i]);
|
||||
return lowercased;
|
||||
}
|
||||
|
||||
NonnullRefPtr<StringImpl> StringImpl::to_uppercase() const
|
||||
{
|
||||
for (size_t i = 0; i < m_length; ++i) {
|
||||
if (!is_ascii_uppercase(characters()[i]))
|
||||
goto slow_path;
|
||||
if (is_ascii_lower_alpha(characters()[i]))
|
||||
return create_uppercased(characters(), m_length).release_nonnull();
|
||||
}
|
||||
return const_cast<StringImpl&>(*this);
|
||||
|
||||
slow_path:
|
||||
char* buffer;
|
||||
auto uppercased = create_uninitialized(m_length, buffer);
|
||||
for (size_t i = 0; i < m_length; ++i)
|
||||
buffer[i] = to_ascii_uppercase(characters()[i]);
|
||||
return uppercased;
|
||||
}
|
||||
|
||||
void StringImpl::compute_hash() const
|
||||
|
|
|
@ -26,6 +26,9 @@ public:
|
|||
static RefPtr<StringImpl> create(const char* cstring, ShouldChomp = NoChomp);
|
||||
static RefPtr<StringImpl> create(const char* cstring, size_t length, ShouldChomp = NoChomp);
|
||||
static RefPtr<StringImpl> create(ReadonlyBytes, ShouldChomp = NoChomp);
|
||||
static RefPtr<StringImpl> create_lowercased(char const* cstring, size_t length);
|
||||
static RefPtr<StringImpl> create_uppercased(char const* cstring, size_t length);
|
||||
|
||||
NonnullRefPtr<StringImpl> to_lowercase() const;
|
||||
NonnullRefPtr<StringImpl> to_uppercase() const;
|
||||
|
||||
|
|
|
@ -173,6 +173,16 @@ bool StringView::equals_ignoring_case(const StringView& other) const
|
|||
return StringUtils::equals_ignoring_case(*this, other);
|
||||
}
|
||||
|
||||
String StringView::to_lowercase_string() const
|
||||
{
|
||||
return StringImpl::create_lowercased(characters_without_null_termination(), length());
|
||||
}
|
||||
|
||||
String StringView::to_uppercase_string() const
|
||||
{
|
||||
return StringImpl::create_uppercased(characters_without_null_termination(), length());
|
||||
}
|
||||
|
||||
StringView StringView::substring_view_starting_from_substring(const StringView& substring) const
|
||||
{
|
||||
const char* remaining_characters = substring.characters_without_null_termination();
|
||||
|
|
|
@ -83,6 +83,9 @@ public:
|
|||
[[nodiscard]] StringView trim(const StringView& characters, TrimMode mode = TrimMode::Both) const { return StringUtils::trim(*this, characters, mode); }
|
||||
[[nodiscard]] StringView trim_whitespace(TrimMode mode = TrimMode::Both) const { return StringUtils::trim_whitespace(*this, mode); }
|
||||
|
||||
[[nodiscard]] String to_lowercase_string() const;
|
||||
[[nodiscard]] String to_uppercase_string() const;
|
||||
|
||||
Optional<size_t> find_first_of(char) const;
|
||||
Optional<size_t> find_first_of(const StringView&) const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue