summaryrefslogtreecommitdiff
path: root/core/variant
diff options
context:
space:
mode:
Diffstat (limited to 'core/variant')
-rw-r--r--core/variant/array.cpp60
-rw-r--r--core/variant/array.h4
-rw-r--r--core/variant/dictionary.cpp143
-rw-r--r--core/variant/dictionary.h3
-rw-r--r--core/variant/variant.h1
-rw-r--r--core/variant/variant_call.cpp39
-rw-r--r--core/variant/variant_construct.h4
-rw-r--r--core/variant/variant_op.cpp6
-rw-r--r--core/variant/variant_op.h18
-rw-r--r--core/variant/variant_parser.h2
-rw-r--r--core/variant/variant_setget.cpp22
11 files changed, 249 insertions, 53 deletions
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index afc4acadf9..7551350c95 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -43,7 +43,7 @@ class ArrayPrivate {
public:
SafeRefCount refcount;
Vector<Variant> array;
-
+ Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values.
ContainerTypeValidate typed;
};
@@ -52,6 +52,16 @@ void Array::_ref(const Array &p_from) const {
ERR_FAIL_COND(!_fp); // should NOT happen.
+ if (unlikely(_fp->read_only != nullptr)) {
+ // If p_from is a read-only array, just copy the contents to avoid further modification.
+ _unref();
+ _p = memnew(ArrayPrivate);
+ _p->refcount.init();
+ _p->array = _fp->array;
+ _p->typed = _fp->typed;
+ return;
+ }
+
if (_fp == _p) {
return; // whatever it is, nothing to do here move along
}
@@ -71,16 +81,27 @@ void Array::_unref() const {
}
if (_p->refcount.unref()) {
+ if (_p->read_only) {
+ memdelete(_p->read_only);
+ }
memdelete(_p);
}
_p = nullptr;
}
Variant &Array::operator[](int p_idx) {
+ if (unlikely(_p->read_only)) {
+ *_p->read_only = _p->array[p_idx];
+ return *_p->read_only;
+ }
return _p->array.write[p_idx];
}
const Variant &Array::operator[](int p_idx) const {
+ if (unlikely(_p->read_only)) {
+ *_p->read_only = _p->array[p_idx];
+ return *_p->read_only;
+ }
return _p->array[p_idx];
}
@@ -93,6 +114,7 @@ bool Array::is_empty() const {
}
void Array::clear() {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.clear();
}
@@ -224,34 +246,43 @@ bool Array::_assign(const Array &p_array) {
}
void Array::operator=(const Array &p_array) {
+ if (this == &p_array) {
+ return;
+ }
_ref(p_array);
}
void Array::push_back(const Variant &p_value) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND(!_p->typed.validate(p_value, "push_back"));
_p->array.push_back(p_value);
}
void Array::append_array(const Array &p_array) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND(!_p->typed.validate(p_array, "append_array"));
_p->array.append_array(p_array._p->array);
}
Error Array::resize(int p_new_size) {
+ ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state.");
return _p->array.resize(p_new_size);
}
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(!_p->typed.validate(p_value, "insert"), ERR_INVALID_PARAMETER);
return _p->array.insert(p_pos, 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(!_p->typed.validate(p_value, "fill"));
_p->array.fill(p_value);
}
void Array::erase(const Variant &p_value) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND(!_p->typed.validate(p_value, "erase"));
_p->array.erase(p_value);
}
@@ -323,10 +354,12 @@ bool Array::has(const Variant &p_value) const {
}
void Array::remove_at(int p_pos) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.remove_at(p_pos);
}
void Array::set(int p_idx, const Variant &p_value) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND(!_p->typed.validate(p_value, "set"));
operator[](p_idx) = p_value;
@@ -481,14 +514,17 @@ struct _ArrayVariantSort {
};
void Array::sort() {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.sort_custom<_ArrayVariantSort>();
}
void Array::sort_custom(const Callable &p_callable) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.sort_custom<CallableComparator, true>(p_callable);
}
void Array::shuffle() {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
const int n = _p->array.size();
if (n < 2) {
return;
@@ -515,15 +551,18 @@ int Array::bsearch_custom(const Variant &p_value, const Callable &p_callable, bo
}
void Array::reverse() {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
_p->array.reverse();
}
void Array::push_front(const Variant &p_value) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND(!_p->typed.validate(p_value, "push_front"));
_p->array.insert(0, p_value);
}
Variant Array::pop_back() {
+ ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state.");
if (!_p->array.is_empty()) {
const int n = _p->array.size() - 1;
const Variant ret = _p->array.get(n);
@@ -534,6 +573,7 @@ Variant Array::pop_back() {
}
Variant Array::pop_front() {
+ ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state.");
if (!_p->array.is_empty()) {
const Variant ret = _p->array.get(0);
_p->array.remove_at(0);
@@ -543,6 +583,7 @@ Variant Array::pop_front() {
}
Variant Array::pop_at(int p_pos) {
+ ERR_FAIL_COND_V_MSG(_p->read_only, Variant(), "Array is in read-only state.");
if (_p->array.is_empty()) {
// Return `null` without printing an error to mimic `pop_back()` and `pop_front()` behavior.
return Variant();
@@ -627,6 +668,7 @@ bool Array::typed_assign(const Array &p_other) {
}
void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script) {
+ ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
ERR_FAIL_COND_MSG(_p->array.size() > 0, "Type can only be set when array is empty.");
ERR_FAIL_COND_MSG(_p->refcount.get() > 1, "Type can only be set when array has no more than one user.");
ERR_FAIL_COND_MSG(_p->typed.type != Variant::NIL, "Type can only be set once.");
@@ -656,6 +698,22 @@ Variant Array::get_typed_script() const {
return _p->typed.script;
}
+void Array::set_read_only(bool p_enable) {
+ if (p_enable == bool(_p->read_only != nullptr)) {
+ return;
+ }
+ if (p_enable) {
+ _p->read_only = memnew(Variant);
+ } else {
+ memdelete(_p->read_only);
+ _p->read_only = nullptr;
+ }
+}
+
+bool Array::is_read_only() const {
+ return _p->read_only != nullptr;
+}
+
Array::Array(const Array &p_from) {
_p = nullptr;
_ref(p_from);
diff --git a/core/variant/array.h b/core/variant/array.h
index ab5f7cd50f..f537700f99 100644
--- a/core/variant/array.h
+++ b/core/variant/array.h
@@ -125,6 +125,10 @@ public:
uint32_t get_typed_builtin() const;
StringName get_typed_class_name() const;
Variant get_typed_script() const;
+
+ void set_read_only(bool p_enable);
+ bool is_read_only() const;
+
Array(const Array &p_from);
Array();
~Array();
diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp
index 0f2f8fc8ed..bda8c93a79 100644
--- a/core/variant/dictionary.cpp
+++ b/core/variant/dictionary.cpp
@@ -30,7 +30,7 @@
#include "dictionary.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
#include "core/templates/safe_refcount.h"
#include "core/variant/variant.h"
// required in this order by VariantInternal, do not remove this comment.
@@ -41,7 +41,8 @@
struct DictionaryPrivate {
SafeRefCount refcount;
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map;
+ Variant *read_only = nullptr; // If enabled, a pointer is used to a temporary value that is used to return read-only values.
+ HashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map;
};
void Dictionary::get_key_list(List<Variant> *p_keys) const {
@@ -49,16 +50,16 @@ void Dictionary::get_key_list(List<Variant> *p_keys) const {
return;
}
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- p_keys->push_back(E.key());
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+ p_keys->push_back(E.key);
}
}
Variant Dictionary::get_key_at_index(int p_index) const {
int index = 0;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
if (index == p_index) {
- return E.key();
+ return E.key;
}
index++;
}
@@ -68,9 +69,9 @@ Variant Dictionary::get_key_at_index(int p_index) const {
Variant Dictionary::get_value_at_index(int p_index) const {
int index = 0;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
if (index == p_index) {
- return E.value();
+ return E.value;
}
index++;
}
@@ -79,11 +80,22 @@ Variant Dictionary::get_value_at_index(int p_index) const {
}
Variant &Dictionary::operator[](const Variant &p_key) {
- if (p_key.get_type() == Variant::STRING_NAME) {
- const StringName *sn = VariantInternal::get_string_name(&p_key);
- return _p->variant_map[sn->operator String()];
+ if (unlikely(_p->read_only)) {
+ if (p_key.get_type() == Variant::STRING_NAME) {
+ const StringName *sn = VariantInternal::get_string_name(&p_key);
+ *_p->read_only = _p->variant_map[sn->operator String()];
+ } else {
+ *_p->read_only = _p->variant_map[p_key];
+ }
+
+ return *_p->read_only;
} else {
- return _p->variant_map[p_key];
+ if (p_key.get_type() == Variant::STRING_NAME) {
+ const StringName *sn = VariantInternal::get_string_name(&p_key);
+ return _p->variant_map[sn->operator String()];
+ } else {
+ return _p->variant_map[p_key];
+ }
}
}
@@ -97,50 +109,55 @@ const Variant &Dictionary::operator[](const Variant &p_key) const {
}
const Variant *Dictionary::getptr(const Variant &p_key) const {
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E;
+ HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator E;
if (p_key.get_type() == Variant::STRING_NAME) {
const StringName *sn = VariantInternal::get_string_name(&p_key);
- E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
+ E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
} else {
- E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+ E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
}
if (!E) {
return nullptr;
}
- return &E.get();
+ return &E->value;
}
Variant *Dictionary::getptr(const Variant &p_key) {
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E;
+ HashMap<Variant, Variant, VariantHasher, VariantComparator>::Iterator E;
if (p_key.get_type() == Variant::STRING_NAME) {
const StringName *sn = VariantInternal::get_string_name(&p_key);
- E = ((OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
+ E = ((HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
} else {
- E = ((OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+ E = ((HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
}
if (!E) {
return nullptr;
}
- return &E.get();
+ if (unlikely(_p->read_only != nullptr)) {
+ *_p->read_only = E->value;
+ return _p->read_only;
+ } else {
+ return &E->value;
+ }
}
Variant Dictionary::get_valid(const Variant &p_key) const {
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E;
+ HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator E;
if (p_key.get_type() == Variant::STRING_NAME) {
const StringName *sn = VariantInternal::get_string_name(&p_key);
- E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
+ E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
} else {
- E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+ E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
}
if (!E) {
return Variant();
}
- return E.get();
+ return E->value;
}
Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const {
@@ -179,6 +196,7 @@ bool Dictionary::has_all(const Array &p_keys) const {
}
bool Dictionary::erase(const Variant &p_key) {
+ ERR_FAIL_COND_V_MSG(_p->read_only, false, "Dictionary is in read-only state.");
if (p_key.get_type() == Variant::STRING_NAME) {
const StringName *sn = VariantInternal::get_string_name(&p_key);
return _p->variant_map.erase(sn->operator String());
@@ -210,9 +228,9 @@ bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_c
return true;
}
recursion_count++;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement this_E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->front(); this_E; this_E = this_E.next()) {
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement other_E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&p_dictionary._p->variant_map)->find(this_E.key());
- if (!other_E || !this_E.value().hash_compare(other_E.value(), recursion_count)) {
+ for (const KeyValue<Variant, Variant> &this_E : _p->variant_map) {
+ HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator other_E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&p_dictionary._p->variant_map)->find(this_E.key);
+ if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count)) {
return false;
}
}
@@ -220,6 +238,16 @@ bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_c
}
void Dictionary::_ref(const Dictionary &p_from) const {
+ if (unlikely(p_from._p->read_only != nullptr)) {
+ // If p_from is a read-only dictionary, just copy the contents to avoid further modification.
+ if (_p) {
+ _unref();
+ }
+ _p = memnew(DictionaryPrivate);
+ _p->refcount.init();
+ _p->variant_map = p_from._p->variant_map;
+ return;
+ }
//make a copy first (thread safe)
if (!p_from._p->refcount.ref()) {
return; // couldn't copy
@@ -237,12 +265,16 @@ void Dictionary::_ref(const Dictionary &p_from) const {
}
void Dictionary::clear() {
+ ERR_FAIL_COND_MSG(_p->read_only, "Dictionary is in read-only state.");
_p->variant_map.clear();
}
void Dictionary::_unref() const {
ERR_FAIL_COND(!_p);
if (_p->refcount.unref()) {
+ if (_p->read_only) {
+ memdelete(_p->read_only);
+ }
memdelete(_p);
}
_p = nullptr;
@@ -261,9 +293,9 @@ uint32_t Dictionary::recursive_hash(int recursion_count) const {
uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);
recursion_count++;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- h = hash_djb2_one_32(E.key().recursive_hash(recursion_count), h);
- h = hash_djb2_one_32(E.value().recursive_hash(recursion_count), h);
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+ h = hash_djb2_one_32(E.key.recursive_hash(recursion_count), h);
+ h = hash_djb2_one_32(E.value.recursive_hash(recursion_count), h);
}
return h;
@@ -278,8 +310,8 @@ Array Dictionary::keys() const {
varr.resize(size());
int i = 0;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- varr[i] = E.key();
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+ varr[i] = E.key;
i++;
}
@@ -295,8 +327,8 @@ Array Dictionary::values() const {
varr.resize(size());
int i = 0;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- varr[i] = E.get();
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+ varr[i] = E.value;
i++;
}
@@ -306,16 +338,23 @@ Array Dictionary::values() const {
const Variant *Dictionary::next(const Variant *p_key) const {
if (p_key == nullptr) {
// caller wants to get the first element
- if (_p->variant_map.front()) {
- return &_p->variant_map.front().key();
+ if (_p->variant_map.begin()) {
+ return &_p->variant_map.begin()->key;
}
return nullptr;
}
- OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(*p_key);
+ HashMap<Variant, Variant, VariantHasher, VariantComparator>::Iterator E = _p->variant_map.find(*p_key);
+
+ if (!E) {
+ return nullptr;
+ }
+
+ ++E;
- if (E && E.next()) {
- return &E.next().key();
+ if (E) {
+ return &E->key;
}
+
return nullptr;
}
@@ -323,6 +362,21 @@ Dictionary Dictionary::duplicate(bool p_deep) const {
return recursive_duplicate(p_deep, 0);
}
+void Dictionary::set_read_only(bool p_enable) {
+ if (p_enable == bool(_p->read_only != nullptr)) {
+ return;
+ }
+ if (p_enable) {
+ _p->read_only = memnew(Variant);
+ } else {
+ memdelete(_p->read_only);
+ _p->read_only = nullptr;
+ }
+}
+bool Dictionary::is_read_only() const {
+ return _p->read_only != nullptr;
+}
+
Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) const {
Dictionary n;
@@ -333,12 +387,12 @@ Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) con
if (p_deep) {
recursion_count++;
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- n[E.key().recursive_duplicate(true, recursion_count)] = E.value().recursive_duplicate(true, recursion_count);
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+ n[E.key.recursive_duplicate(true, recursion_count)] = E.value.recursive_duplicate(true, recursion_count);
}
} else {
- for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
- n[E.key()] = E.value();
+ for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+ n[E.key] = E.value;
}
}
@@ -346,6 +400,9 @@ Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) con
}
void Dictionary::operator=(const Dictionary &p_dictionary) {
+ if (this == &p_dictionary) {
+ return;
+ }
_ref(p_dictionary);
}
diff --git a/core/variant/dictionary.h b/core/variant/dictionary.h
index 16cf0c2bf8..1224a4ff6f 100644
--- a/core/variant/dictionary.h
+++ b/core/variant/dictionary.h
@@ -84,6 +84,9 @@ public:
Dictionary duplicate(bool p_deep = false) const;
Dictionary recursive_duplicate(bool p_deep, int recursion_count) const;
+ void set_read_only(bool p_enable);
+ bool is_read_only() const;
+
const void *id() const;
Dictionary(const Dictionary &p_from);
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 475bf7158d..726ba120b5 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -473,6 +473,7 @@ public:
OP_NEGATE,
OP_POSITIVE,
OP_MODULE,
+ OP_POWER,
//bitwise
OP_SHIFT_LEFT,
OP_SHIFT_RIGHT,
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index f4b2af5a94..a3568a8d6a 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -919,11 +919,11 @@ struct _VariantCall {
}
struct ConstantData {
- Map<StringName, int> value;
+ HashMap<StringName, int> value;
#ifdef DEBUG_ENABLED
List<StringName> value_ordered;
#endif
- Map<StringName, Variant> variant_value;
+ HashMap<StringName, Variant> variant_value;
#ifdef DEBUG_ENABLED
List<StringName> variant_value_ordered;
#endif
@@ -1281,14 +1281,14 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0);
_VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type];
- Map<StringName, int>::Element *E = cd.value.find(p_value);
+ HashMap<StringName, int>::Iterator E = cd.value.find(p_value);
if (!E) {
- Map<StringName, Variant>::Element *F = cd.variant_value.find(p_value);
+ HashMap<StringName, Variant>::Iterator F = cd.variant_value.find(p_value);
if (F) {
if (r_valid) {
*r_valid = true;
}
- return F->get();
+ return F->value;
} else {
return -1;
}
@@ -1297,7 +1297,7 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va
*r_valid = true;
}
- return E->get();
+ return E->value;
}
#ifdef DEBUG_METHODS_ENABLED
@@ -1873,6 +1873,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedByteArray, sort, sarray(), varray());
bind_method(PackedByteArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedByteArray, duplicate, sarray(), varray());
+ bind_method(PackedByteArray, find, sarray("value", "from"), varray(0));
+ bind_method(PackedByteArray, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedByteArray, count, sarray("value"), varray());
bind_function(PackedByteArray, get_string_from_ascii, _VariantCall::func_PackedByteArray_get_string_from_ascii, sarray(), varray());
bind_function(PackedByteArray, get_string_from_utf8, _VariantCall::func_PackedByteArray_get_string_from_utf8, sarray(), varray());
@@ -1935,6 +1938,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedInt32Array, sort, sarray(), varray());
bind_method(PackedInt32Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedInt32Array, duplicate, sarray(), varray());
+ bind_method(PackedInt32Array, find, sarray("value", "from"), varray(0));
+ bind_method(PackedInt32Array, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedInt32Array, count, sarray("value"), varray());
/* Int64 Array */
@@ -1955,6 +1961,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedInt64Array, sort, sarray(), varray());
bind_method(PackedInt64Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedInt64Array, duplicate, sarray(), varray());
+ bind_method(PackedInt64Array, find, sarray("value", "from"), varray(0));
+ bind_method(PackedInt64Array, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedInt64Array, count, sarray("value"), varray());
/* Float32 Array */
@@ -1975,6 +1984,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedFloat32Array, sort, sarray(), varray());
bind_method(PackedFloat32Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedFloat32Array, duplicate, sarray(), varray());
+ bind_method(PackedFloat32Array, find, sarray("value", "from"), varray(0));
+ bind_method(PackedFloat32Array, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedFloat32Array, count, sarray("value"), varray());
/* Float64 Array */
@@ -1995,6 +2007,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedFloat64Array, sort, sarray(), varray());
bind_method(PackedFloat64Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedFloat64Array, duplicate, sarray(), varray());
+ bind_method(PackedFloat64Array, find, sarray("value", "from"), varray(0));
+ bind_method(PackedFloat64Array, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedFloat64Array, count, sarray("value"), varray());
/* String Array */
@@ -2015,6 +2030,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedStringArray, sort, sarray(), varray());
bind_method(PackedStringArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedStringArray, duplicate, sarray(), varray());
+ bind_method(PackedStringArray, find, sarray("value", "from"), varray(0));
+ bind_method(PackedStringArray, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedStringArray, count, sarray("value"), varray());
/* Vector2 Array */
@@ -2035,6 +2053,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedVector2Array, sort, sarray(), varray());
bind_method(PackedVector2Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedVector2Array, duplicate, sarray(), varray());
+ bind_method(PackedVector2Array, find, sarray("value", "from"), varray(0));
+ bind_method(PackedVector2Array, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedVector2Array, count, sarray("value"), varray());
/* Vector3 Array */
@@ -2055,6 +2076,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedVector3Array, sort, sarray(), varray());
bind_method(PackedVector3Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedVector3Array, duplicate, sarray(), varray());
+ bind_method(PackedVector3Array, find, sarray("value", "from"), varray(0));
+ bind_method(PackedVector3Array, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedVector3Array, count, sarray("value"), varray());
/* Color Array */
@@ -2075,6 +2099,9 @@ static void _register_variant_builtin_methods() {
bind_method(PackedColorArray, sort, sarray(), varray());
bind_method(PackedColorArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedColorArray, duplicate, sarray(), varray());
+ bind_method(PackedColorArray, find, sarray("value", "from"), varray(0));
+ bind_method(PackedColorArray, rfind, sarray("value", "from"), varray(-1));
+ bind_method(PackedColorArray, count, sarray("value"), varray());
/* Register constants */
diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h
index ce2e9af04f..638c0136f3 100644
--- a/core/variant/variant_construct.h
+++ b/core/variant/variant_construct.h
@@ -344,7 +344,7 @@ public:
return;
}
- VariantTypeChanger<Array>::change(&r_ret);
+ r_ret = Array();
Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(&r_ret);
const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
@@ -356,7 +356,7 @@ public:
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
- VariantTypeChanger<Array>::change(r_ret);
+ *r_ret = Array();
Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(r_ret);
const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp
index 35e0319aa3..adace2b534 100644
--- a/core/variant/variant_op.cpp
+++ b/core/variant/variant_op.cpp
@@ -361,6 +361,11 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorStringModT<PackedVector3Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_VECTOR3_ARRAY);
register_op<OperatorEvaluatorStringModT<PackedColorArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_COLOR_ARRAY);
+ register_op<OperatorEvaluatorPow<int64_t, int64_t, int64_t>>(Variant::OP_POWER, Variant::INT, Variant::INT);
+ register_op<OperatorEvaluatorPow<double, int64_t, double>>(Variant::OP_POWER, Variant::INT, Variant::FLOAT);
+ register_op<OperatorEvaluatorPow<double, double, double>>(Variant::OP_POWER, Variant::FLOAT, Variant::FLOAT);
+ register_op<OperatorEvaluatorPow<double, double, int64_t>>(Variant::OP_POWER, Variant::FLOAT, Variant::INT);
+
register_op<OperatorEvaluatorNeg<int64_t, int64_t>>(Variant::OP_NEGATE, Variant::INT, Variant::NIL);
register_op<OperatorEvaluatorNeg<double, double>>(Variant::OP_NEGATE, Variant::FLOAT, Variant::NIL);
register_op<OperatorEvaluatorNeg<Vector2, Vector2>>(Variant::OP_NEGATE, Variant::VECTOR2, Variant::NIL);
@@ -929,6 +934,7 @@ static const char *_op_names[Variant::OP_MAX] = {
"unary-",
"unary+",
"%",
+ "**",
"<<",
">>",
"&",
diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h
index f72a92d31a..3e9bae1078 100644
--- a/core/variant/variant_op.h
+++ b/core/variant/variant_op.h
@@ -92,6 +92,24 @@ public:
};
template <class R, class A, class B>
+class OperatorEvaluatorPow {
+public:
+ static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+ const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+ const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+ *r_ret = R(Math::pow((double)a, (double)b));
+ r_valid = true;
+ }
+ static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ *VariantGetInternalPtr<R>::get_ptr(r_ret) = R(Math::pow((double)*VariantGetInternalPtr<A>::get_ptr(left), (double)*VariantGetInternalPtr<B>::get_ptr(right)));
+ }
+ static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+ PtrToArg<R>::encode(R(Math::pow((double)PtrToArg<A>::convert(left), (double)PtrToArg<B>::convert(right))), r_ret);
+ }
+ static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
class OperatorEvaluatorXForm {
public:
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h
index 70ca8d8cb5..56b484c8bc 100644
--- a/core/variant/variant_parser.h
+++ b/core/variant/variant_parser.h
@@ -113,7 +113,7 @@ public:
struct Tag {
String name;
- Map<String, Variant> fields;
+ HashMap<String, Variant> fields;
};
private:
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index 6023e4d129..3839da495f 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -624,6 +624,11 @@ struct VariantIndexedSetGet_Array {
PtrToArg<Variant>::encode(v[index], member);
}
static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) {
+ if (VariantGetInternalPtr<Array>::get_ptr(base)->is_read_only()) {
+ *valid = false;
+ *oob = true;
+ return;
+ }
int64_t size = VariantGetInternalPtr<Array>::get_ptr(base)->size();
if (index < 0) {
index += size;
@@ -638,6 +643,10 @@ struct VariantIndexedSetGet_Array {
*valid = true;
}
static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) {
+ if (VariantGetInternalPtr<Array>::get_ptr(base)->is_read_only()) {
+ *oob = true;
+ return;
+ }
int64_t size = VariantGetInternalPtr<Array>::get_ptr(base)->size();
if (index < 0) {
index += size;
@@ -766,11 +775,20 @@ struct VariantIndexedSetGet_String {
PtrToArg<Variant>::encode(*ptr, member); \
} \
static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \
+ if (VariantGetInternalPtr<m_base_type>::get_ptr(base)->is_read_only()) { \
+ *valid = false; \
+ *oob = true; \
+ return; \
+ } \
(*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \
*oob = false; \
*valid = true; \
} \
static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \
+ if (VariantGetInternalPtr<m_base_type>::get_ptr(base)->is_read_only()) { \
+ *oob = true; \
+ return; \
+ } \
(*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \
*oob = false; \
} \
@@ -946,6 +964,10 @@ struct VariantKeyedSetGetDictionary {
PtrToArg<Variant>::encode(*ptr, value);
}
static void set(Variant *base, const Variant *key, const Variant *value, bool *r_valid) {
+ if (VariantGetInternalPtr<Dictionary>::get_ptr(base)->is_read_only()) {
+ *r_valid = false;
+ return;
+ }
(*VariantGetInternalPtr<Dictionary>::get_ptr(base))[*key] = *value;
*r_valid = true;
}