mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 17:10:23 +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
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/CharacterTypes.h>
|
||||||
#include <AK/FlyString.h>
|
#include <AK/FlyString.h>
|
||||||
#include <AK/HashTable.h>
|
#include <AK/HashTable.h>
|
||||||
#include <AK/Memory.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);
|
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';
|
if (!cstring)
|
||||||
}
|
return nullptr;
|
||||||
|
if (!length)
|
||||||
static inline char to_ascii_lowercase(char c)
|
return the_empty_stringimpl();
|
||||||
{
|
char* buffer;
|
||||||
if (is_ascii_uppercase(c))
|
auto impl = create_uninitialized(length, buffer);
|
||||||
return c | 0x20;
|
for (size_t i = 0; i < length; ++i)
|
||||||
return c;
|
buffer[i] = (char)to_ascii_uppercase(cstring[i]);
|
||||||
}
|
return impl;
|
||||||
|
|
||||||
static inline char to_ascii_uppercase(char c)
|
|
||||||
{
|
|
||||||
if (is_ascii_lowercase(c))
|
|
||||||
return c & ~0x20;
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<StringImpl> StringImpl::to_lowercase() const
|
NonnullRefPtr<StringImpl> StringImpl::to_lowercase() const
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < m_length; ++i) {
|
for (size_t i = 0; i < m_length; ++i) {
|
||||||
if (!is_ascii_lowercase(characters()[i]))
|
if (is_ascii_upper_alpha(characters()[i]))
|
||||||
goto slow_path;
|
return create_lowercased(characters(), m_length).release_nonnull();
|
||||||
}
|
}
|
||||||
return const_cast<StringImpl&>(*this);
|
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
|
NonnullRefPtr<StringImpl> StringImpl::to_uppercase() const
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < m_length; ++i) {
|
for (size_t i = 0; i < m_length; ++i) {
|
||||||
if (!is_ascii_uppercase(characters()[i]))
|
if (is_ascii_lower_alpha(characters()[i]))
|
||||||
goto slow_path;
|
return create_uppercased(characters(), m_length).release_nonnull();
|
||||||
}
|
}
|
||||||
return const_cast<StringImpl&>(*this);
|
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
|
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, ShouldChomp = NoChomp);
|
||||||
static RefPtr<StringImpl> create(const char* cstring, size_t length, 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(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_lowercase() const;
|
||||||
NonnullRefPtr<StringImpl> to_uppercase() 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);
|
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
|
StringView StringView::substring_view_starting_from_substring(const StringView& substring) const
|
||||||
{
|
{
|
||||||
const char* remaining_characters = substring.characters_without_null_termination();
|
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(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]] 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(char) const;
|
||||||
Optional<size_t> find_first_of(const StringView&) const;
|
Optional<size_t> find_first_of(const StringView&) const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue