From 6b7cf6a432905868593cd363a7bc05a73b2cbcf7 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 7 Apr 2024 20:39:00 +1000 Subject: [PATCH] SmallString: Add missing methods --- src/common/small_string.cpp | 135 ++++++++++++++++++++++++++++++++++-- src/common/small_string.h | 17 ++++- 2 files changed, 143 insertions(+), 9 deletions(-) diff --git a/src/common/small_string.cpp b/src/common/small_string.cpp index 384341599..94acb4833 100644 --- a/src/common/small_string.cpp +++ b/src/common/small_string.cpp @@ -455,7 +455,13 @@ bool SmallStringBase::equals(const SmallStringBase& str) const bool SmallStringBase::equals(const std::string_view str) const { return (m_length == static_cast(str.length()) && - (m_length == 0 || CASE_N_COMPARE(m_buffer, str.data(), m_length) == 0)); + (m_length == 0 || std::memcmp(m_buffer, str.data(), m_length) == 0)); +} + +bool SmallStringBase::equals(const std::string& str) const +{ + return (m_length == static_cast(str.length()) && + (m_length == 0 || std::memcmp(m_buffer, str.data(), m_length) == 0)); } bool SmallStringBase::iequals(const char* otherText) const @@ -477,24 +483,108 @@ bool SmallStringBase::iequals(const std::string_view str) const (m_length == 0 || CASE_N_COMPARE(m_buffer, str.data(), m_length) == 0)); } -int SmallStringBase::compare(const SmallStringBase& str) const +bool SmallStringBase::iequals(const std::string& str) const { - return std::strcmp(m_buffer, str.m_buffer); + return (m_length == static_cast(str.length()) && + (m_length == 0 || CASE_N_COMPARE(m_buffer, str.data(), m_length) == 0)); } int SmallStringBase::compare(const char* otherText) const { - return std::strcmp(m_buffer, otherText); + return compare(std::string_view(otherText)); } -int SmallStringBase::icompare(const SmallStringBase& otherString) const +int SmallStringBase::compare(const SmallStringBase& str) const { - return CASE_COMPARE(m_buffer, otherString.m_buffer); + if (m_length == 0) + return (str.m_length == 0) ? 0 : -1; + else if (str.m_length == 0) + return 1; + + const int res = std::strncmp(m_buffer, str.m_buffer, std::min(m_length, str.m_length)); + if (m_length == str.m_length || res != 0) + return res; + else + return (m_length > str.m_length) ? 1 : -1; +} + +int SmallStringBase::compare(const std::string_view str) const +{ + const u32 slength = static_cast(str.length()); + if (m_length == 0) + return (slength == 0) ? 0 : -1; + else if (slength == 0) + return 1; + + const int res = std::strncmp(m_buffer, str.data(), std::min(m_length, slength)); + if (m_length == slength || res != 0) + return res; + else + return (m_length > slength) ? 1 : -1; +} + +int SmallStringBase::compare(const std::string& str) const +{ + const u32 slength = static_cast(str.length()); + if (m_length == 0) + return (slength == 0) ? 0 : -1; + else if (slength == 0) + return 1; + + const int res = std::strncmp(m_buffer, str.data(), std::min(m_length, slength)); + if (m_length == slength || res != 0) + return res; + else + return (m_length > slength) ? 1 : -1; } int SmallStringBase::icompare(const char* otherText) const { - return CASE_COMPARE(m_buffer, otherText); + return icompare(std::string_view(otherText)); +} + +int SmallStringBase::icompare(const SmallStringBase& str) const +{ + if (m_length == 0) + return (str.m_length == 0) ? 0 : -1; + else if (str.m_length == 0) + return 1; + + const int res = CASE_N_COMPARE(m_buffer, str.m_buffer, std::min(m_length, str.m_length)); + if (m_length == str.m_length || res != 0) + return res; + else + return (m_length > str.m_length) ? 1 : -1; +} + +int SmallStringBase::icompare(const std::string_view str) const +{ + const u32 slength = static_cast(str.length()); + if (m_length == 0) + return (slength == 0) ? 0 : -1; + else if (slength == 0) + return 1; + + const int res = CASE_N_COMPARE(m_buffer, str.data(), std::min(m_length, slength)); + if (m_length == slength || res != 0) + return res; + else + return (m_length > slength) ? 1 : -1; +} + +int SmallStringBase::icompare(const std::string& str) const +{ + const u32 slength = static_cast(str.length()); + if (m_length == 0) + return (slength == 0) ? 0 : -1; + else if (slength == 0) + return 1; + + const int res = CASE_N_COMPARE(m_buffer, str.data(), std::min(m_length, slength)); + if (m_length == slength || res != 0) + return res; + else + return (m_length > slength) ? 1 : -1; } bool SmallStringBase::starts_with(const char* str, bool case_sensitive) const @@ -527,6 +617,16 @@ bool SmallStringBase::starts_with(const std::string_view str, bool case_sensitiv (CASE_N_COMPARE(str.data(), m_buffer, other_length) == 0); } +bool SmallStringBase::starts_with(const std::string& str, bool case_sensitive) const +{ + const u32 other_length = static_cast(str.length()); + if (other_length > m_length) + return false; + + return (case_sensitive) ? (std::strncmp(str.data(), m_buffer, other_length) == 0) : + (CASE_N_COMPARE(str.data(), m_buffer, other_length) == 0); +} + bool SmallStringBase::ends_with(const char* str, bool case_sensitive) const { const u32 other_length = static_cast(std::strlen(str)); @@ -560,6 +660,17 @@ bool SmallStringBase::ends_with(const std::string_view str, bool case_sensitive) (CASE_N_COMPARE(str.data(), m_buffer + start_offset, other_length) == 0); } +bool SmallStringBase::ends_with(const std::string& str, bool case_sensitive) const +{ + const u32 other_length = static_cast(str.length()); + if (other_length > m_length) + return false; + + const u32 start_offset = m_length - other_length; + return (case_sensitive) ? (std::strncmp(str.data(), m_buffer + start_offset, other_length) == 0) : + (CASE_N_COMPARE(str.data(), m_buffer + start_offset, other_length) == 0); +} + void SmallStringBase::clear() { // in debug, zero whole string, in release, zero only the first character @@ -601,6 +712,16 @@ s32 SmallStringBase::find(const char* str, u32 offset) const return at ? static_cast(at - m_buffer) : -1; } +u32 SmallStringBase::count(char ch) const +{ + const char* ptr = m_buffer; + const char* end = ptr + m_length; + u32 count = 0; + while (ptr != end) + count += static_cast(*(ptr++) == ch); + return count; +} + void SmallStringBase::resize(u32 new_size, char fill, bool shrink_if_smaller) { // if going larger, or we don't own the buffer, realloc diff --git a/src/common/small_string.h b/src/common/small_string.h index c8a52f9e7..b92711def 100644 --- a/src/common/small_string.h +++ b/src/common/small_string.h @@ -102,25 +102,31 @@ public: bool equals(const char* str) const; bool equals(const SmallStringBase& str) const; bool equals(const std::string_view str) const; + bool equals(const std::string& str) const; bool iequals(const char* str) const; bool iequals(const SmallStringBase& str) const; bool iequals(const std::string_view str) const; + bool iequals(const std::string& str) const; // numerical compares int compare(const char* str) const; int compare(const SmallStringBase& str) const; int compare(const std::string_view str) const; + int compare(const std::string& str) const; int icompare(const char* str) const; int icompare(const SmallStringBase& str) const; int icompare(const std::string_view str) const; + int icompare(const std::string& str) const; // starts with / ends with bool starts_with(const char* str, bool case_sensitive = true) const; - bool starts_with(const std::string_view str, bool case_sensitive = true) const; bool starts_with(const SmallStringBase& str, bool case_sensitive = true) const; + bool starts_with(const std::string_view str, bool case_sensitive = true) const; + bool starts_with(const std::string& str, bool case_sensitive = true) const; bool ends_with(const char* str, bool case_sensitive = true) const; - bool ends_with(const std::string_view str, bool case_sensitive = true) const; bool ends_with(const SmallStringBase& str, bool case_sensitive = true) const; + bool ends_with(const std::string_view str, bool case_sensitive = true) const; + bool ends_with(const std::string& str, bool case_sensitive = true) const; // searches for a character inside a string // rfind is the same except it starts at the end instead of the start @@ -133,6 +139,9 @@ public: // returns -1 if it is not found, otherwise the offset in the string s32 find(const char* str, u32 offset = 0) const; + // returns the number of instances of the specified character + u32 count(char ch) const; + // removes characters from string void erase(s32 offset, s32 count = std::numeric_limits::max()); @@ -182,15 +191,19 @@ public: ALWAYS_INLINE bool operator==(const char* str) const { return equals(str); } ALWAYS_INLINE bool operator==(const SmallStringBase& str) const { return equals(str); } ALWAYS_INLINE bool operator==(const std::string_view str) const { return equals(str); } + ALWAYS_INLINE bool operator==(const std::string& str) const { return equals(str); } ALWAYS_INLINE bool operator!=(const char* str) const { return !equals(str); } ALWAYS_INLINE bool operator!=(const SmallStringBase& str) const { return !equals(str); } ALWAYS_INLINE bool operator!=(const std::string_view str) const { return !equals(str); } + ALWAYS_INLINE bool operator!=(const std::string& str) const { return !equals(str); } ALWAYS_INLINE bool operator<(const char* str) const { return (compare(str) < 0); } ALWAYS_INLINE bool operator<(const SmallStringBase& str) const { return (compare(str) < 0); } ALWAYS_INLINE bool operator<(const std::string_view str) const { return (compare(str) < 0); } + ALWAYS_INLINE bool operator<(const std::string& str) const { return (compare(str) < 0); } ALWAYS_INLINE bool operator>(const char* str) const { return (compare(str) > 0); } ALWAYS_INLINE bool operator>(const SmallStringBase& str) const { return (compare(str) > 0); } ALWAYS_INLINE bool operator>(const std::string_view str) const { return (compare(str) > 0); } + ALWAYS_INLINE bool operator>(const std::string& str) const { return (compare(str) > 0); } SmallStringBase& operator=(const SmallStringBase& copy); SmallStringBase& operator=(const char* str);