Add Span equality (== and !=) operators.

Exchange duplicate equality iteration implementations across `Vector` and `String` with the `Span` version, for a speed boost.
This commit is contained in:
Lukas Tenbrink
2025-11-15 13:44:50 +01:00
parent ef34c3d534
commit d7f5c13db8
5 changed files with 44 additions and 98 deletions

View File

@ -33,6 +33,24 @@
#include "core/error/error_macros.h"
#include "core/typedefs.h"
template <typename LHS, typename RHS>
bool are_spans_equal(const LHS *p_lhs, const RHS *p_rhs, size_t p_size) {
if constexpr (std::is_same_v<LHS, RHS> && std::is_fundamental_v<LHS>) {
// 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<T>::find(const T &p_val, uint64_t p_from) const {
template <typename T>
constexpr int64_t Span<T>::find_sequence(const Span<T> &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<T>::rfind(const T &p_val, uint64_t p_from) const {
template <typename T>
constexpr int64_t Span<T>::rfind_sequence(const Span<T> &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<T>::max() const {
return max_val;
}
template <typename LHS, typename RHS>
bool operator==(const Span<LHS> &p_lhs, const Span<RHS> &p_rhs) {
return p_lhs.size() == p_rhs.size() && are_spans_equal(p_lhs.ptr(), p_rhs.ptr(), p_lhs.size());
}
template <typename LHS, typename RHS>
_FORCE_INLINE_ bool operator!=(const Span<LHS> &p_lhs, const Span<RHS> &p_rhs) {
return !(p_lhs == p_rhs);
}
// Zero-constructing Span initializes _ptr and _len to 0 (and thus empty).
template <typename T>
struct is_zero_constructible<Span<T>> : std::true_type {};

View File

@ -248,31 +248,8 @@ public:
return result;
}
bool operator==(const Vector<T> &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<T> &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<T> &p_arr) const { return span() == p_arr.span(); }
bool operator!=(const Vector<T> &p_arr) const { return span() != p_arr.span(); }
struct Iterator {
_FORCE_INLINE_ T &operator*() const {