Use LocalVector in Array
This commit is contained in:
parent
1917bc3454
commit
3d9a8b5585
1 changed files with 55 additions and 42 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue