Use LocalVector in Array

This commit is contained in:
Nazarii 2024-10-04 12:06:27 +03:00
parent 1917bc3454
commit 3d9a8b5585

View file

@ -44,7 +44,7 @@
class ArrayPrivate { class ArrayPrivate {
public: public:
SafeRefCount refcount; SafeRefCount refcount;
Vector<Variant> array; LocalVector<Variant> array;
Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values. Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values.
ContainerTypeValidate typed; ContainerTypeValidate typed;
}; };
@ -82,11 +82,11 @@ void Array::_unref() const {
} }
Array::Iterator Array::begin() { Array::Iterator Array::begin() {
return Iterator(_p->array.ptrw(), _p->read_only); return Iterator(_p->array.ptr(), _p->read_only);
} }
Array::Iterator Array::end() { Array::Iterator Array::end() {
return Iterator(_p->array.ptrw() + _p->array.size(), _p->read_only); return Iterator(_p->array.ptr() + _p->array.size(), _p->read_only);
} }
Array::ConstIterator Array::begin() const { Array::ConstIterator Array::begin() const {
@ -102,7 +102,7 @@ Variant &Array::operator[](int p_idx) {
*_p->read_only = _p->array[p_idx]; *_p->read_only = _p->array[p_idx];
return *_p->read_only; return *_p->read_only;
} }
return _p->array.write[p_idx]; return _p->array[p_idx];
} }
const Variant &Array::operator[](int p_idx) const { const Variant &Array::operator[](int p_idx) const {
@ -139,9 +139,9 @@ bool Array::recursive_equal(const Array &p_array, int recursion_count) const {
if (_p == p_array._p) { if (_p == p_array._p) {
return true; return true;
} }
const Vector<Variant> &a1 = _p->array; const LocalVector<Variant> &a1 = _p->array;
const Vector<Variant> &a2 = p_array._p->array; const LocalVector<Variant> &a2 = p_array._p->array;
const int size = a1.size(); const uint32_t size = a1.size();
if (size != a2.size()) { if (size != a2.size()) {
return false; return false;
} }
@ -152,7 +152,7 @@ bool Array::recursive_equal(const Array &p_array, int recursion_count) const {
return true; return true;
} }
recursion_count++; recursion_count++;
for (int i = 0; i < size; i++) { for (uint32_t i = 0; i < size; i++) {
if (!a1[i].hash_compare(a2[i], recursion_count, false)) { if (!a1[i].hash_compare(a2[i], recursion_count, false)) {
return false; return false;
} }
@ -201,7 +201,7 @@ uint32_t Array::recursive_hash(int recursion_count) const {
uint32_t h = hash_murmur3_one_32(Variant::ARRAY); uint32_t h = hash_murmur3_one_32(Variant::ARRAY);
recursion_count++; recursion_count++;
for (int i = 0; i < _p->array.size(); i++) { for (uint32_t i = 0; i < _p->array.size(); i++) {
h = hash_murmur3_one_32(_p->array[i].recursive_hash(recursion_count), h); h = hash_murmur3_one_32(_p->array[i].recursive_hash(recursion_count), h);
} }
return hash_fmix32(h); return hash_fmix32(h);
@ -227,12 +227,12 @@ void Array::assign(const Array &p_array) {
} }
const Variant *source = p_array._p->array.ptr(); const Variant *source = p_array._p->array.ptr();
int size = p_array._p->array.size(); uint32_t size = p_array._p->array.size();
if ((source_typed.type == Variant::NIL && typed.type == Variant::OBJECT) || (source_typed.type == Variant::OBJECT && source_typed.can_reference(typed))) { if ((source_typed.type == Variant::NIL && typed.type == Variant::OBJECT) || (source_typed.type == Variant::OBJECT && source_typed.can_reference(typed))) {
// from variants to objects or // from variants to objects or
// from base classes to subclasses // from base classes to subclasses
for (int i = 0; i < size; i++) { for (uint32_t i = 0; i < size; i++) {
const Variant &element = source[i]; const Variant &element = source[i];
if (element.get_type() != Variant::NIL && (element.get_type() != Variant::OBJECT || !typed.validate_object(element, "assign"))) { if (element.get_type() != Variant::NIL && (element.get_type() != Variant::OBJECT || !typed.validate_object(element, "assign"))) {
ERR_FAIL_MSG(vformat(R"(Unable to convert array index %d from "%s" to "%s".)", i, Variant::get_type_name(element.get_type()), Variant::get_type_name(typed.type))); ERR_FAIL_MSG(vformat(R"(Unable to convert array index %d from "%s" to "%s".)", i, Variant::get_type_name(element.get_type()), Variant::get_type_name(typed.type)));
@ -245,13 +245,14 @@ void Array::assign(const Array &p_array) {
ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Array[%s]" to "Array[%s]".)", Variant::get_type_name(source_typed.type), Variant::get_type_name(typed.type))); ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Array[%s]" to "Array[%s]".)", Variant::get_type_name(source_typed.type), Variant::get_type_name(typed.type)));
} }
Vector<Variant> array; LocalVector<Variant, uint32_t> &array = _p->array;
array.clear();
array.resize(size); array.resize(size);
Variant *data = array.ptrw(); Variant *data = array.ptr();
if (source_typed.type == Variant::NIL && typed.type != Variant::OBJECT) { if (source_typed.type == Variant::NIL && typed.type != Variant::OBJECT) {
// from variants to primitives // from variants to primitives
for (int i = 0; i < size; i++) { for (uint32_t i = 0; i < size; i++) {
const Variant *value = source + i; const Variant *value = source + i;
if (value->get_type() == typed.type) { if (value->get_type() == typed.type) {
data[i] = *value; data[i] = *value;
@ -266,7 +267,7 @@ void Array::assign(const Array &p_array) {
} }
} else if (Variant::can_convert_strict(source_typed.type, typed.type)) { } else if (Variant::can_convert_strict(source_typed.type, typed.type)) {
// from primitives to different convertible primitives // from primitives to different convertible primitives
for (int i = 0; i < size; i++) { for (uint32_t i = 0; i < size; i++) {
const Variant *value = source + i; const Variant *value = source + i;
Callable::CallError ce; Callable::CallError ce;
Variant::construct(typed.type, data[i], &value, 1, ce); Variant::construct(typed.type, data[i], &value, 1, ce);
@ -275,8 +276,6 @@ void Array::assign(const Array &p_array) {
} else { } else {
ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Array[%s]" to "Array[%s]".)", Variant::get_type_name(source_typed.type), Variant::get_type_name(typed.type))); ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Array[%s]" to "Array[%s]".)", Variant::get_type_name(source_typed.type), Variant::get_type_name(typed.type)));
} }
_p->array = array;
} }
void Array::push_back(const Variant &p_value) { void Array::push_back(const Variant &p_value) {
@ -289,39 +288,48 @@ void Array::push_back(const Variant &p_value) {
void Array::append_array(const Array &p_array) { void Array::append_array(const Array &p_array) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state."); ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
Vector<Variant> validated_array = p_array._p->array; LocalVector<Variant> &validated_array = p_array._p->array;
for (int i = 0; i < validated_array.size(); ++i) { LocalVector<Variant> &array = _p->array;
ERR_FAIL_COND(!_p->typed.validate(validated_array.write[i], "append_array")); for (uint32_t i = 0; i < validated_array.size(); ++i) {
ERR_FAIL_COND(!_p->typed.validate(validated_array[i], "append_array"));
}
uint32_t current_size = array.size();
array.resize(array.size() + validated_array.size());
for (uint32_t i = current_size; i < array.size(); i++) {
array[i] = validated_array[i - current_size];
} }
_p->array.append_array(validated_array);
} }
Error Array::resize(int p_new_size) { Error Array::resize(int p_new_size) {
ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state."); ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state.");
ERR_FAIL_INDEX_V_MSG(p_new_size, INT32_MAX, ERR_INVALID_PARAMETER, "Trying to resize with invalid size.");
Variant::Type &variant_type = _p->typed.type; Variant::Type &variant_type = _p->typed.type;
int old_size = _p->array.size(); int old_size = _p->array.size();
Error err = _p->array.resize_zeroed(p_new_size); _p->array.resize(p_new_size);
if (!err && variant_type != Variant::NIL && variant_type != Variant::OBJECT) { if (variant_type != Variant::NIL && variant_type != Variant::OBJECT) {
for (int i = old_size; i < p_new_size; i++) { for (int i = old_size; i < p_new_size; i++) {
VariantInternal::initialize(&_p->array.write[i], variant_type); VariantInternal::initialize(&_p->array[i], variant_type);
} }
} }
return err; return OK;
} }
Error Array::insert(int p_pos, const Variant &p_value) { Error Array::insert(int p_pos, const Variant &p_value) {
ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state."); ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state.");
Variant value = p_value; Variant value = p_value;
ERR_FAIL_COND_V(!_p->typed.validate(value, "insert"), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(!_p->typed.validate(value, "insert"), ERR_INVALID_PARAMETER);
return _p->array.insert(p_pos, value); ERR_FAIL_INDEX_V(p_pos, (int)_p->array.size() + 1, ERR_INVALID_PARAMETER);
_p->array.insert(p_pos, value);
return OK;
} }
void Array::fill(const Variant &p_value) { void Array::fill(const Variant &p_value) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state."); ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
Variant value = p_value; Variant value = p_value;
ERR_FAIL_COND(!_p->typed.validate(value, "fill")); ERR_FAIL_COND(!_p->typed.validate(value, "fill"));
_p->array.fill(value); for (Variant &var : _p->array) {
var = p_value;
}
} }
void Array::erase(const Variant &p_value) { void Array::erase(const Variant &p_value) {
@ -408,7 +416,7 @@ int Array::rfind(const Variant &p_value, int p_from) const {
// Relative offset from the end // Relative offset from the end
p_from = _p->array.size() + p_from; p_from = _p->array.size() + p_from;
} }
if (p_from < 0 || p_from >= _p->array.size()) { if (p_from < 0 || p_from >= (int)_p->array.size()) {
// Limit to array boundaries // Limit to array boundaries
p_from = _p->array.size() - 1; p_from = _p->array.size() - 1;
} }
@ -431,7 +439,7 @@ int Array::rfind_custom(const Callable &p_callable, int p_from) const {
// Relative offset from the end. // Relative offset from the end.
p_from = _p->array.size() + p_from; p_from = _p->array.size() + p_from;
} }
if (p_from < 0 || p_from >= _p->array.size()) { if (p_from < 0 || p_from >= (int)_p->array.size()) {
// Limit to array boundaries. // Limit to array boundaries.
p_from = _p->array.size() - 1; p_from = _p->array.size() - 1;
} }
@ -465,7 +473,7 @@ int Array::count(const Variant &p_value) const {
} }
int amount = 0; int amount = 0;
for (int i = 0; i < _p->array.size(); i++) { for (uint32_t i = 0; i < _p->array.size(); i++) {
if (StringLikeVariantComparator::compare(_p->array[i], value)) { if (StringLikeVariantComparator::compare(_p->array[i], value)) {
amount++; amount++;
} }
@ -697,7 +705,9 @@ void Array::sort() {
void Array::sort_custom(const Callable &p_callable) { void Array::sort_custom(const Callable &p_callable) {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state."); ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.sort_custom<CallableComparator, true>(p_callable); Variant *data = _p->array.ptr();
SortArray<Variant, CallableComparator, true> sorter{ p_callable };
sorter.sort(data, _p->array.size());
} }
void Array::shuffle() { void Array::shuffle() {
@ -706,7 +716,7 @@ void Array::shuffle() {
if (n < 2) { if (n < 2) {
return; return;
} }
Variant *data = _p->array.ptrw(); Variant *data = _p->array.ptr();
for (int i = n - 1; i >= 1; i--) { for (int i = n - 1; i >= 1; i--) {
const int j = Math::rand() % (i + 1); const int j = Math::rand() % (i + 1);
const Variant tmp = data[j]; const Variant tmp = data[j];
@ -719,19 +729,22 @@ int Array::bsearch(const Variant &p_value, bool p_before) const {
Variant value = p_value; Variant value = p_value;
ERR_FAIL_COND_V(!_p->typed.validate(value, "binary search"), -1); ERR_FAIL_COND_V(!_p->typed.validate(value, "binary search"), -1);
SearchArray<Variant, _ArrayVariantSort> avs; SearchArray<Variant, _ArrayVariantSort> avs;
return avs.bisect(_p->array.ptrw(), _p->array.size(), value, p_before); return avs.bisect(_p->array.ptr(), _p->array.size(), value, p_before);
} }
int Array::bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before) const { int Array::bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before) const {
Variant value = p_value; Variant value = p_value;
ERR_FAIL_COND_V(!_p->typed.validate(value, "custom binary search"), -1); ERR_FAIL_COND_V(!_p->typed.validate(value, "custom binary search"), -1);
SearchArray<Variant, CallableComparator> search{ p_callable };
return _p->array.bsearch_custom<CallableComparator>(value, p_before, p_callable); return search.bisect(_p->array.ptr(), _p->array.size(), p_value, p_before);
} }
void Array::reverse() { void Array::reverse() {
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state."); ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.reverse(); for (uint32_t i = 0; i < _p->array.size() / 2; i++) {
Variant *p = _p->array.ptr();
SWAP(p[i], p[_p->array.size() - i - 1]);
}
} }
void Array::push_front(const Variant &p_value) { void Array::push_front(const Variant &p_value) {
@ -744,8 +757,8 @@ void Array::push_front(const Variant &p_value) {
Variant Array::pop_back() { Variant Array::pop_back() {
ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state."); ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state.");
if (!_p->array.is_empty()) { if (!_p->array.is_empty()) {
const int n = _p->array.size() - 1; const uint32_t n = _p->array.size() - 1;
const Variant ret = _p->array.get(n); const Variant ret = _p->array[n];
_p->array.resize(n); _p->array.resize(n);
return ret; return ret;
} }
@ -755,7 +768,7 @@ Variant Array::pop_back() {
Variant Array::pop_front() { Variant Array::pop_front() {
ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state."); ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state.");
if (!_p->array.is_empty()) { if (!_p->array.is_empty()) {
const Variant ret = _p->array.get(0); const Variant ret = _p->array[0];
_p->array.remove_at(0); _p->array.remove_at(0);
return ret; return ret;
} }
@ -776,14 +789,14 @@ Variant Array::pop_at(int p_pos) {
ERR_FAIL_INDEX_V_MSG( ERR_FAIL_INDEX_V_MSG(
p_pos, p_pos,
_p->array.size(), (int)_p->array.size(),
Variant(), Variant(),
vformat( vformat(
"The calculated index %s is out of bounds (the array has %s elements). Leaving the array untouched and returning `null`.", "The calculated index %s is out of bounds (the array has %s elements). Leaving the array untouched and returning `null`.",
p_pos, p_pos,
_p->array.size())); _p->array.size()));
const Variant ret = _p->array.get(p_pos); const Variant ret = _p->array[p_pos];
_p->array.remove_at(p_pos); _p->array.remove_at(p_pos);
return ret; return ret;
} }