diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 9e6701bcf4d..18bc9372a4b 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -303,28 +303,8 @@ String &String::operator+=(char32_t p_char) { } bool String::operator==(const char *p_str) const { - // compare Latin-1 encoded c-string - int len = strlen(p_str); - - if (length() != len) { - return false; - } - if (is_empty()) { - return true; - } - - int l = length(); - - const char32_t *dst = get_data(); - - // Compare char by char - for (int i = 0; i < l; i++) { - if ((char32_t)p_str[i] != dst[i]) { - return false; - } - } - - return true; + // Compare Latin-1 encoded c-string. + return span() == Span(p_str, strlen(p_str)).reinterpret(); } bool String::operator==(const wchar_t *p_str) const { @@ -338,40 +318,16 @@ bool String::operator==(const wchar_t *p_str) const { } bool String::operator==(const char32_t *p_str) const { - const int len = strlen(p_str); - - if (length() != len) { - return false; - } - if (is_empty()) { - return true; - } - - return memcmp(ptr(), p_str, len * sizeof(char32_t)) == 0; + // Compare UTF-32 encoded c-string. + return span() == Span(p_str, strlen(p_str)); } bool String::operator==(const String &p_str) const { - if (length() != p_str.length()) { - return false; - } - if (is_empty()) { - return true; - } - - return memcmp(ptr(), p_str.ptr(), length() * sizeof(char32_t)) == 0; + return span() == p_str.span(); } bool String::operator==(const Span &p_str_range) const { - const int len = p_str_range.size(); - - if (length() != len) { - return false; - } - if (is_empty()) { - return true; - } - - return memcmp(ptr(), p_str_range.ptr(), len * sizeof(char32_t)) == 0; + return span() == p_str_range; } bool operator==(const char *p_chr, const String &p_str) { @@ -384,7 +340,7 @@ bool operator==(const wchar_t *p_chr, const String &p_str) { return p_str == String::utf16((const char16_t *)p_chr); #else // wchar_t is 32-bi - return p_str == String((const char32_t *)p_chr); + return p_str == (const char32_t *)p_chr; #endif } diff --git a/core/string/ustring.h b/core/string/ustring.h index eeedd3edfdb..187821da50c 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -211,12 +211,7 @@ public: _FORCE_INLINE_ CharStringT(const T *p_cstr) { copy_from(p_cstr); } _FORCE_INLINE_ void operator=(const T *p_cstr) { copy_from(p_cstr); } - _FORCE_INLINE_ bool operator==(const CharStringT &p_other) const { - if (length() != p_other.length()) { - return false; - } - return memcmp(ptr(), p_other.ptr(), length() * sizeof(T)) == 0; - } + _FORCE_INLINE_ bool operator==(const CharStringT &p_other) const { return span() == p_other.span(); } _FORCE_INLINE_ bool operator!=(const CharStringT &p_other) const { return !(*this == p_other); } _FORCE_INLINE_ bool operator<(const CharStringT &p_other) const { if (length() == 0) { diff --git a/core/templates/span.h b/core/templates/span.h index b179d278ca4..db66527a86e 100644 --- a/core/templates/span.h +++ b/core/templates/span.h @@ -33,6 +33,24 @@ #include "core/error/error_macros.h" #include "core/typedefs.h" +template +bool are_spans_equal(const LHS *p_lhs, const RHS *p_rhs, size_t p_size) { + if constexpr (std::is_same_v && std::is_fundamental_v) { + // Optimize trivial type comparison. + // is_trivially_equality_comparable would help, but it doesn't exist. + return memcmp(p_lhs, p_rhs, p_size * sizeof(LHS)) == 0; + } else { + // Normal case: Need to iterate the array manually. + for (size_t j = 0; j < p_size; j++) { + if (p_lhs[j] != p_rhs[j]) { + return false; + } + } + + return true; + } +} + // Equivalent of std::span. // Represents a view into a contiguous memory space. // DISCLAIMER: This data type does not own the underlying buffer. DO NOT STORE IT. @@ -126,14 +144,7 @@ constexpr int64_t Span::find(const T &p_val, uint64_t p_from) const { template constexpr int64_t Span::find_sequence(const Span &p_span, uint64_t p_from) const { for (uint64_t i = p_from; i <= size() - p_span.size(); i++) { - bool found = true; - for (uint64_t j = 0; j < p_span.size(); j++) { - if (ptr()[i + j] != p_span.ptr()[j]) { - found = false; - break; - } - } - if (found) { + if (are_spans_equal(ptr() + i, p_span.ptr(), p_span.size())) { return i; } } @@ -154,14 +165,7 @@ constexpr int64_t Span::rfind(const T &p_val, uint64_t p_from) const { template constexpr int64_t Span::rfind_sequence(const Span &p_span, uint64_t p_from) const { for (int64_t i = p_from; i >= 0; i--) { - bool found = true; - for (uint64_t j = 0; j < p_span.size(); j++) { - if (ptr()[i + j] != p_span.ptr()[j]) { - found = false; - break; - } - } - if (found) { + if (are_spans_equal(ptr() + i, p_span.ptr(), p_span.size())) { return i; } } @@ -219,6 +223,16 @@ constexpr T Span::max() const { return max_val; } +template +bool operator==(const Span &p_lhs, const Span &p_rhs) { + return p_lhs.size() == p_rhs.size() && are_spans_equal(p_lhs.ptr(), p_rhs.ptr(), p_lhs.size()); +} + +template +_FORCE_INLINE_ bool operator!=(const Span &p_lhs, const Span &p_rhs) { + return !(p_lhs == p_rhs); +} + // Zero-constructing Span initializes _ptr and _len to 0 (and thus empty). template struct is_zero_constructible> : std::true_type {}; diff --git a/core/templates/vector.h b/core/templates/vector.h index 13ef23253cc..25d7166b016 100644 --- a/core/templates/vector.h +++ b/core/templates/vector.h @@ -248,31 +248,8 @@ public: return result; } - bool operator==(const Vector &p_arr) const { - Size s = size(); - if (s != p_arr.size()) { - return false; - } - for (Size i = 0; i < s; i++) { - if (operator[](i) != p_arr[i]) { - return false; - } - } - return true; - } - - bool operator!=(const Vector &p_arr) const { - Size s = size(); - if (s != p_arr.size()) { - return true; - } - for (Size i = 0; i < s; i++) { - if (operator[](i) != p_arr[i]) { - return true; - } - } - return false; - } + bool operator==(const Vector &p_arr) const { return span() == p_arr.span(); } + bool operator!=(const Vector &p_arr) const { return span() != p_arr.span(); } struct Iterator { _FORCE_INLINE_ T &operator*() const { diff --git a/tests/core/templates/test_span.h b/tests/core/templates/test_span.h index 0059d8d4f34..869f8e42213 100644 --- a/tests/core/templates/test_span.h +++ b/tests/core/templates/test_span.h @@ -61,6 +61,10 @@ TEST_CASE("[Span] Constexpr Validators") { static_assert(span_string[0] == U'1'); static_assert(span_string[span_string.size() - 1] == U'5'); + CHECK_EQ(span_string, span_string); // Same identity / ptr. + CHECK_EQ(span_string, Span(U"1223456", 6)); // Different ptr. + CHECK_EQ(span_string, Span("122345").reinterpret()); // Different type. + int idx = 0; for (const char32_t &chr : span_string) { CHECK_EQ(chr, span_string[idx++]);