From 3046eac6e5397a053ad34ca468e0d887e2148210 Mon Sep 17 00:00:00 2001 From: nlupugla Date: Sun, 20 Oct 2024 21:45:27 -0400 Subject: [PATCH] Improved struct type checking. --- core/core_bind.cpp | 13 +---- core/core_bind.h | 1 + core/variant/array.cpp | 52 ++++++++--------- core/variant/array.h | 8 +-- core/variant/container_type_validate.h | 81 ++++++++++++++++---------- core/variant/dictionary.cpp | 4 ++ core/variant/dictionary.h | 1 + core/variant/struct.h | 4 +- core/variant/struct_generator.cpp | 48 +++++++-------- core/variant/struct_generator.h | 77 ++++++++++++------------ core/variant/typed_array.h | 4 +- core/variant/variant_setget.cpp | 2 +- tests/core/variant/test_struct.h | 6 +- 13 files changed, 157 insertions(+), 144 deletions(-) diff --git a/core/core_bind.cpp b/core/core_bind.cpp index a49d8aa44751..1ecd23fd0624 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -1646,16 +1646,7 @@ TypedArray ClassDB::class_get_struct_list(const StringName &p_class, TypedArray ret; ::ClassDB::get_struct_list(p_class, &structs, p_no_inheritance); for (const StructInfo &struct_info : structs) { - Dictionary struct_dict; - for (int i = 0; i < struct_info.count; i++) { - Dictionary member_dict; - member_dict[SNAME("name")] = struct_info.names[i]; - member_dict[SNAME("type")] = struct_info.types[i]; - member_dict[SNAME("class_name")] = struct_info.class_names[i]; - member_dict[SNAME("default_value")] = struct_info.default_values[i]; - struct_dict[struct_info.name] = member_dict; - } - ret.push_back(struct_dict); + ret.push_back(StructInfo::Layout::to_dict(struct_info)); } return ret; } @@ -1671,7 +1662,7 @@ TypedArray ClassDB::class_get_struct_members(const StringName &p_cla Dictionary dict; dict[SNAME("name")] = struct_info->names[i]; dict[SNAME("type")] = struct_info->types[i]; - dict[SNAME("class_name")] = struct_info->class_names[i]; + dict[SNAME("type_name")] = struct_info->type_names[i]; dict[SNAME("default_value")] = struct_info->default_values[i]; ret.push_back(dict); } diff --git a/core/core_bind.h b/core/core_bind.h index a21f04e3a23d..cf96d0a36793 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -504,6 +504,7 @@ class ClassDB : public Object { bool class_has_struct(const StringName &p_class, const StringName &p_struct, bool p_no_inheritance = false) const; TypedArray class_get_struct_list(const StringName &p_class, bool p_no_inheritance = false) const; + // TODO: class_get_struct_members seems kind of pointless. It should maybe just be class_get_struct or something. TypedArray class_get_struct_members(const StringName &p_class, const StringName &p_struct) const; #ifdef TOOLS_ENABLED diff --git a/core/variant/array.cpp b/core/variant/array.cpp index 5a6a27b2d105..e86d3ac332e9 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -51,22 +51,18 @@ class ArrayPrivate { ContainerTypeValidate typed; _FORCE_INLINE_ bool is_struct() const { - return !typed.is_array_of_structs && typed.struct_info != nullptr; + return typed.get_is_struct(); } _FORCE_INLINE_ bool is_array_of_structs() const { - return typed.is_array_of_structs; - } - - _FORCE_INLINE_ bool is_struct_array() const { - return false; // TODO: not supported yet + return typed.is_array_of_structs(); } _FORCE_INLINE_ int32_t find_member_index(const StringName &p_member) const { // TODO: is there a better way to do this than linear search? - ERR_FAIL_NULL_V_MSG(typed.struct_info, -1, "Can only find member on a Struct"); - for (int32_t i = 0; i < typed.struct_info->count; i++) { - if (p_member == typed.struct_info->names[i]) { + ERR_FAIL_COND_V_MSG(!typed.get_is_struct(), -1, "Can only find member on a Struct"); + for (int32_t i = 0; i < typed.get_struct_info()->count; i++) { + if (p_member == typed.get_struct_info()->names[i]) { return i; } } @@ -75,9 +71,9 @@ class ArrayPrivate { _FORCE_INLINE_ int32_t rfind_member_index(const StringName &p_member) const { // TODO: is there a better way to do this than linear search? - ERR_FAIL_NULL_V_MSG(typed.struct_info, -1, "Can only find member on a Struct"); - for (int32_t i = typed.struct_info->count - 1; i >= 0; i--) { - if (p_member == typed.struct_info->names[i]) { + ERR_FAIL_COND_V_MSG(!typed.get_is_struct(), -1, "Can only find member on a Struct"); + for (int32_t i = typed.get_struct_info()->count - 1; i >= 0; i--) { + if (p_member == typed.get_struct_info()->names[i]) { return i; } } @@ -250,6 +246,10 @@ void Array::operator=(const Array &p_array) { _ref(p_array); } +bool Array::can_reference(const Array &p_array) const { + return _p->typed.can_reference(p_array._p->typed); +} + void Array::assign(const Array &p_array) { const ContainerTypeValidate &typed = _p->typed; const ContainerTypeValidate &source_typed = p_array._p->typed; @@ -363,7 +363,7 @@ Error Array::resize(int p_new_size) { if (err || variant_type == Variant::NIL || variant_type == Variant::OBJECT) { return err; } - if (const StructInfo *info = _p->typed.struct_info) { // Typed array of structs + if (const StructInfo *info = _p->typed.get_struct_info()) { // Typed array of structs for (int i = old_size; i < p_new_size; i++) { _p->array.write[i] = Array(*info); } @@ -603,7 +603,7 @@ const Variant &Array::get_named(const StringName &p_member) const { const StringName Array::get_member_name(int p_idx) const { // TODO: probably need some error handling here. - return _p->typed.struct_info->names[p_idx]; + return _p->typed.get_struct_info()->names[p_idx]; } int Array::find_member(const StringName &p_member) const { @@ -629,7 +629,7 @@ Array Array::duplicate(bool p_deep) const { Array Array::recursive_duplicate(bool p_deep, int recursion_count) const { Array new_arr; if (const StructInfo *struct_info = get_struct_info()) { - new_arr.set_struct(*struct_info, is_array_of_structs()); + new_arr.set_struct(*struct_info, is_struct()); } else { new_arr._p->typed = _p->typed; if (p_deep) { @@ -1002,13 +1002,13 @@ void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Var _p->typed = ContainerTypeValidate(Variant::Type(p_type), p_class_name, script, "TypedArray"); } -void Array::set_struct(const StructInfo &p_struct_info, bool p_is_array_of_structs) { +void Array::set_struct(const StructInfo &p_struct_info, bool p_is_struct) { if (validate_set_type() != OK) { return; } const int32_t size = p_struct_info.count; _p->array.resize(size); - _p->typed = ContainerTypeValidate(p_struct_info, p_is_array_of_structs); + _p->typed = ContainerTypeValidate(p_struct_info, p_is_struct); } void Array::initialize_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script) { @@ -1019,11 +1019,11 @@ void Array::initialize_typed(uint32_t p_type, const StringName &p_class_name, co _p->typed = ContainerTypeValidate(Variant::Type(p_type), p_class_name, script, "TypedArray"); } -void Array::initialize_struct_type(const StructInfo &p_struct_info, bool is_array_of_structs) { - if (!is_array_of_structs) { +void Array::initialize_struct_type(const StructInfo &p_struct_info, bool p_is_struct) { + if (p_is_struct) { _p->array.resize(p_struct_info.count); } - _p->typed = ContainerTypeValidate(p_struct_info, is_array_of_structs); + _p->typed = ContainerTypeValidate(p_struct_info, p_is_struct); } bool Array::is_typed() const { @@ -1059,7 +1059,7 @@ Variant Array::get_typed_script() const { } const StructInfo *Array::get_struct_info() const { - return _p->typed.struct_info; + return _p->typed.get_struct_info(); } Array Array::create_read_only() { @@ -1087,7 +1087,7 @@ Array::Array(const Array &p_from, const StructInfo &p_struct_info) { _p = memnew(ArrayPrivate); _p->refcount.init(); // TODO: should this be _ref(p_from)? - initialize_struct_type(p_struct_info, p_from.is_array_of_structs()); + initialize_struct_type(p_struct_info, true); assign(p_from); } @@ -1095,19 +1095,19 @@ Array::Array(const Dictionary &p_from, const StructInfo &p_struct_info) { _p = memnew(ArrayPrivate); _p->refcount.init(); // TODO: should this be _ref(p_from)? - initialize_struct_type(p_struct_info, false); + initialize_struct_type(p_struct_info, true); Variant *pw = _p->array.ptrw(); for (int32_t i = 0; i < p_struct_info.count; i++) { pw[i] = p_from.has(p_struct_info.names[i]) ? p_from[p_struct_info.names[i]] : p_struct_info.default_values[i]; } } -Array::Array(const StructInfo &p_struct_info, bool is_array_of_structs) { +Array::Array(const StructInfo &p_struct_info, bool p_is_struct) { _p = memnew(ArrayPrivate); _p->refcount.init(); - initialize_struct_type(p_struct_info, is_array_of_structs); - if (!is_array_of_structs) { + initialize_struct_type(p_struct_info, p_is_struct); + if (p_is_struct) { Variant *pw = _p->array.ptrw(); for (int32_t i = 0; i < p_struct_info.count; i++) { pw[i] = p_struct_info.default_values[i].duplicate(true); diff --git a/core/variant/array.h b/core/variant/array.h index 40f05abe2546..7cd883bbe1c6 100644 --- a/core/variant/array.h +++ b/core/variant/array.h @@ -42,7 +42,6 @@ class StringName; class Callable; template class Vector; -struct StructMember; struct ContainerTypeValidate; struct StructInfo; class Dictionary; @@ -144,6 +143,7 @@ class Array { uint32_t recursive_hash(int recursion_count) const; void operator=(const Array &p_array); + bool can_reference(const Array &p_array) const; void assign(const Array &p_array); void push_back(const Variant &p_value); _FORCE_INLINE_ void append(const Variant &p_value) { push_back(p_value); } //for python compatibility @@ -201,11 +201,11 @@ class Array { Error validate_set_type(); void set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script); - void set_struct(const StructInfo &p_struct_info, bool p_is_array_of_structs = false); + void set_struct(const StructInfo &p_struct_info, bool p_is_struct = true); protected: void initialize_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script); - void initialize_struct_type(const StructInfo &p_struct_info, bool p_is_array_of_structs = false); + void initialize_struct_type(const StructInfo &p_struct_info, bool p_is_struct = true); public: bool is_typed() const; @@ -226,7 +226,7 @@ class Array { Array(const Array &p_from); Array(const Array &p_from, const StructInfo &p_struct_info); Array(const Dictionary &p_from, const StructInfo &p_struct_info); - Array(const StructInfo &p_struct_info, bool p_is_array_of_structs = false); + Array(const StructInfo &p_struct_info, bool p_is_struct = true); Array(); ~Array(); }; diff --git a/core/variant/container_type_validate.h b/core/variant/container_type_validate.h index 30417da435f0..c52a0476a09d 100644 --- a/core/variant/container_type_validate.h +++ b/core/variant/container_type_validate.h @@ -39,9 +39,8 @@ struct ValidatedVariant { Variant value; bool valid; - ValidatedVariant(const Variant &p_value, const bool p_valid) { - value = p_value; - valid = p_valid; + ValidatedVariant(const Variant &p_value, const bool p_valid) : + value(p_value), valid(p_valid) { } }; @@ -50,25 +49,37 @@ struct ContainerTypeValidate { StringName class_name; Ref