diff options
author | Emmanuel Leblond <emmanuel.leblond@gmail.com> | 2021-11-02 00:00:38 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-02 00:00:38 +0100 |
commit | 795cd2eb38626970e7487fcc0686b33c19fd6ab5 (patch) | |
tree | 84166ca907363cd1d8b8ec503cfe98e431909df4 /core/variant/variant.cpp | |
parent | 7b83039885d2d3051726f93760d3f8f2a617b8f2 (diff) | |
parent | ce47ce8efba7d17c96ff7cc308c1cdbaa3965143 (diff) |
Merge pull request #35816 from touilleMan/dictionary-operator==-true-comparison
Modify Array/Dictionary::operator== to do real key/value comparison
Diffstat (limited to 'core/variant/variant.cpp')
-rw-r--r-- | core/variant/variant.cpp | 84 |
1 files changed, 41 insertions, 43 deletions
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 1d70d4c506..c43ff8626e 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -784,16 +784,11 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } bool Variant::operator==(const Variant &p_variant) const { - if (type != p_variant.type) { //evaluation of operator== needs to be more strict - return false; - } - bool v; - Variant r; - evaluate(OP_EQUAL, *this, p_variant, r, v); - return r; + return hash_compare(p_variant); } bool Variant::operator!=(const Variant &p_variant) const { + // Don't use `!hash_compare(p_variant)` given it makes use of OP_EQUAL if (type != p_variant.type) { //evaluation of operator== needs to be more strict return true; } @@ -1617,25 +1612,23 @@ struct _VariantStrPair { }; Variant::operator String() const { - List<const void *> stack; - - return stringify(stack); + return stringify(0); } template <class T> -String stringify_vector(const T &vec, List<const void *> &stack) { +String stringify_vector(const T &vec, int recursion_count) { String str("["); for (int i = 0; i < vec.size(); i++) { if (i > 0) { str += ", "; } - str = str + Variant(vec[i]).stringify(stack); + str = str + Variant(vec[i]).stringify(recursion_count); } str += "]"; return str; } -String Variant::stringify(List<const void *> &stack) const { +String Variant::stringify(int recursion_count) const { switch (type) { case NIL: return "null"; @@ -1679,23 +1672,22 @@ String Variant::stringify(List<const void *> &stack) const { return operator Color(); case DICTIONARY: { const Dictionary &d = *reinterpret_cast<const Dictionary *>(_data._mem); - if (stack.find(d.id())) { + if (recursion_count > MAX_RECURSION) { + ERR_PRINT("Max recursion reached"); return "{...}"; } - stack.push_back(d.id()); - - //const String *K=nullptr; String str("{"); List<Variant> keys; d.get_key_list(&keys); Vector<_VariantStrPair> pairs; - for (const Variant &E : keys) { + recursion_count++; + for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { _VariantStrPair sp; - sp.key = E.stringify(stack); - sp.value = d[E].stringify(stack); + sp.key = E->get().stringify(recursion_count); + sp.value = d[E->get()].stringify(recursion_count); pairs.push_back(sp); } @@ -1710,46 +1702,43 @@ String Variant::stringify(List<const void *> &stack) const { } str += "}"; - stack.erase(d.id()); return str; } break; case PACKED_VECTOR2_ARRAY: { - return stringify_vector(operator Vector<Vector2>(), stack); + return stringify_vector(operator Vector<Vector2>(), recursion_count); } break; case PACKED_VECTOR3_ARRAY: { - return stringify_vector(operator Vector<Vector3>(), stack); + return stringify_vector(operator Vector<Vector3>(), recursion_count); } break; case PACKED_COLOR_ARRAY: { - return stringify_vector(operator Vector<Color>(), stack); + return stringify_vector(operator Vector<Color>(), recursion_count); } break; case PACKED_STRING_ARRAY: { - return stringify_vector(operator Vector<String>(), stack); + return stringify_vector(operator Vector<String>(), recursion_count); } break; case PACKED_BYTE_ARRAY: { - return stringify_vector(operator Vector<uint8_t>(), stack); + return stringify_vector(operator Vector<uint8_t>(), recursion_count); } break; case PACKED_INT32_ARRAY: { - return stringify_vector(operator Vector<int32_t>(), stack); + return stringify_vector(operator Vector<int32_t>(), recursion_count); } break; case PACKED_INT64_ARRAY: { - return stringify_vector(operator Vector<int64_t>(), stack); + return stringify_vector(operator Vector<int64_t>(), recursion_count); } break; case PACKED_FLOAT32_ARRAY: { - return stringify_vector(operator Vector<float>(), stack); + return stringify_vector(operator Vector<float>(), recursion_count); } break; case PACKED_FLOAT64_ARRAY: { - return stringify_vector(operator Vector<double>(), stack); + return stringify_vector(operator Vector<double>(), recursion_count); } break; case ARRAY: { Array arr = operator Array(); - if (stack.find(arr.id())) { + if (recursion_count > MAX_RECURSION) { + ERR_PRINT("Max recursion reached"); return "[...]"; } - stack.push_back(arr.id()); - String str = stringify_vector(arr, stack); - - stack.erase(arr.id()); + String str = stringify_vector(arr, recursion_count); return str; } break; @@ -2768,6 +2757,10 @@ Variant::Variant(const Variant &p_variant) { } uint32_t Variant::hash() const { + return recursive_hash(0); +} + +uint32_t Variant::recursive_hash(int recursion_count) const { switch (type) { case NIL: { return 0; @@ -2895,7 +2888,7 @@ uint32_t Variant::hash() const { return reinterpret_cast<const NodePath *>(_data._mem)->hash(); } break; case DICTIONARY: { - return reinterpret_cast<const Dictionary *>(_data._mem)->hash(); + return reinterpret_cast<const Dictionary *>(_data._mem)->recursive_hash(recursion_count); } break; case CALLABLE: { @@ -2909,7 +2902,7 @@ uint32_t Variant::hash() const { } break; case ARRAY: { const Array &arr = *reinterpret_cast<const Array *>(_data._mem); - return arr.hash(); + return arr.recursive_hash(recursion_count); } break; case PACKED_BYTE_ARRAY: { @@ -3083,7 +3076,7 @@ uint32_t Variant::hash() const { \ return true -bool Variant::hash_compare(const Variant &p_variant) const { +bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const { if (type != p_variant.type) { return false; } @@ -3214,14 +3207,19 @@ bool Variant::hash_compare(const Variant &p_variant) const { const Array &l = *(reinterpret_cast<const Array *>(_data._mem)); const Array &r = *(reinterpret_cast<const Array *>(p_variant._data._mem)); - if (l.size() != r.size()) { + if (!l.recursive_equal(r, recursion_count + 1)) { return false; } - for (int i = 0; i < l.size(); ++i) { - if (!l[i].hash_compare(r[i])) { - return false; - } + return true; + } break; + + case DICTIONARY: { + const Dictionary &l = *(reinterpret_cast<const Dictionary *>(_data._mem)); + const Dictionary &r = *(reinterpret_cast<const Dictionary *>(p_variant._data._mem)); + + if (!l.recursive_equal(r, recursion_count + 1)) { + return false; } return true; |