From 7423ce4625d197cdf610697eea595eaca0183106 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 12 Mar 2026 00:05:41 -0400 Subject: [PATCH 01/13] Reduce cases, branches, etc, with regard to Variant --- core/variant/variant.cpp | 1476 +++++++++++--------------------------- core/variant/variant.h | 112 +-- 2 files changed, 444 insertions(+), 1144 deletions(-) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 5504104074e..b51115f7ddd 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -32,147 +32,178 @@ #include "variant.h" +#include "callable.h" #include "core/debugger/engine_debugger.h" #include "core/io/json.h" #include "core/io/resource.h" #include "core/math/math_funcs.h" #include "core/variant/variant_parser.h" +#include +#include PagedAllocator Variant::Pools::_bucket_small; PagedAllocator Variant::Pools::_bucket_medium; PagedAllocator Variant::Pools::_bucket_large; -String Variant::get_type_name(Variant::Type p_type) { - switch (p_type) { - case NIL: { - return "Nil"; - } - - // Atomic types. - case BOOL: { - return "bool"; - } - case INT: { - return "int"; - } - case FLOAT: { - return "float"; - } - case STRING: { - return "String"; - } +static const std::array TYPE_STRING_TABLE = { + "Nil", + "bool", + "int", + "float", + "String", + "Vector2", + "Vector2i", + "Rect2", + "Rect2i", + "Vector3", + "Vector3i", + "Transform2D", + "Vector4", + "Vector4i", + "Plane", + "Quaternion", + "AABB", + "Basis", + "Transform3D", + "Projection", + "Color", + "StringName", + "NodePath", + "RID", + "Object", + "Callable", + "Signal", + "Dictionary", + "Array", + "PackedByteArray", + "PackedInt32Array", + "PackedInt64Array", + "PackedFloat32Array", + "PackedFloat64Array", + "PackedStringArray", + "PackedVector2Array", + "PackedVector3Array", + "PackedColorArray", + "PackedVector4Array", +}; - // Math types. - case VECTOR2: { - return "Vector2"; - } - case VECTOR2I: { - return "Vector2i"; - } - case RECT2: { - return "Rect2"; - } - case RECT2I: { - return "Rect2i"; - } - case TRANSFORM2D: { - return "Transform2D"; - } - case VECTOR3: { - return "Vector3"; - } - case VECTOR3I: { - return "Vector3i"; - } - case VECTOR4: { - return "Vector4"; - } - case VECTOR4I: { - return "Vector4i"; - } - case PLANE: { - return "Plane"; - } - case AABB: { - return "AABB"; - } - case QUATERNION: { - return "Quaternion"; - } - case BASIS: { - return "Basis"; - } - case TRANSFORM3D: { - return "Transform3D"; - } - case PROJECTION: { - return "Projection"; - } +static const std::array TYPE_CAST_TABLE = { + ~0ull, // nil + (1 << Variant::BOOL) | (1 << Variant::INT) | (1 << Variant::FLOAT) | (1 << Variant::STRING), // bool + (1 << Variant::BOOL) | (1 << Variant::INT) | (1 << Variant::FLOAT) | (1 << Variant::STRING), // int + (1 << Variant::BOOL) | (1 << Variant::INT) | (1 << Variant::FLOAT) | (1 << Variant::STRING), // float + ~((1ull << Variant::OBJECT)), // string + (1 << Variant::VECTOR2) | (1 << Variant::VECTOR2I), // vec2 + (1 << Variant::VECTOR2) | (1 << Variant::VECTOR2I), // ivec2 + (1 << Variant::RECT2) | (1 << Variant::RECT2I), // rect2 + (1 << Variant::RECT2) | (1 << Variant::RECT2I), // irect2 + (1 << Variant::VECTOR3) | (1 << Variant::VECTOR3I), // vec3 + (1 << Variant::VECTOR3) | (1 << Variant::VECTOR3I), // ivec3 + (1 << Variant::TRANSFORM2D) | (1 << Variant::TRANSFORM3D), // transform2d + (1 << Variant::VECTOR4) | (1 << Variant::VECTOR4I), // vec4 + (1 << Variant::VECTOR4) | (1 << Variant::VECTOR4I), // ivec4 + (1 << Variant::PLANE), // plane + (1 << Variant::QUATERNION) | (1 << Variant::BASIS), // quaternion + (1 << Variant::AABB), // aabb + (1 << Variant::QUATERNION) | (1 << Variant::BASIS), // basis + (1 << Variant::TRANSFORM2D) | + (1 << Variant::QUATERNION) | + (1 << Variant::BASIS) | + (1 << Variant::TRANSFORM3D) | + (1 << Variant::PROJECTION), // transform3d + (1 << Variant::TRANSFORM3D) | (1 << Variant::PROJECTION), // projection + (1 << Variant::STRING) | (1 << Variant::INT) | (1 << Variant::COLOR), // color + (1 << Variant::STRING) | (1 << Variant::STRING_NAME), // stringname + (1 << Variant::STRING) | (1 << Variant::NODE_PATH), // nodepath + (1 << Variant::OBJECT) | (1 << Variant::RID), // rid + (1 << Variant::NIL) | (1 << Variant::OBJECT), // object + (1 << Variant::CALLABLE), // callbale + (1 << Variant::SIGNAL), // signal + (1 << Variant::DICTIONARY), // dictionary + (1ull << Variant::ARRAY) | + (1ull << Variant::PACKED_BYTE_ARRAY) | + (1ull << Variant::PACKED_INT32_ARRAY) | + (1ull << Variant::PACKED_INT64_ARRAY) | + (1ull << Variant::PACKED_FLOAT32_ARRAY) | + (1ull << Variant::PACKED_FLOAT64_ARRAY) | + (1ull << Variant::PACKED_STRING_ARRAY) | + (1ull << Variant::PACKED_COLOR_ARRAY) | + (1ull << Variant::PACKED_VECTOR2_ARRAY) | + (1ull << Variant::PACKED_VECTOR3_ARRAY) | + (1ull << Variant::PACKED_VECTOR4_ARRAY), // array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_BYTE_ARRAY), // packedbytearray + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_INT32_ARRAY), // packedint32array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_INT64_ARRAY), // packedint64array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_FLOAT32_ARRAY), // packedfloat32array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_FLOAT64_ARRAY), // packedfloat64array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_STRING_ARRAY), // packedstringarray + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_VECTOR2_ARRAY), // packedvec2array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_VECTOR3_ARRAY), // packedvec3array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_COLOR_ARRAY), // packedcolorarray + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_VECTOR4_ARRAY), // packedvec4array +}; - // Miscellaneous types. - case COLOR: { - return "Color"; - } - case RID: { - return "RID"; - } - case OBJECT: { - return "Object"; - } - case CALLABLE: { - return "Callable"; - } - case SIGNAL: { - return "Signal"; - } - case STRING_NAME: { - return "StringName"; - } - case NODE_PATH: { - return "NodePath"; - } - case DICTIONARY: { - return "Dictionary"; - } - case ARRAY: { - return "Array"; - } +static const std::array TYPE_STRICT_CAST_TABLE = { + ~0ull, // nil + (1 << Variant::BOOL) | (1 << Variant::INT) | (1 << Variant::FLOAT), // bool + (1 << Variant::BOOL) | (1 << Variant::INT) | (1 << Variant::FLOAT), // int + (1 << Variant::BOOL) | (1 << Variant::INT) | (1 << Variant::FLOAT), // float + (1 << Variant::NODE_PATH) | (1 << Variant::STRING) | (1 << Variant::STRING_NAME), // string + (1 << Variant::VECTOR2) | (1 << Variant::VECTOR2I), // vec2 + (1 << Variant::VECTOR2) | (1 << Variant::VECTOR2I), // ivec2 + (1 << Variant::RECT2) | (1 << Variant::RECT2I), // rect2 + (1 << Variant::RECT2) | (1 << Variant::RECT2I), // irect2 + (1 << Variant::VECTOR3) | (1 << Variant::VECTOR3I), // vec3 + (1 << Variant::VECTOR3) | (1 << Variant::VECTOR3I), // ivec3 + (1 << Variant::TRANSFORM2D) | (1 << Variant::TRANSFORM3D), // transform2d + (1 << Variant::VECTOR4) | (1 << Variant::VECTOR4I), // vec4 + (1 << Variant::VECTOR4) | (1 << Variant::VECTOR4I), // ivec4 + (1 << Variant::PLANE), // plane + (1 << Variant::QUATERNION) | (1 << Variant::BASIS), // quaternion + (1 << Variant::AABB), // aabb + (1 << Variant::QUATERNION) | (1 << Variant::BASIS), // basis + (1 << Variant::TRANSFORM2D) | + (1 << Variant::QUATERNION) | + (1 << Variant::BASIS) | + (1 << Variant::TRANSFORM3D) | + (1 << Variant::PROJECTION), // transform3d + (1 << Variant::TRANSFORM3D) | (1 << Variant::PROJECTION), // projection + (1 << Variant::STRING) | (1 << Variant::INT) | (1 << Variant::COLOR), // color + (1 << Variant::STRING) | (1 << Variant::STRING_NAME), // stringname + (1 << Variant::STRING) | (1 << Variant::NODE_PATH), // nodepath + (1 << Variant::OBJECT) | (1 << Variant::RID), // rid + (1 << Variant::NIL) | (1 << Variant::OBJECT), // object + (1 << Variant::CALLABLE), // callbale + (1 << Variant::SIGNAL), // signal + (1 << Variant::DICTIONARY), // dictionary + (1ull << Variant::ARRAY) | + (1ull << Variant::PACKED_BYTE_ARRAY) | + (1ull << Variant::PACKED_INT32_ARRAY) | + (1ull << Variant::PACKED_INT64_ARRAY) | + (1ull << Variant::PACKED_FLOAT32_ARRAY) | + (1ull << Variant::PACKED_FLOAT64_ARRAY) | + (1ull << Variant::PACKED_STRING_ARRAY) | + (1ull << Variant::PACKED_COLOR_ARRAY) | + (1ull << Variant::PACKED_VECTOR2_ARRAY) | + (1ull << Variant::PACKED_VECTOR3_ARRAY) | + (1ull << Variant::PACKED_VECTOR4_ARRAY), // array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_BYTE_ARRAY), // packedbytearray + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_INT32_ARRAY), // packedint32array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_INT64_ARRAY), // packedint64array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_FLOAT32_ARRAY), // packedfloat32array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_FLOAT64_ARRAY), // packedfloat64array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_STRING_ARRAY), // packedstringarray + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_VECTOR2_ARRAY), // packedvec2array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_VECTOR3_ARRAY), // packedvec3array + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_COLOR_ARRAY), // packedcolorarray + (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_VECTOR4_ARRAY), // packedvec4array +}; - // Arrays. - case PACKED_BYTE_ARRAY: { - return "PackedByteArray"; - } - case PACKED_INT32_ARRAY: { - return "PackedInt32Array"; - } - case PACKED_INT64_ARRAY: { - return "PackedInt64Array"; - } - case PACKED_FLOAT32_ARRAY: { - return "PackedFloat32Array"; - } - case PACKED_FLOAT64_ARRAY: { - return "PackedFloat64Array"; - } - case PACKED_STRING_ARRAY: { - return "PackedStringArray"; - } - case PACKED_VECTOR2_ARRAY: { - return "PackedVector2Array"; - } - case PACKED_VECTOR3_ARRAY: { - return "PackedVector3Array"; - } - case PACKED_COLOR_ARRAY: { - return "PackedColorArray"; - } - case PACKED_VECTOR4_ARRAY: { - return "PackedVector4Array"; - } - default: { - } +String Variant::get_type_name(Variant::Type p_type) { + if (p_type < VARIANT_MAX) + { + return TYPE_STRING_TABLE[p_type]; } - return ""; } @@ -189,678 +220,21 @@ Variant::Type Variant::get_type_by_name(const String &p_type_name) { } bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { - if (p_type_from == p_type_to) { - return true; - } - if (p_type_to == NIL) { //nil can convert to anything - return true; + std::uint64_t valid_types = 0; + if (p_type_to < VARIANT_MAX) + { + valid_types = TYPE_CAST_TABLE[p_type_to]; } - - if (p_type_from == NIL) { - return (p_type_to == OBJECT); - } - - const Type *valid_types = nullptr; - const Type *invalid_types = nullptr; - - switch (p_type_to) { - case BOOL: { - static const Type valid[] = { - INT, - FLOAT, - STRING, - NIL, - }; - - valid_types = valid; - } break; - case INT: { - static const Type valid[] = { - BOOL, - FLOAT, - STRING, - NIL, - }; - - valid_types = valid; - - } break; - case FLOAT: { - static const Type valid[] = { - BOOL, - INT, - STRING, - NIL, - }; - - valid_types = valid; - - } break; - case STRING: { - static const Type invalid[] = { - OBJECT, - NIL - }; - - invalid_types = invalid; - } break; - case VECTOR2: { - static const Type valid[] = { - VECTOR2I, - NIL, - }; - - valid_types = valid; - - } break; - case VECTOR2I: { - static const Type valid[] = { - VECTOR2, - NIL, - }; - - valid_types = valid; - - } break; - case RECT2: { - static const Type valid[] = { - RECT2I, - NIL, - }; - - valid_types = valid; - - } break; - case RECT2I: { - static const Type valid[] = { - RECT2, - NIL, - }; - - valid_types = valid; - - } break; - case TRANSFORM2D: { - static const Type valid[] = { - TRANSFORM3D, - NIL - }; - - valid_types = valid; - } break; - case VECTOR3: { - static const Type valid[] = { - VECTOR3I, - NIL, - }; - - valid_types = valid; - - } break; - case VECTOR3I: { - static const Type valid[] = { - VECTOR3, - NIL, - }; - - valid_types = valid; - - } break; - case VECTOR4: { - static const Type valid[] = { - VECTOR4I, - NIL, - }; - - valid_types = valid; - - } break; - case VECTOR4I: { - static const Type valid[] = { - VECTOR4, - NIL, - }; - - valid_types = valid; - - } break; - - case QUATERNION: { - static const Type valid[] = { - BASIS, - NIL - }; - - valid_types = valid; - - } break; - case BASIS: { - static const Type valid[] = { - QUATERNION, - NIL - }; - - valid_types = valid; - - } break; - case TRANSFORM3D: { - static const Type valid[] = { - TRANSFORM2D, - QUATERNION, - BASIS, - PROJECTION, - NIL - }; - - valid_types = valid; - - } break; - case PROJECTION: { - static const Type valid[] = { - TRANSFORM3D, - NIL - }; - - valid_types = valid; - - } break; - - case COLOR: { - static const Type valid[] = { - STRING, - INT, - NIL, - }; - - valid_types = valid; - - } break; - - case RID: { - static const Type valid[] = { - OBJECT, - NIL - }; - - valid_types = valid; - } break; - case OBJECT: { - static const Type valid[] = { - NIL - }; - - valid_types = valid; - } break; - case STRING_NAME: { - static const Type valid[] = { - STRING, - NIL - }; - - valid_types = valid; - } break; - case NODE_PATH: { - static const Type valid[] = { - STRING, - NIL - }; - - valid_types = valid; - } break; - case ARRAY: { - static const Type valid[] = { - PACKED_BYTE_ARRAY, - PACKED_INT32_ARRAY, - PACKED_INT64_ARRAY, - PACKED_FLOAT32_ARRAY, - PACKED_FLOAT64_ARRAY, - PACKED_STRING_ARRAY, - PACKED_COLOR_ARRAY, - PACKED_VECTOR2_ARRAY, - PACKED_VECTOR3_ARRAY, - PACKED_VECTOR4_ARRAY, - NIL - }; - - valid_types = valid; - } break; - // arrays - case PACKED_BYTE_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - - valid_types = valid; - } break; - case PACKED_INT32_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - valid_types = valid; - } break; - case PACKED_INT64_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - valid_types = valid; - } break; - case PACKED_FLOAT32_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - - valid_types = valid; - } break; - case PACKED_FLOAT64_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - - valid_types = valid; - } break; - case PACKED_STRING_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - valid_types = valid; - } break; - case PACKED_VECTOR2_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - valid_types = valid; - - } break; - case PACKED_VECTOR3_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - valid_types = valid; - - } break; - case PACKED_COLOR_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - - valid_types = valid; - - } break; - case PACKED_VECTOR4_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - valid_types = valid; - - } break; - default: { - } - } - - if (valid_types) { - int i = 0; - while (valid_types[i] != NIL) { - if (p_type_from == valid_types[i]) { - return true; - } - i++; - } - - } else if (invalid_types) { - int i = 0; - while (invalid_types[i] != NIL) { - if (p_type_from == invalid_types[i]) { - return false; - } - i++; - } - - return true; - } - - return false; + return (valid_types & (1ull << p_type_from)) != 0; } bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type_to) { - if (p_type_from == p_type_to) { - return true; - } - if (p_type_to == NIL) { //nil can convert to anything - return true; - } - - if (p_type_from == NIL) { - return (p_type_to == OBJECT); - } - - const Type *valid_types = nullptr; - - switch (p_type_to) { - case BOOL: { - static const Type valid[] = { - INT, - FLOAT, - //STRING, - NIL, - }; - - valid_types = valid; - } break; - case INT: { - static const Type valid[] = { - BOOL, - FLOAT, - //STRING, - NIL, - }; - - valid_types = valid; - - } break; - case FLOAT: { - static const Type valid[] = { - BOOL, - INT, - //STRING, - NIL, - }; - - valid_types = valid; - - } break; - case STRING: { - static const Type valid[] = { - NODE_PATH, - STRING_NAME, - NIL - }; - - valid_types = valid; - } break; - case VECTOR2: { - static const Type valid[] = { - VECTOR2I, - NIL, - }; - - valid_types = valid; - - } break; - case VECTOR2I: { - static const Type valid[] = { - VECTOR2, - NIL, - }; - - valid_types = valid; - - } break; - case RECT2: { - static const Type valid[] = { - RECT2I, - NIL, - }; - - valid_types = valid; - - } break; - case RECT2I: { - static const Type valid[] = { - RECT2, - NIL, - }; - - valid_types = valid; - - } break; - case TRANSFORM2D: { - static const Type valid[] = { - TRANSFORM3D, - NIL - }; - - valid_types = valid; - } break; - case VECTOR3: { - static const Type valid[] = { - VECTOR3I, - NIL, - }; - - valid_types = valid; - - } break; - case VECTOR3I: { - static const Type valid[] = { - VECTOR3, - NIL, - }; - - valid_types = valid; - - } break; - case VECTOR4: { - static const Type valid[] = { - VECTOR4I, - NIL, - }; - - valid_types = valid; - - } break; - case VECTOR4I: { - static const Type valid[] = { - VECTOR4, - NIL, - }; - - valid_types = valid; - - } break; - - case QUATERNION: { - static const Type valid[] = { - BASIS, - NIL - }; - - valid_types = valid; - - } break; - case BASIS: { - static const Type valid[] = { - QUATERNION, - NIL - }; - - valid_types = valid; - - } break; - case TRANSFORM3D: { - static const Type valid[] = { - TRANSFORM2D, - QUATERNION, - BASIS, - PROJECTION, - NIL - }; - - valid_types = valid; - - } break; - case PROJECTION: { - static const Type valid[] = { - TRANSFORM3D, - NIL - }; - - valid_types = valid; - - } break; - - case COLOR: { - static const Type valid[] = { - STRING, - INT, - NIL, - }; - - valid_types = valid; - - } break; - - case RID: { - static const Type valid[] = { - OBJECT, - NIL - }; - - valid_types = valid; - } break; - case OBJECT: { - static const Type valid[] = { - NIL - }; - - valid_types = valid; - } break; - case STRING_NAME: { - static const Type valid[] = { - STRING, - NIL - }; - - valid_types = valid; - } break; - case NODE_PATH: { - static const Type valid[] = { - STRING, - NIL - }; - - valid_types = valid; - } break; - case ARRAY: { - static const Type valid[] = { - PACKED_BYTE_ARRAY, - PACKED_INT32_ARRAY, - PACKED_INT64_ARRAY, - PACKED_FLOAT32_ARRAY, - PACKED_FLOAT64_ARRAY, - PACKED_STRING_ARRAY, - PACKED_COLOR_ARRAY, - PACKED_VECTOR2_ARRAY, - PACKED_VECTOR3_ARRAY, - PACKED_VECTOR4_ARRAY, - NIL - }; - - valid_types = valid; - } break; - // arrays - case PACKED_BYTE_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - - valid_types = valid; - } break; - case PACKED_INT32_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - valid_types = valid; - } break; - case PACKED_INT64_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - valid_types = valid; - } break; - case PACKED_FLOAT32_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - - valid_types = valid; - } break; - case PACKED_FLOAT64_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - - valid_types = valid; - } break; - case PACKED_STRING_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - valid_types = valid; - } break; - case PACKED_VECTOR2_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - valid_types = valid; - - } break; - case PACKED_VECTOR3_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - valid_types = valid; - - } break; - case PACKED_COLOR_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - - valid_types = valid; - - } break; - case PACKED_VECTOR4_ARRAY: { - static const Type valid[] = { - ARRAY, - NIL - }; - valid_types = valid; - - } break; - default: { - } + std::uint64_t valid_types = 0; + if (p_type_to < VARIANT_MAX) + { + valid_types = TYPE_STRICT_CAST_TABLE[p_type_to]; } - - if (valid_types) { - int i = 0; - while (valid_types[i] != NIL) { - if (p_type_from == valid_types[i]) { - return true; - } - i++; - } - } - - return false; + return (valid_types & (1ull << p_type_from)) != 0; } bool Variant::operator==(const Variant &p_variant) const { @@ -1077,11 +451,7 @@ bool Variant::is_one() const { } bool Variant::is_null() const { - if (type == OBJECT && _get_obj().obj) { - return false; - } else { - return true; - } + return !(type == OBJECT && _get_obj().obj); } void Variant::ObjData::ref(const ObjData &p_from, bool p_is_weak_ref_old, bool p_is_weak_ref) { @@ -1318,53 +688,23 @@ void Variant::reference(const Variant &p_variant) { void Variant::zero() { switch (type) { - case NIL: - break; + case NIL: break; case BOOL: - _data._bool = false; - break; case INT: - _data._int = 0; - break; case FLOAT: - _data._float = 0; - break; - case VECTOR2: - *reinterpret_cast(_data._mem) = Vector2(); - break; case VECTOR2I: - *reinterpret_cast(_data._mem) = Vector2i(); - break; case RECT2: - *reinterpret_cast(_data._mem) = Rect2(); - break; case RECT2I: - *reinterpret_cast(_data._mem) = Rect2i(); - break; case VECTOR3: - *reinterpret_cast(_data._mem) = Vector3(); - break; case VECTOR3I: - *reinterpret_cast(_data._mem) = Vector3i(); - break; case VECTOR4: - *reinterpret_cast(_data._mem) = Vector4(); - break; case VECTOR4I: - *reinterpret_cast(_data._mem) = Vector4i(); - break; case PLANE: - *reinterpret_cast(_data._mem) = Plane(); - break; case QUATERNION: - *reinterpret_cast(_data._mem) = Quaternion(); - break; - case COLOR: - *reinterpret_cast(_data._mem) = Color(); + _data = {}; break; - default: Type prev_type = type; clear(); @@ -1377,109 +717,151 @@ void Variant::zero() { } } +template +void destroy(T *s) { reinterpret_cast(s)->~T(); } + +template +void bucketFree(PagedAllocator *bucket, void *mem) +{ + ((PagedAllocator *)bucket)->free((T*)mem); +} + +using Destructor = void (*)(void *); +using BucketFree = void (*)(void *, void *); + void Variant::_clear_internal() { + static const std::array DESTRUCTOR_TABLE = { + nullptr, + nullptr, + nullptr, + nullptr, + (Destructor)destroy, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + (Destructor)destroy, + nullptr, + nullptr, + nullptr, + nullptr, + (Destructor)destroy<::AABB>, + (Destructor)destroy, + (Destructor)destroy, + (Destructor)destroy, + nullptr, + (Destructor)destroy, + (Destructor)destroy, + (Destructor)destroy<::RID>, + nullptr, + (Destructor)destroy, + (Destructor)destroy, + (Destructor)destroy, + (Destructor)destroy, + }; + static const std::array BUCKET_FREE_FN_TBL + { + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + (BucketFree)bucketFree, + nullptr, + nullptr, + nullptr, + nullptr, + (BucketFree)bucketFree, + (BucketFree)bucketFree, + (BucketFree)bucketFree, + (BucketFree)bucketFree, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + }; + static const std::array BUCKET_TBL + { + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + (void*)&Pools::_bucket_small, + nullptr, + nullptr, + nullptr, + nullptr, + (void*)&Pools::_bucket_small, + (void*)&Pools::_bucket_medium, + (void*)&Pools::_bucket_medium, + (void*)&Pools::_bucket_large, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + }; switch (type) { - case STRING: { - reinterpret_cast(_data._mem)->~String(); + case STRING: + case STRING_NAME: + case NODE_PATH: + case RID: + case CALLABLE: + case SIGNAL: + case DICTIONARY: + case ARRAY: { + DESTRUCTOR_TABLE[type](_data._mem); } break; // Math types. - case TRANSFORM2D: { - if (_data._transform2d) { - _data._transform2d->~Transform2D(); - Pools::_bucket_small.free((Pools::BucketSmall *)_data._transform2d); - _data._transform2d = nullptr; - } - } break; - case AABB: { - if (_data._aabb) { - _data._aabb->~AABB(); - Pools::_bucket_small.free((Pools::BucketSmall *)_data._aabb); - _data._aabb = nullptr; - } - } break; - case BASIS: { - if (_data._basis) { - _data._basis->~Basis(); - Pools::_bucket_medium.free((Pools::BucketMedium *)_data._basis); - _data._basis = nullptr; - } - } break; - case TRANSFORM3D: { - if (_data._transform3d) { - _data._transform3d->~Transform3D(); - Pools::_bucket_medium.free((Pools::BucketMedium *)_data._transform3d); - _data._transform3d = nullptr; - } - } break; + case AABB: + case TRANSFORM2D: + case TRANSFORM3D: + case BASIS: case PROJECTION: { - if (_data._projection) { - _data._projection->~Projection(); - Pools::_bucket_large.free((Pools::BucketLarge *)_data._projection); - _data._projection = nullptr; + if (_data._ptr) { + DESTRUCTOR_TABLE[type](_data._ptr); + BUCKET_FREE_FN_TBL[type](BUCKET_TBL[type], _data._ptr); + _data._ptr = nullptr; } } break; - // Miscellaneous types. - case STRING_NAME: { - reinterpret_cast(_data._mem)->~StringName(); - } break; - case NODE_PATH: { - reinterpret_cast(_data._mem)->~NodePath(); - } break; - case OBJECT: { - _get_obj().unref(is_weak_ref); - } break; - case RID: { - // Not much need probably. - // HACK: Can't seem to use destructor + scoping operator, so hack. - typedef ::RID RID_Class; - reinterpret_cast(_data._mem)->~RID_Class(); - } break; - case CALLABLE: { - reinterpret_cast(_data._mem)->~Callable(); - } break; - case SIGNAL: { - reinterpret_cast(_data._mem)->~Signal(); - } break; - case DICTIONARY: { - reinterpret_cast(_data._mem)->~Dictionary(); - } break; - case ARRAY: { - reinterpret_cast(_data._mem)->~Array(); - } break; - + case OBJECT: { _get_obj().unref(is_weak_ref); } break; // Arrays. - case PACKED_BYTE_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); - } break; - case PACKED_INT32_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); - } break; - case PACKED_INT64_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); - } break; - case PACKED_FLOAT32_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); - } break; - case PACKED_FLOAT64_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); - } break; - case PACKED_STRING_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); - } break; - case PACKED_VECTOR2_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); - } break; - case PACKED_VECTOR3_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); - } break; - case PACKED_COLOR_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); - } break; - case PACKED_VECTOR4_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); - } break; + case PACKED_BYTE_ARRAY: + case PACKED_INT32_ARRAY: + case PACKED_INT64_ARRAY: + case PACKED_FLOAT32_ARRAY: + case PACKED_FLOAT64_ARRAY: + case PACKED_STRING_ARRAY: + case PACKED_VECTOR2_ARRAY: + case PACKED_VECTOR3_ARRAY: + case PACKED_VECTOR4_ARRAY: + case PACKED_COLOR_ARRAY: { PackedArrayRefBase::destroy(_data.packed_array); } break; default: { // Not needed, there is no point. The following do not allocate memory: // VECTOR2, VECTOR3, VECTOR4, RECT2, PLANE, QUATERNION, COLOR. @@ -1520,12 +902,11 @@ Variant::operator uint8_t() const { } Variant::operator ObjectID() const { - if (type == INT) { - return ObjectID(_data._int); - } else if (type == OBJECT) { - return _get_obj().id; - } else { - return ObjectID(); + switch (type) + { + case Variant::INT: return ObjectID(_data._int); + case Variant::OBJECT: return _get_obj().id; + default: return ObjectID(); } } @@ -1542,13 +923,12 @@ Variant::operator double() const { } Variant::operator StringName() const { - if (type == STRING_NAME) { - return *reinterpret_cast(_data._mem); - } else if (type == STRING) { - return *reinterpret_cast(_data._mem); + switch (type) + { + case Variant::STRING_NAME: return *reinterpret_cast(_data._mem); + case Variant::STRING: return *reinterpret_cast(_data._mem); + default: return StringName(); } - - return StringName(); } struct _VariantStrPair { @@ -1748,131 +1128,102 @@ String Variant::to_json_string() const { } Variant::operator Vector2() const { - if (type == VECTOR2) { - return *reinterpret_cast(_data._mem); - } else if (type == VECTOR2I) { - return *reinterpret_cast(_data._mem); - } else if (type == VECTOR3) { - return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - } else if (type == VECTOR3I) { - return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - } else if (type == VECTOR4) { - return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - } else if (type == VECTOR4I) { - return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - } else { - return Vector2(); + switch (type) + { + case Variant::VECTOR2: return *reinterpret_cast(_data._mem); + case Variant::VECTOR2I: return *reinterpret_cast(_data._mem); + case Variant::VECTOR3: return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + case Variant::VECTOR3I: return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + case Variant::VECTOR4: return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + case Variant::VECTOR4I: return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + default: return Vector2(); } } Variant::operator Vector2i() const { - if (type == VECTOR2I) { - return *reinterpret_cast(_data._mem); - } else if (type == VECTOR2) { - return *reinterpret_cast(_data._mem); - } else if (type == VECTOR3) { - return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - } else if (type == VECTOR3I) { - return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - } else if (type == VECTOR4) { - return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - } else if (type == VECTOR4I) { - return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - } else { - return Vector2i(); + switch (type) + { + case Variant::VECTOR2: return *reinterpret_cast(_data._mem); + case Variant::VECTOR2I: return *reinterpret_cast(_data._mem); + case Variant::VECTOR3: return Vector2i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + case Variant::VECTOR3I: return Vector2i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + case Variant::VECTOR4: return Vector2i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + case Variant::VECTOR4I: return Vector2i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + default: return Vector2i(); } } Variant::operator Rect2() const { - if (type == RECT2) { - return *reinterpret_cast(_data._mem); - } else if (type == RECT2I) { - return *reinterpret_cast(_data._mem); - } else { - return Rect2(); + switch (type) + { + case Variant::RECT2: return *reinterpret_cast(_data._mem); + case Variant::RECT2I: return *reinterpret_cast(_data._mem); + default: return Rect2(); } } Variant::operator Rect2i() const { - if (type == RECT2I) { - return *reinterpret_cast(_data._mem); - } else if (type == RECT2) { - return *reinterpret_cast(_data._mem); - } else { - return Rect2i(); + switch (type) + { + case Variant::RECT2: return *reinterpret_cast(_data._mem); + case Variant::RECT2I: return *reinterpret_cast(_data._mem); + default: return Rect2i(); } } Variant::operator Vector3() const { - if (type == VECTOR3) { - return *reinterpret_cast(_data._mem); - } else if (type == VECTOR3I) { - return *reinterpret_cast(_data._mem); - } else if (type == VECTOR2) { - return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); - } else if (type == VECTOR2I) { - return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); - } else if (type == VECTOR4) { - return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); - } else if (type == VECTOR4I) { - return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); - } else { - return Vector3(); + switch (type) + { + case Variant::VECTOR2: return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); + case Variant::VECTOR2I: return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); + case Variant::VECTOR3: return *reinterpret_cast(_data._mem); + case Variant::VECTOR3I: return *reinterpret_cast(_data._mem); + case Variant::VECTOR4: return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); + case Variant::VECTOR4I: return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); + default: return Vector3(); } } Variant::operator Vector3i() const { - if (type == VECTOR3I) { - return *reinterpret_cast(_data._mem); - } else if (type == VECTOR3) { - return *reinterpret_cast(_data._mem); - } else if (type == VECTOR2) { - return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); - } else if (type == VECTOR2I) { - return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); - } else if (type == VECTOR4) { - return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); - } else if (type == VECTOR4I) { - return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); - } else { - return Vector3i(); + switch (type) + { + case Variant::VECTOR2: return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); + case Variant::VECTOR2I: return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); + case Variant::VECTOR3: return *reinterpret_cast(_data._mem); + case Variant::VECTOR3I: return *reinterpret_cast(_data._mem); + case Variant::VECTOR4: return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); + case Variant::VECTOR4I: return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); + default: return Vector3i(); } } Variant::operator Vector4() const { - if (type == VECTOR4) { - return *reinterpret_cast(_data._mem); - } else if (type == VECTOR4I) { - return *reinterpret_cast(_data._mem); - } else if (type == VECTOR2) { - return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); - } else if (type == VECTOR2I) { - return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); - } else if (type == VECTOR3) { - return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); - } else if (type == VECTOR3I) { - return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); - } else { - return Vector4(); + switch (type) + { + case Variant::VECTOR2: return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); + case Variant::VECTOR2I: return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); + case Variant::VECTOR3: return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); + case Variant::VECTOR3I: return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); + case Variant::VECTOR4: return *reinterpret_cast(_data._mem); + case Variant::VECTOR4I: return *reinterpret_cast(_data._mem); + default: return Vector4(); } } Variant::operator Vector4i() const { - if (type == VECTOR4I) { - return *reinterpret_cast(_data._mem); - } else if (type == VECTOR4) { + switch (type) + { + case Variant::VECTOR2: return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); + case Variant::VECTOR2I: return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); + case Variant::VECTOR3: return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); + case Variant::VECTOR3I: return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); + case Variant::VECTOR4: + { const Vector4 &v4 = *reinterpret_cast(_data._mem); return Vector4i(v4.x, v4.y, v4.z, v4.w); - } else if (type == VECTOR2) { - return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); - } else if (type == VECTOR2I) { - return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); - } else if (type == VECTOR3) { - return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); - } else if (type == VECTOR3I) { - return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); - } else { - return Vector4i(); + } break; + case Variant::VECTOR4I: return *reinterpret_cast(_data._mem); + default: return Vector4i(); } } @@ -3413,22 +2764,19 @@ bool StringLikeVariantComparator::compare(const Variant &p_lhs, const Variant &p } bool StringLikeVariantOrder::compare(const Variant &p_lhs, const Variant &p_rhs) { - if (p_lhs.get_type() == Variant::STRING) { - const String &lhs = *VariantInternal::get_string(&p_lhs); - if (p_rhs.get_type() == Variant::STRING) { - return StringName::AlphCompare::compare(lhs, *VariantInternal::get_string(&p_rhs)); - } else if (p_rhs.get_type() == Variant::STRING_NAME) { - return StringName::AlphCompare::compare(lhs, *VariantInternal::get_string_name(&p_rhs)); - } - } else if (p_lhs.get_type() == Variant::STRING_NAME) { - const StringName &lhs = *VariantInternal::get_string_name(&p_lhs); - if (p_rhs.get_type() == Variant::STRING) { - return StringName::AlphCompare::compare(lhs, *VariantInternal::get_string(&p_rhs)); - } else if (p_rhs.get_type() == Variant::STRING_NAME) { - return StringName::AlphCompare::compare(lhs, *VariantInternal::get_string_name(&p_rhs)); - } + String lhs; + switch (p_lhs.get_type()) + { + case Variant::STRING: lhs = *VariantInternal::get_string(&p_lhs); break; + case Variant::STRING_NAME: lhs = *VariantInternal::get_string_name(&p_lhs); break; + default: return p_lhs < p_rhs; + } + switch (p_rhs.get_type()) + { + case Variant::STRING: return StringName::AlphCompare::compare(lhs, *VariantInternal::get_string(&p_rhs)); + case Variant::STRING_NAME: return StringName::AlphCompare::compare(lhs, *VariantInternal::get_string_name(&p_rhs)); + default: return p_lhs < p_rhs; } - return p_lhs < p_rhs; } @@ -3436,17 +2784,12 @@ bool Variant::is_ref_counted() const { return type == OBJECT && _get_obj().id.is_ref_counted(); } -bool Variant::is_type_shared(Variant::Type p_type) { - switch (p_type) { - case OBJECT: - case ARRAY: - case DICTIONARY: - return true; - default: { - } - } +static const std::uint64_t IS_SHARED = (1ull << Variant::OBJECT) | + (1ull << Variant::ARRAY) | + (1ull << Variant::DICTIONARY); - return false; +bool Variant::is_type_shared(Variant::Type p_type) { + return (IS_SHARED & (1ull << p_type)) != 0; } bool Variant::is_shared() const { @@ -3455,33 +2798,28 @@ bool Variant::is_shared() const { bool Variant::is_read_only() const { switch (type) { - case ARRAY: - return reinterpret_cast(_data._mem)->is_read_only(); - case DICTIONARY: - return reinterpret_cast(_data._mem)->is_read_only(); - default: - return false; + case ARRAY: return reinterpret_cast(_data._mem)->is_read_only(); + case DICTIONARY: return reinterpret_cast(_data._mem)->is_read_only(); + default: return false; } } void Variant::_variant_call_error(const String &p_method, Callable::CallError &error) { + String err; switch (error.error) { case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: { - String err = "Invalid type for argument #" + itos(error.argument) + ", expected '" + Variant::get_type_name(Variant::Type(error.expected)) + "'."; - ERR_PRINT(err.utf8().get_data()); - + err = "Invalid type for argument #" + itos(error.argument) + ", expected '" + Variant::get_type_name(Variant::Type(error.expected)) + "'."; } break; case Callable::CallError::CALL_ERROR_INVALID_METHOD: { - String err = "Invalid method '" + p_method + "' for type '" + Variant::get_type_name(type) + "'."; - ERR_PRINT(err.utf8().get_data()); + err = "Invalid method '" + p_method + "' for type '" + Variant::get_type_name(type) + "'."; } break; case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: { - String err = "Too many arguments for method '" + p_method + "'"; - ERR_PRINT(err.utf8().get_data()); + err = "Too many arguments for method '" + p_method + "'"; } break; default: { } } + ERR_PRINT(err.utf8().get_data()); } void Variant::construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct, void *p_construct_ud) { diff --git a/core/variant/variant.h b/core/variant/variant.h index b7e84054e4f..6fc7cab1cf0 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -93,8 +93,6 @@ class Variant { // If this changes the table in variant_op must be updated enum Type { NIL, - - // atomic types BOOL, INT, FLOAT, @@ -282,54 +280,32 @@ class Variant { void _clear_internal(); - static constexpr bool needs_deinit[Variant::VARIANT_MAX] = { - false, //NIL, - false, //BOOL, - false, //INT, - false, //FLOAT, - true, //STRING, - false, //VECTOR2, - false, //VECTOR2I, - false, //RECT2, - false, //RECT2I, - false, //VECTOR3, - false, //VECTOR3I, - true, //TRANSFORM2D, - false, //VECTOR4, - false, //VECTOR4I, - false, //PLANE, - false, //QUATERNION, - true, //AABB, - true, //BASIS, - true, //TRANSFORM, - true, //PROJECTION, - - // misc types - false, //COLOR, - true, //STRING_NAME, - true, //NODE_PATH, - false, //RID, - true, //OBJECT, - true, //CALLABLE, - true, //SIGNAL, - true, //DICTIONARY, - true, //ARRAY, - - // typed arrays - true, //PACKED_BYTE_ARRAY, - true, //PACKED_INT32_ARRAY, - true, //PACKED_INT64_ARRAY, - true, //PACKED_FLOAT32_ARRAY, - true, //PACKED_FLOAT64_ARRAY, - true, //PACKED_STRING_ARRAY, - true, //PACKED_VECTOR2_ARRAY, - true, //PACKED_VECTOR3_ARRAY, - true, //PACKED_COLOR_ARRAY, - true, //PACKED_VECTOR4_ARRAY, - }; + static constexpr std::uint64_t needs_deinit = (1ull << Variant::STRING) | + (1ull << Variant::TRANSFORM2D) | + (1ull << Variant::AABB) | + (1ull << Variant::BASIS) | + (1ull << Variant::TRANSFORM3D) | + (1ull << Variant::PROJECTION) | + (1ull << Variant::STRING_NAME) | + (1ull << Variant::NODE_PATH) | + (1ull << Variant::OBJECT) | + (1ull << Variant::CALLABLE) | + (1ull << Variant::SIGNAL) | + (1ull << Variant::DICTIONARY) | + (1ull << Variant::ARRAY) | + (1ull << Variant::PACKED_BYTE_ARRAY) | + (1ull << Variant::PACKED_INT32_ARRAY) | + (1ull << Variant::PACKED_INT64_ARRAY) | + (1ull << Variant::PACKED_FLOAT32_ARRAY) | + (1ull << Variant::PACKED_FLOAT64_ARRAY) | + (1ull << Variant::PACKED_STRING_ARRAY) | + (1ull << Variant::PACKED_COLOR_ARRAY) | + (1ull << Variant::PACKED_VECTOR2_ARRAY) | + (1ull << Variant::PACKED_VECTOR3_ARRAY) | + (1ull << Variant::PACKED_VECTOR4_ARRAY); _FORCE_INLINE_ void clear() { - if (unlikely(needs_deinit[type])) { // Make it fast for types that don't need deinit. + if (unlikely((needs_deinit & (1ull << type)) != 0)) { // Make it fast for types that don't need deinit. _clear_internal(); } type = NIL; @@ -354,38 +330,24 @@ class Variant { template _ALWAYS_INLINE_ T _to_int() const { switch (get_type()) { - case NIL: - return 0; - case BOOL: - return _data._bool ? 1 : 0; - case INT: - return T(_data._int); - case FLOAT: - return T(_data._float); - case STRING: - return reinterpret_cast(_data._mem)->to_int(); - default: { - return 0; - } + case NIL: return 0; + case BOOL: return _data._bool ? 1 : 0; + case INT: return T(_data._int); + case FLOAT: return T(_data._float); + case STRING: return reinterpret_cast(_data._mem)->to_int(); + default: return 0; } } template _ALWAYS_INLINE_ T _to_float() const { switch (type) { - case NIL: - return 0; - case BOOL: - return _data._bool ? 1 : 0; - case INT: - return T(_data._int); - case FLOAT: - return T(_data._float); - case STRING: - return reinterpret_cast(_data._mem)->to_float(); - default: { - return 0; - } + case NIL: return 0; + case BOOL: return _data._bool ? 1 : 0; + case INT: return T(_data._int); + case FLOAT: return T(_data._float); + case STRING: return reinterpret_cast(_data._mem)->to_float(); + default: return 0; } } @@ -872,7 +834,7 @@ class Variant { } _FORCE_INLINE_ Variant() {} _FORCE_INLINE_ ~Variant() { - if (unlikely(needs_deinit[type])) { // Make it fast for types that don't need deinit. + if (unlikely((needs_deinit & (1ull << type)) != 0)) { // Make it fast for types that don't need deinit. _clear_internal(); } } From b71841894a1e81e3a56da0150252b79784cc5094 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 12 Mar 2026 00:40:39 -0400 Subject: [PATCH 02/13] clang-format --- core/variant/variant.cpp | 344 ++++++++++++++++++++++----------------- core/variant/variant.h | 80 +++++---- 2 files changed, 244 insertions(+), 180 deletions(-) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index b51115f7ddd..06c2fa2a43a 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -107,10 +107,10 @@ static const std::array TYPE_CAST_TAB (1 << Variant::AABB), // aabb (1 << Variant::QUATERNION) | (1 << Variant::BASIS), // basis (1 << Variant::TRANSFORM2D) | - (1 << Variant::QUATERNION) | - (1 << Variant::BASIS) | - (1 << Variant::TRANSFORM3D) | - (1 << Variant::PROJECTION), // transform3d + (1 << Variant::QUATERNION) | + (1 << Variant::BASIS) | + (1 << Variant::TRANSFORM3D) | + (1 << Variant::PROJECTION), // transform3d (1 << Variant::TRANSFORM3D) | (1 << Variant::PROJECTION), // projection (1 << Variant::STRING) | (1 << Variant::INT) | (1 << Variant::COLOR), // color (1 << Variant::STRING) | (1 << Variant::STRING_NAME), // stringname @@ -121,16 +121,16 @@ static const std::array TYPE_CAST_TAB (1 << Variant::SIGNAL), // signal (1 << Variant::DICTIONARY), // dictionary (1ull << Variant::ARRAY) | - (1ull << Variant::PACKED_BYTE_ARRAY) | - (1ull << Variant::PACKED_INT32_ARRAY) | - (1ull << Variant::PACKED_INT64_ARRAY) | - (1ull << Variant::PACKED_FLOAT32_ARRAY) | - (1ull << Variant::PACKED_FLOAT64_ARRAY) | - (1ull << Variant::PACKED_STRING_ARRAY) | - (1ull << Variant::PACKED_COLOR_ARRAY) | - (1ull << Variant::PACKED_VECTOR2_ARRAY) | - (1ull << Variant::PACKED_VECTOR3_ARRAY) | - (1ull << Variant::PACKED_VECTOR4_ARRAY), // array + (1ull << Variant::PACKED_BYTE_ARRAY) | + (1ull << Variant::PACKED_INT32_ARRAY) | + (1ull << Variant::PACKED_INT64_ARRAY) | + (1ull << Variant::PACKED_FLOAT32_ARRAY) | + (1ull << Variant::PACKED_FLOAT64_ARRAY) | + (1ull << Variant::PACKED_STRING_ARRAY) | + (1ull << Variant::PACKED_COLOR_ARRAY) | + (1ull << Variant::PACKED_VECTOR2_ARRAY) | + (1ull << Variant::PACKED_VECTOR3_ARRAY) | + (1ull << Variant::PACKED_VECTOR4_ARRAY), // array (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_BYTE_ARRAY), // packedbytearray (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_INT32_ARRAY), // packedint32array (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_INT64_ARRAY), // packedint64array @@ -163,10 +163,10 @@ static const std::array TYPE_STRICT_C (1 << Variant::AABB), // aabb (1 << Variant::QUATERNION) | (1 << Variant::BASIS), // basis (1 << Variant::TRANSFORM2D) | - (1 << Variant::QUATERNION) | - (1 << Variant::BASIS) | - (1 << Variant::TRANSFORM3D) | - (1 << Variant::PROJECTION), // transform3d + (1 << Variant::QUATERNION) | + (1 << Variant::BASIS) | + (1 << Variant::TRANSFORM3D) | + (1 << Variant::PROJECTION), // transform3d (1 << Variant::TRANSFORM3D) | (1 << Variant::PROJECTION), // projection (1 << Variant::STRING) | (1 << Variant::INT) | (1 << Variant::COLOR), // color (1 << Variant::STRING) | (1 << Variant::STRING_NAME), // stringname @@ -177,16 +177,16 @@ static const std::array TYPE_STRICT_C (1 << Variant::SIGNAL), // signal (1 << Variant::DICTIONARY), // dictionary (1ull << Variant::ARRAY) | - (1ull << Variant::PACKED_BYTE_ARRAY) | - (1ull << Variant::PACKED_INT32_ARRAY) | - (1ull << Variant::PACKED_INT64_ARRAY) | - (1ull << Variant::PACKED_FLOAT32_ARRAY) | - (1ull << Variant::PACKED_FLOAT64_ARRAY) | - (1ull << Variant::PACKED_STRING_ARRAY) | - (1ull << Variant::PACKED_COLOR_ARRAY) | - (1ull << Variant::PACKED_VECTOR2_ARRAY) | - (1ull << Variant::PACKED_VECTOR3_ARRAY) | - (1ull << Variant::PACKED_VECTOR4_ARRAY), // array + (1ull << Variant::PACKED_BYTE_ARRAY) | + (1ull << Variant::PACKED_INT32_ARRAY) | + (1ull << Variant::PACKED_INT64_ARRAY) | + (1ull << Variant::PACKED_FLOAT32_ARRAY) | + (1ull << Variant::PACKED_FLOAT64_ARRAY) | + (1ull << Variant::PACKED_STRING_ARRAY) | + (1ull << Variant::PACKED_COLOR_ARRAY) | + (1ull << Variant::PACKED_VECTOR2_ARRAY) | + (1ull << Variant::PACKED_VECTOR3_ARRAY) | + (1ull << Variant::PACKED_VECTOR4_ARRAY), // array (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_BYTE_ARRAY), // packedbytearray (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_INT32_ARRAY), // packedint32array (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_INT64_ARRAY), // packedint64array @@ -200,8 +200,7 @@ static const std::array TYPE_STRICT_C }; String Variant::get_type_name(Variant::Type p_type) { - if (p_type < VARIANT_MAX) - { + if (p_type < VARIANT_MAX) { return TYPE_STRING_TABLE[p_type]; } return ""; @@ -221,8 +220,7 @@ Variant::Type Variant::get_type_by_name(const String &p_type_name) { bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { std::uint64_t valid_types = 0; - if (p_type_to < VARIANT_MAX) - { + if (p_type_to < VARIANT_MAX) { valid_types = TYPE_CAST_TABLE[p_type_to]; } return (valid_types & (1ull << p_type_from)) != 0; @@ -230,8 +228,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type_to) { std::uint64_t valid_types = 0; - if (p_type_to < VARIANT_MAX) - { + if (p_type_to < VARIANT_MAX) { valid_types = TYPE_STRICT_CAST_TABLE[p_type_to]; } return (valid_types & (1ull << p_type_from)) != 0; @@ -688,7 +685,8 @@ void Variant::reference(const Variant &p_variant) { void Variant::zero() { switch (type) { - case NIL: break; + case NIL: + break; case BOOL: case INT: case FLOAT: @@ -717,13 +715,14 @@ void Variant::zero() { } } -template -void destroy(T *s) { reinterpret_cast(s)->~T(); } +template +void destroy(T *s) { + reinterpret_cast(s)->~T(); +} -template -void bucketFree(PagedAllocator *bucket, void *mem) -{ - ((PagedAllocator *)bucket)->free((T*)mem); +template +void bucketFree(PagedAllocator *bucket, void *mem) { + ((PagedAllocator *)bucket)->free((T *)mem); } using Destructor = void (*)(void *); @@ -761,8 +760,7 @@ void Variant::_clear_internal() { (Destructor)destroy, (Destructor)destroy, }; - static const std::array BUCKET_FREE_FN_TBL - { + static const std::array BUCKET_FREE_FN_TBL{ nullptr, nullptr, nullptr, @@ -793,8 +791,7 @@ void Variant::_clear_internal() { nullptr, nullptr, }; - static const std::array BUCKET_TBL - { + static const std::array BUCKET_TBL{ nullptr, nullptr, nullptr, @@ -806,15 +803,15 @@ void Variant::_clear_internal() { nullptr, nullptr, nullptr, - (void*)&Pools::_bucket_small, + (void *)&Pools::_bucket_small, nullptr, nullptr, nullptr, nullptr, - (void*)&Pools::_bucket_small, - (void*)&Pools::_bucket_medium, - (void*)&Pools::_bucket_medium, - (void*)&Pools::_bucket_large, + (void *)&Pools::_bucket_small, + (void *)&Pools::_bucket_medium, + (void *)&Pools::_bucket_medium, + (void *)&Pools::_bucket_large, nullptr, nullptr, nullptr, @@ -850,7 +847,9 @@ void Variant::_clear_internal() { } } break; // Miscellaneous types. - case OBJECT: { _get_obj().unref(is_weak_ref); } break; + case OBJECT: { + _get_obj().unref(is_weak_ref); + } break; // Arrays. case PACKED_BYTE_ARRAY: case PACKED_INT32_ARRAY: @@ -861,7 +860,9 @@ void Variant::_clear_internal() { case PACKED_VECTOR2_ARRAY: case PACKED_VECTOR3_ARRAY: case PACKED_VECTOR4_ARRAY: - case PACKED_COLOR_ARRAY: { PackedArrayRefBase::destroy(_data.packed_array); } break; + case PACKED_COLOR_ARRAY: { + PackedArrayRefBase::destroy(_data.packed_array); + } break; default: { // Not needed, there is no point. The following do not allocate memory: // VECTOR2, VECTOR3, VECTOR4, RECT2, PLANE, QUATERNION, COLOR. @@ -902,11 +903,13 @@ Variant::operator uint8_t() const { } Variant::operator ObjectID() const { - switch (type) - { - case Variant::INT: return ObjectID(_data._int); - case Variant::OBJECT: return _get_obj().id; - default: return ObjectID(); + switch (type) { + case Variant::INT: + return ObjectID(_data._int); + case Variant::OBJECT: + return _get_obj().id; + default: + return ObjectID(); } } @@ -923,11 +926,13 @@ Variant::operator double() const { } Variant::operator StringName() const { - switch (type) - { - case Variant::STRING_NAME: return *reinterpret_cast(_data._mem); - case Variant::STRING: return *reinterpret_cast(_data._mem); - default: return StringName(); + switch (type) { + case Variant::STRING_NAME: + return *reinterpret_cast(_data._mem); + case Variant::STRING: + return *reinterpret_cast(_data._mem); + default: + return StringName(); } } @@ -1128,102 +1133,140 @@ String Variant::to_json_string() const { } Variant::operator Vector2() const { - switch (type) - { - case Variant::VECTOR2: return *reinterpret_cast(_data._mem); - case Variant::VECTOR2I: return *reinterpret_cast(_data._mem); - case Variant::VECTOR3: return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - case Variant::VECTOR3I: return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - case Variant::VECTOR4: return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - case Variant::VECTOR4I: return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - default: return Vector2(); + switch (type) { + case Variant::VECTOR2: + return *reinterpret_cast(_data._mem); + case Variant::VECTOR2I: + return *reinterpret_cast(_data._mem); + case Variant::VECTOR3: + return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + case Variant::VECTOR3I: + return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + case Variant::VECTOR4: + return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + case Variant::VECTOR4I: + return Vector2(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + default: + return Vector2(); } } Variant::operator Vector2i() const { - switch (type) - { - case Variant::VECTOR2: return *reinterpret_cast(_data._mem); - case Variant::VECTOR2I: return *reinterpret_cast(_data._mem); - case Variant::VECTOR3: return Vector2i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - case Variant::VECTOR3I: return Vector2i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - case Variant::VECTOR4: return Vector2i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - case Variant::VECTOR4I: return Vector2i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); - default: return Vector2i(); + switch (type) { + case Variant::VECTOR2: + return *reinterpret_cast(_data._mem); + case Variant::VECTOR2I: + return *reinterpret_cast(_data._mem); + case Variant::VECTOR3: + return Vector2i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + case Variant::VECTOR3I: + return Vector2i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + case Variant::VECTOR4: + return Vector2i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + case Variant::VECTOR4I: + return Vector2i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y); + default: + return Vector2i(); } } Variant::operator Rect2() const { - switch (type) - { - case Variant::RECT2: return *reinterpret_cast(_data._mem); - case Variant::RECT2I: return *reinterpret_cast(_data._mem); - default: return Rect2(); + switch (type) { + case Variant::RECT2: + return *reinterpret_cast(_data._mem); + case Variant::RECT2I: + return *reinterpret_cast(_data._mem); + default: + return Rect2(); } } Variant::operator Rect2i() const { - switch (type) - { - case Variant::RECT2: return *reinterpret_cast(_data._mem); - case Variant::RECT2I: return *reinterpret_cast(_data._mem); - default: return Rect2i(); + switch (type) { + case Variant::RECT2: + return *reinterpret_cast(_data._mem); + case Variant::RECT2I: + return *reinterpret_cast(_data._mem); + default: + return Rect2i(); } } Variant::operator Vector3() const { - switch (type) - { - case Variant::VECTOR2: return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); - case Variant::VECTOR2I: return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); - case Variant::VECTOR3: return *reinterpret_cast(_data._mem); - case Variant::VECTOR3I: return *reinterpret_cast(_data._mem); - case Variant::VECTOR4: return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); - case Variant::VECTOR4I: return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); - default: return Vector3(); + switch (type) { + case Variant::VECTOR2: + return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); + case Variant::VECTOR2I: + return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); + case Variant::VECTOR3: + return *reinterpret_cast(_data._mem); + case Variant::VECTOR3I: + return *reinterpret_cast(_data._mem); + case Variant::VECTOR4: + return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); + case Variant::VECTOR4I: + return Vector3(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); + default: + return Vector3(); } } Variant::operator Vector3i() const { - switch (type) - { - case Variant::VECTOR2: return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); - case Variant::VECTOR2I: return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); - case Variant::VECTOR3: return *reinterpret_cast(_data._mem); - case Variant::VECTOR3I: return *reinterpret_cast(_data._mem); - case Variant::VECTOR4: return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); - case Variant::VECTOR4I: return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); - default: return Vector3i(); + switch (type) { + case Variant::VECTOR2: + return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); + case Variant::VECTOR2I: + return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0); + case Variant::VECTOR3: + return *reinterpret_cast(_data._mem); + case Variant::VECTOR3I: + return *reinterpret_cast(_data._mem); + case Variant::VECTOR4: + return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); + case Variant::VECTOR4I: + return Vector3i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z); + default: + return Vector3i(); } } Variant::operator Vector4() const { - switch (type) - { - case Variant::VECTOR2: return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); - case Variant::VECTOR2I: return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); - case Variant::VECTOR3: return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); - case Variant::VECTOR3I: return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); - case Variant::VECTOR4: return *reinterpret_cast(_data._mem); - case Variant::VECTOR4I: return *reinterpret_cast(_data._mem); - default: return Vector4(); + switch (type) { + case Variant::VECTOR2: + return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); + case Variant::VECTOR2I: + return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); + case Variant::VECTOR3: + return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); + case Variant::VECTOR3I: + return Vector4(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); + case Variant::VECTOR4: + return *reinterpret_cast(_data._mem); + case Variant::VECTOR4I: + return *reinterpret_cast(_data._mem); + default: + return Vector4(); } } Variant::operator Vector4i() const { - switch (type) - { - case Variant::VECTOR2: return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); - case Variant::VECTOR2I: return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); - case Variant::VECTOR3: return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); - case Variant::VECTOR3I: return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); - case Variant::VECTOR4: - { - const Vector4 &v4 = *reinterpret_cast(_data._mem); - return Vector4i(v4.x, v4.y, v4.z, v4.w); - } break; - case Variant::VECTOR4I: return *reinterpret_cast(_data._mem); - default: return Vector4i(); + switch (type) { + case Variant::VECTOR2: + return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); + case Variant::VECTOR2I: + return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, 0.0, 0.0); + case Variant::VECTOR3: + return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); + case Variant::VECTOR3I: + return Vector4i(reinterpret_cast(_data._mem)->x, reinterpret_cast(_data._mem)->y, reinterpret_cast(_data._mem)->z, 0.0); + case Variant::VECTOR4: { + const Vector4 &v4 = *reinterpret_cast(_data._mem); + return Vector4i(v4.x, v4.y, v4.z, v4.w); + } break; + case Variant::VECTOR4I: + return *reinterpret_cast(_data._mem); + default: + return Vector4i(); } } @@ -2765,17 +2808,23 @@ bool StringLikeVariantComparator::compare(const Variant &p_lhs, const Variant &p bool StringLikeVariantOrder::compare(const Variant &p_lhs, const Variant &p_rhs) { String lhs; - switch (p_lhs.get_type()) - { - case Variant::STRING: lhs = *VariantInternal::get_string(&p_lhs); break; - case Variant::STRING_NAME: lhs = *VariantInternal::get_string_name(&p_lhs); break; - default: return p_lhs < p_rhs; - } - switch (p_rhs.get_type()) - { - case Variant::STRING: return StringName::AlphCompare::compare(lhs, *VariantInternal::get_string(&p_rhs)); - case Variant::STRING_NAME: return StringName::AlphCompare::compare(lhs, *VariantInternal::get_string_name(&p_rhs)); - default: return p_lhs < p_rhs; + switch (p_lhs.get_type()) { + case Variant::STRING: + lhs = *VariantInternal::get_string(&p_lhs); + break; + case Variant::STRING_NAME: + lhs = *VariantInternal::get_string_name(&p_lhs); + break; + default: + return p_lhs < p_rhs; + } + switch (p_rhs.get_type()) { + case Variant::STRING: + return StringName::AlphCompare::compare(lhs, *VariantInternal::get_string(&p_rhs)); + case Variant::STRING_NAME: + return StringName::AlphCompare::compare(lhs, *VariantInternal::get_string_name(&p_rhs)); + default: + return p_lhs < p_rhs; } return p_lhs < p_rhs; } @@ -2785,8 +2834,8 @@ bool Variant::is_ref_counted() const { } static const std::uint64_t IS_SHARED = (1ull << Variant::OBJECT) | - (1ull << Variant::ARRAY) | - (1ull << Variant::DICTIONARY); + (1ull << Variant::ARRAY) | + (1ull << Variant::DICTIONARY); bool Variant::is_type_shared(Variant::Type p_type) { return (IS_SHARED & (1ull << p_type)) != 0; @@ -2798,9 +2847,12 @@ bool Variant::is_shared() const { bool Variant::is_read_only() const { switch (type) { - case ARRAY: return reinterpret_cast(_data._mem)->is_read_only(); - case DICTIONARY: return reinterpret_cast(_data._mem)->is_read_only(); - default: return false; + case ARRAY: + return reinterpret_cast(_data._mem)->is_read_only(); + case DICTIONARY: + return reinterpret_cast(_data._mem)->is_read_only(); + default: + return false; } } diff --git a/core/variant/variant.h b/core/variant/variant.h index 6fc7cab1cf0..2af6c101d7a 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -281,28 +281,28 @@ class Variant { void _clear_internal(); static constexpr std::uint64_t needs_deinit = (1ull << Variant::STRING) | - (1ull << Variant::TRANSFORM2D) | - (1ull << Variant::AABB) | - (1ull << Variant::BASIS) | - (1ull << Variant::TRANSFORM3D) | - (1ull << Variant::PROJECTION) | - (1ull << Variant::STRING_NAME) | - (1ull << Variant::NODE_PATH) | - (1ull << Variant::OBJECT) | - (1ull << Variant::CALLABLE) | - (1ull << Variant::SIGNAL) | - (1ull << Variant::DICTIONARY) | - (1ull << Variant::ARRAY) | - (1ull << Variant::PACKED_BYTE_ARRAY) | - (1ull << Variant::PACKED_INT32_ARRAY) | - (1ull << Variant::PACKED_INT64_ARRAY) | - (1ull << Variant::PACKED_FLOAT32_ARRAY) | - (1ull << Variant::PACKED_FLOAT64_ARRAY) | - (1ull << Variant::PACKED_STRING_ARRAY) | - (1ull << Variant::PACKED_COLOR_ARRAY) | - (1ull << Variant::PACKED_VECTOR2_ARRAY) | - (1ull << Variant::PACKED_VECTOR3_ARRAY) | - (1ull << Variant::PACKED_VECTOR4_ARRAY); + (1ull << Variant::TRANSFORM2D) | + (1ull << Variant::AABB) | + (1ull << Variant::BASIS) | + (1ull << Variant::TRANSFORM3D) | + (1ull << Variant::PROJECTION) | + (1ull << Variant::STRING_NAME) | + (1ull << Variant::NODE_PATH) | + (1ull << Variant::OBJECT) | + (1ull << Variant::CALLABLE) | + (1ull << Variant::SIGNAL) | + (1ull << Variant::DICTIONARY) | + (1ull << Variant::ARRAY) | + (1ull << Variant::PACKED_BYTE_ARRAY) | + (1ull << Variant::PACKED_INT32_ARRAY) | + (1ull << Variant::PACKED_INT64_ARRAY) | + (1ull << Variant::PACKED_FLOAT32_ARRAY) | + (1ull << Variant::PACKED_FLOAT64_ARRAY) | + (1ull << Variant::PACKED_STRING_ARRAY) | + (1ull << Variant::PACKED_COLOR_ARRAY) | + (1ull << Variant::PACKED_VECTOR2_ARRAY) | + (1ull << Variant::PACKED_VECTOR3_ARRAY) | + (1ull << Variant::PACKED_VECTOR4_ARRAY); _FORCE_INLINE_ void clear() { if (unlikely((needs_deinit & (1ull << type)) != 0)) { // Make it fast for types that don't need deinit. @@ -330,24 +330,36 @@ class Variant { template _ALWAYS_INLINE_ T _to_int() const { switch (get_type()) { - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return T(_data._int); - case FLOAT: return T(_data._float); - case STRING: return reinterpret_cast(_data._mem)->to_int(); - default: return 0; + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return T(_data._int); + case FLOAT: + return T(_data._float); + case STRING: + return reinterpret_cast(_data._mem)->to_int(); + default: + return 0; } } template _ALWAYS_INLINE_ T _to_float() const { switch (type) { - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return T(_data._int); - case FLOAT: return T(_data._float); - case STRING: return reinterpret_cast(_data._mem)->to_float(); - default: return 0; + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return T(_data._int); + case FLOAT: + return T(_data._float); + case STRING: + return reinterpret_cast(_data._mem)->to_float(); + default: + return 0; } } From ac618b9131a31068492a4db37d34a5be45544ef1 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 12 Mar 2026 01:13:42 -0400 Subject: [PATCH 03/13] Apply some better enumeration validation --- core/variant/variant.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 06c2fa2a43a..97abff12ca6 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -200,7 +200,7 @@ static const std::array TYPE_STRICT_C }; String Variant::get_type_name(Variant::Type p_type) { - if (p_type < VARIANT_MAX) { + if ((p_type >= NIL) && (p_type < VARIANT_MAX)) { return TYPE_STRING_TABLE[p_type]; } return ""; @@ -209,7 +209,7 @@ String Variant::get_type_name(Variant::Type p_type) { Variant::Type Variant::get_type_by_name(const String &p_type_name) { static HashMap type_names; if (unlikely(type_names.is_empty())) { - for (int i = 0; i < VARIANT_MAX; i++) { + for (int i = NIL; i < VARIANT_MAX; i++) { type_names[get_type_name((Type)i)] = (Type)i; } } @@ -220,7 +220,7 @@ Variant::Type Variant::get_type_by_name(const String &p_type_name) { bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { std::uint64_t valid_types = 0; - if (p_type_to < VARIANT_MAX) { + if ((p_type_to >= NIL) && (p_type_to < VARIANT_MAX)) { valid_types = TYPE_CAST_TABLE[p_type_to]; } return (valid_types & (1ull << p_type_from)) != 0; @@ -228,7 +228,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type_to) { std::uint64_t valid_types = 0; - if (p_type_to < VARIANT_MAX) { + if ((p_type_to >= NIL) && (p_type_to < VARIANT_MAX)) { valid_types = TYPE_STRICT_CAST_TABLE[p_type_to]; } return (valid_types & (1ull << p_type_from)) != 0; From 6ff4f4f682f4351ee03cc0261ed5251f7cd90ff8 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 12 Mar 2026 01:30:24 -0400 Subject: [PATCH 04/13] early return on default error case --- core/variant/variant.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 97abff12ca6..8860d520886 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -2868,8 +2868,8 @@ void Variant::_variant_call_error(const String &p_method, Callable::CallError &e case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: { err = "Too many arguments for method '" + p_method + "'"; } break; - default: { - } + default: + return; } ERR_PRINT(err.utf8().get_data()); } From f9ed091177ccd59eea8d2fb6d04d1e817e1a2105 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 12 Mar 2026 01:47:40 -0400 Subject: [PATCH 05/13] Pull some error messages from later in the file --- core/variant/variant.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 8860d520886..2009cc624df 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -117,7 +117,7 @@ static const std::array TYPE_CAST_TAB (1 << Variant::STRING) | (1 << Variant::NODE_PATH), // nodepath (1 << Variant::OBJECT) | (1 << Variant::RID), // rid (1 << Variant::NIL) | (1 << Variant::OBJECT), // object - (1 << Variant::CALLABLE), // callbale + (1 << Variant::CALLABLE), // callable (1 << Variant::SIGNAL), // signal (1 << Variant::DICTIONARY), // dictionary (1ull << Variant::ARRAY) | @@ -2826,7 +2826,6 @@ bool StringLikeVariantOrder::compare(const Variant &p_lhs, const Variant &p_rhs) default: return p_lhs < p_rhs; } - return p_lhs < p_rhs; } bool Variant::is_ref_counted() const { @@ -2859,15 +2858,17 @@ bool Variant::is_read_only() const { void Variant::_variant_call_error(const String &p_method, Callable::CallError &error) { String err; switch (error.error) { - case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: { + case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: err = "Invalid type for argument #" + itos(error.argument) + ", expected '" + Variant::get_type_name(Variant::Type(error.expected)) + "'."; - } break; - case Callable::CallError::CALL_ERROR_INVALID_METHOD: { + case Callable::CallError::CALL_ERROR_INVALID_METHOD: err = "Invalid method '" + p_method + "' for type '" + Variant::get_type_name(type) + "'."; - } break; - case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: { + case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: + case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: err = "Too many arguments for method '" + p_method + "'"; - } break; + case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL: + err = "Instance is null"; + case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST: + err = "Method not const in const instance"; default: return; } From 7913061c7bc137c1f47222d8445c8fd9973aad2d Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 12 Mar 2026 01:56:28 -0400 Subject: [PATCH 06/13] Actually break on error set --- core/variant/variant.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 2009cc624df..ef4bd76ddb2 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -2860,15 +2860,20 @@ void Variant::_variant_call_error(const String &p_method, Callable::CallError &e switch (error.error) { case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: err = "Invalid type for argument #" + itos(error.argument) + ", expected '" + Variant::get_type_name(Variant::Type(error.expected)) + "'."; + break; case Callable::CallError::CALL_ERROR_INVALID_METHOD: err = "Invalid method '" + p_method + "' for type '" + Variant::get_type_name(type) + "'."; + break; case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: err = "Too many arguments for method '" + p_method + "'"; + break; case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL: err = "Instance is null"; + break; case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST: err = "Method not const in const instance"; + break; default: return; } From 0912d32db92cceecb5c553bcf422a25e255dc0fc Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 12 Mar 2026 21:05:40 -0400 Subject: [PATCH 07/13] Turn runtime static hashmap to a compile-time hashmap --- core/variant/variant.cpp | 53 +++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index ef4bd76ddb2..036654d1d6d 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -40,6 +40,7 @@ #include "core/variant/variant_parser.h" #include #include +#include PagedAllocator Variant::Pools::_bucket_small; PagedAllocator Variant::Pools::_bucket_medium; @@ -199,6 +200,48 @@ static const std::array TYPE_STRICT_C (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_VECTOR4_ARRAY), // packedvec4array }; +static const std::unordered_map STRING_TO_TYPE_TBL = { + { "Nil", Variant::NIL }, + { "bool", Variant::BOOL }, + { "int", Variant::INT }, + { "float", Variant::FLOAT }, + { "String", Variant::STRING }, + { "Vector2", Variant::VECTOR2 }, + { "Vector2i", Variant::VECTOR2I }, + { "Rect2", Variant::RECT2 }, + { "Rect2i", Variant::RECT2I }, + { "Vector3", Variant::VECTOR3 }, + { "Vector3i", Variant::VECTOR3I }, + { "Transform2D", Variant::TRANSFORM2D }, + { "Vector4", Variant::VECTOR4 }, + { "Vector4i", Variant::VECTOR4I }, + { "Plane", Variant::PLANE }, + { "Quaternion", Variant::QUATERNION }, + { "AABB", Variant::AABB }, + { "Basis", Variant::BASIS }, + { "Transform3D", Variant::TRANSFORM3D }, + { "Projection", Variant::PROJECTION }, + { "Color", Variant::COLOR }, + { "StringName", Variant::STRING_NAME }, + { "NodePath", Variant::NODE_PATH }, + { "RID", Variant::RID }, + { "Object", Variant::OBJECT }, + { "Callable", Variant::CALLABLE }, + { "Signal", Variant::SIGNAL }, + { "Dictionary", Variant::DICTIONARY }, + { "Array", Variant::ARRAY }, + { "PackedByteArray", Variant::PACKED_BYTE_ARRAY }, + { "PackedInt32Array", Variant::PACKED_INT32_ARRAY }, + { "PackedInt64Array", Variant::PACKED_INT64_ARRAY }, + { "PackedFloat32Array", Variant::PACKED_FLOAT32_ARRAY }, + { "PackedFloat64Array", Variant::PACKED_FLOAT64_ARRAY }, + { "PackedStringArray", Variant::PACKED_STRING_ARRAY }, + { "PackedVector2Array", Variant::PACKED_VECTOR2_ARRAY }, + { "PackedVector3Array", Variant::PACKED_VECTOR3_ARRAY }, + { "PackedColorArray", Variant::PACKED_COLOR_ARRAY }, + { "PackedVector4Array", Variant::PACKED_VECTOR4_ARRAY }, +}; + String Variant::get_type_name(Variant::Type p_type) { if ((p_type >= NIL) && (p_type < VARIANT_MAX)) { return TYPE_STRING_TABLE[p_type]; @@ -207,15 +250,7 @@ String Variant::get_type_name(Variant::Type p_type) { } Variant::Type Variant::get_type_by_name(const String &p_type_name) { - static HashMap type_names; - if (unlikely(type_names.is_empty())) { - for (int i = NIL; i < VARIANT_MAX; i++) { - type_names[get_type_name((Type)i)] = (Type)i; - } - } - - const Type *ptr = type_names.getptr(p_type_name); - return (ptr == nullptr) ? VARIANT_MAX : *ptr; + return STRING_TO_TYPE_TBL.at(std::string(p_type_name.utf8().ptr())); } bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { From 3bdbec910314a1a8c7ed2e98cc2f37de026fd8bd Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 12 Mar 2026 21:35:23 -0400 Subject: [PATCH 08/13] Doc comments --- core/variant/variant.cpp | 19 +++++++++++++++++++ core/variant/variant.h | 3 ++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 036654d1d6d..f64b90a839a 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -46,6 +46,11 @@ PagedAllocator Variant::Pools::_bucket_small; PagedAllocator Variant::Pools::_bucket_medium; PagedAllocator Variant::Pools::_bucket_large; +/* + * This table gives textual names to the Variant::Type enum and is used in + * `get_type_name`. These must line up with their respective values in the + * Variant::Type enumeration + */ static const std::array TYPE_STRING_TABLE = { "Nil", "bool", @@ -88,6 +93,11 @@ static const std::array TYPE_STRING_TABLE = "PackedVector4Array", }; +/* + * This table indicates the types that a given Variant::Type can be cast from + * and is used in `can_convert`. These must line up with their respective values + * in the Variant::Type enumeration + */ static const std::array TYPE_CAST_TABLE = { ~0ull, // nil (1 << Variant::BOOL) | (1 << Variant::INT) | (1 << Variant::FLOAT) | (1 << Variant::STRING), // bool @@ -144,6 +154,11 @@ static const std::array TYPE_CAST_TAB (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_VECTOR4_ARRAY), // packedvec4array }; +/* + * This table indicates the types that a given Variant::Type can be cast from + * and is used in `can_convert_strict`. These must line up with their respective + * values in the Variant::Type enumeration + */ static const std::array TYPE_STRICT_CAST_TABLE = { ~0ull, // nil (1 << Variant::BOOL) | (1 << Variant::INT) | (1 << Variant::FLOAT), // bool @@ -200,6 +215,10 @@ static const std::array TYPE_STRICT_C (1ull << Variant::ARRAY) | (1ull << Variant::PACKED_VECTOR4_ARRAY), // packedvec4array }; +/* + * This table provides an inverse conversion to TYPE_STRING_TABLE and is used in + * `get_type_by_name`. + */ static const std::unordered_map STRING_TO_TYPE_TBL = { { "Nil", Variant::NIL }, { "bool", Variant::BOOL }, diff --git a/core/variant/variant.h b/core/variant/variant.h index 2af6c101d7a..62e50d9a87f 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -90,7 +90,8 @@ typedef Vector PackedVector4Array; class Variant { public: - // If this changes the table in variant_op must be updated + // If this changes the table in variant_op must be updated along side the + // tables in variant.cpp enum Type { NIL, BOOL, From 6626c410b7c9f2907e351d936cc87fee35c5761f Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 12 Mar 2026 21:45:59 -0400 Subject: [PATCH 09/13] Comment for clear_internal table --- core/variant/variant.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index f64b90a839a..65b14025bda 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -783,6 +783,9 @@ using Destructor = void (*)(void *); using BucketFree = void (*)(void *, void *); void Variant::_clear_internal() { + /* + * The following tables must line up with Variant::Type + */ static const std::array DESTRUCTOR_TABLE = { nullptr, nullptr, From c408e16a3feabcacda5ffe88ab02af1589373936 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Thu, 12 Mar 2026 22:31:05 -0400 Subject: [PATCH 10/13] Fix regression --- core/variant/variant.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 65b14025bda..79247c397a3 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -269,7 +269,11 @@ String Variant::get_type_name(Variant::Type p_type) { } Variant::Type Variant::get_type_by_name(const String &p_type_name) { - return STRING_TO_TYPE_TBL.at(std::string(p_type_name.utf8().ptr())); + std::string stdName(p_type_name.utf8().ptr()); + if (STRING_TO_TYPE_TBL.find(stdName) != STRING_TO_TYPE_TBL.end()) { + return STRING_TO_TYPE_TBL.at(stdName); + } + return Variant::Type::VARIANT_MAX; } bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { From 671ec61bc0d576d62034c2f8338d19a9174ff3d1 Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Fri, 13 Mar 2026 13:27:28 -0400 Subject: [PATCH 11/13] Clean up Variant::reference --- core/variant/variant.cpp | 491 ++++++++++++++++++--------------------- core/variant/variant.h | 23 ++ 2 files changed, 251 insertions(+), 263 deletions(-) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 79247c397a3..9a080a06e5b 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -46,6 +46,105 @@ PagedAllocator Variant::Pools::_bucket_small; PagedAllocator Variant::Pools::_bucket_medium; PagedAllocator Variant::Pools::_bucket_large; +/* + * The following three tables help handling cases where buckets are involved, + * namely `_clear_internal` and `reference`. These must line up with their + * respective values in the Variant::Type enumeration + */ +const std::array Variant::BUCKET_TBL = { + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + (void *)&Variant::Pools::_bucket_small, + nullptr, + nullptr, + nullptr, + nullptr, + (void *)&Variant::Pools::_bucket_small, + (void *)&Variant::Pools::_bucket_medium, + (void *)&Variant::Pools::_bucket_medium, + (void *)&Variant::Pools::_bucket_large, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, +}; +const std::array Variant::BUCKET_ALLOC_FN_TBL = { + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + (Variant::BucketAlloc)Variant::bucketAlloc, + nullptr, + nullptr, + nullptr, + nullptr, + (Variant::BucketAlloc)Variant::bucketAlloc, + (Variant::BucketAlloc)Variant::bucketAlloc, + (Variant::BucketAlloc)Variant::bucketAlloc, + (Variant::BucketAlloc)Variant::bucketAlloc, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, +}; +const std::array Variant::BUCKET_FREE_FN_TBL{ + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + (Variant::BucketFree)Variant::bucketFree, + nullptr, + nullptr, + nullptr, + nullptr, + (Variant::BucketFree)Variant::bucketFree, + (Variant::BucketFree)Variant::bucketFree, + (Variant::BucketFree)Variant::bucketFree, + (Variant::BucketFree)Variant::bucketFree, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, +}; + /* * This table gives textual names to the Variant::Type enum and is used in * `get_type_name`. These must line up with their respective values in the @@ -564,181 +663,113 @@ void Variant::ObjData::unref(bool p_is_weak_ref) { *this = ObjData(); } +using CopyCtorFromPtr = void (*)(void *, void *); + +template +void copyConstructFromPtr(T *dst, U *src) { + memnew_placement(dst, T(*src)); +} + +/* + * This table holds in-place copy constructors for different variants in the + * Variant::Type enum and is used in `reference`. These must line up with their + * respective values in the Variant::Type enumeration + */ +static const std::array COPY_CTOR_TABLE = { + nullptr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr<::AABB, ::AABB>, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr<::RID, ::RID>, + nullptr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, + (CopyCtorFromPtr)copyConstructFromPtr, +}; + void Variant::reference(const Variant &p_variant) { + using PackedArrayCreate = PackedArrayRefBase *(*)(); + + static const std::array< + PackedArrayCreate, + Variant::VARIANT_MAX - Variant::PACKED_BYTE_ARRAY> + PACKED_ARRAY_CREATE_TBL = { + packedArrayCreate, + packedArrayCreate, + packedArrayCreate, + packedArrayCreate, + packedArrayCreate, + packedArrayCreate, + packedArrayCreate, + packedArrayCreate, + packedArrayCreate, + packedArrayCreate, + }; + void *dst; + void *src; if (type == OBJECT && p_variant.type == OBJECT) { _get_obj().ref(p_variant._get_obj(), is_weak_ref, p_variant.is_weak_ref); return; } - clear(); - type = p_variant.type; - switch (p_variant.type) { - case NIL: { - // None. - } break; - - // Atomic types. - case BOOL: { - _data._bool = p_variant._data._bool; - } break; - case INT: { - _data._int = p_variant._data._int; - } break; - case FLOAT: { - _data._float = p_variant._data._float; - } break; - case STRING: { - memnew_placement(_data._mem, String(*reinterpret_cast(p_variant._data._mem))); - } break; - - // Math types. - case VECTOR2: { - memnew_placement(_data._mem, Vector2(*reinterpret_cast(p_variant._data._mem))); - } break; - case VECTOR2I: { - memnew_placement(_data._mem, Vector2i(*reinterpret_cast(p_variant._data._mem))); - } break; - case RECT2: { - memnew_placement(_data._mem, Rect2(*reinterpret_cast(p_variant._data._mem))); - } break; - case RECT2I: { - memnew_placement(_data._mem, Rect2i(*reinterpret_cast(p_variant._data._mem))); - } break; - case TRANSFORM2D: { - _data._transform2d = (Transform2D *)Pools::_bucket_small.alloc(); - memnew_placement(_data._transform2d, Transform2D(*p_variant._data._transform2d)); - } break; - case VECTOR3: { - memnew_placement(_data._mem, Vector3(*reinterpret_cast(p_variant._data._mem))); - } break; - case VECTOR3I: { - memnew_placement(_data._mem, Vector3i(*reinterpret_cast(p_variant._data._mem))); - } break; - case VECTOR4: { - memnew_placement(_data._mem, Vector4(*reinterpret_cast(p_variant._data._mem))); - } break; - case VECTOR4I: { - memnew_placement(_data._mem, Vector4i(*reinterpret_cast(p_variant._data._mem))); - } break; - case PLANE: { - memnew_placement(_data._mem, Plane(*reinterpret_cast(p_variant._data._mem))); - } break; - case AABB: { - _data._aabb = (::AABB *)Pools::_bucket_small.alloc(); - memnew_placement(_data._aabb, ::AABB(*p_variant._data._aabb)); - } break; - case QUATERNION: { - memnew_placement(_data._mem, Quaternion(*reinterpret_cast(p_variant._data._mem))); - } break; - case BASIS: { - _data._basis = (Basis *)Pools::_bucket_medium.alloc(); - memnew_placement(_data._basis, Basis(*p_variant._data._basis)); - } break; - case TRANSFORM3D: { - _data._transform3d = (Transform3D *)Pools::_bucket_medium.alloc(); - memnew_placement(_data._transform3d, Transform3D(*p_variant._data._transform3d)); - } break; - case PROJECTION: { - _data._projection = (Projection *)Pools::_bucket_large.alloc(); - memnew_placement(_data._projection, Projection(*p_variant._data._projection)); - } break; - - // Miscellaneous types. - case COLOR: { - memnew_placement(_data._mem, Color(*reinterpret_cast(p_variant._data._mem))); - } break; - case RID: { - memnew_placement(_data._mem, ::RID(*reinterpret_cast(p_variant._data._mem))); - } break; - case OBJECT: { + case TRANSFORM2D: + case AABB: + case BASIS: + case TRANSFORM3D: + case PROJECTION: + _data._ptr = BUCKET_ALLOC_FN_TBL[p_variant.type](BUCKET_TBL[p_variant.type]); + dst = _data._ptr; + src = p_variant._data._ptr; + break; + case OBJECT: memnew_placement(_data._mem, ObjData); _get_obj().ref(p_variant._get_obj(), is_weak_ref, p_variant.is_weak_ref); - } break; - case CALLABLE: { - memnew_placement(_data._mem, Callable(*reinterpret_cast(p_variant._data._mem))); - } break; - case SIGNAL: { - memnew_placement(_data._mem, Signal(*reinterpret_cast(p_variant._data._mem))); - } break; - case STRING_NAME: { - memnew_placement(_data._mem, StringName(*reinterpret_cast(p_variant._data._mem))); - } break; - case NODE_PATH: { - memnew_placement(_data._mem, NodePath(*reinterpret_cast(p_variant._data._mem))); - } break; - case DICTIONARY: { - memnew_placement(_data._mem, Dictionary(*reinterpret_cast(p_variant._data._mem))); - } break; - case ARRAY: { - memnew_placement(_data._mem, Array(*reinterpret_cast(p_variant._data._mem))); - } break; - - // Arrays. - case PACKED_BYTE_ARRAY: { - _data.packed_array = static_cast *>(p_variant._data.packed_array)->reference(); - if (!_data.packed_array) { - _data.packed_array = PackedArrayRef::create(); - } - } break; - case PACKED_INT32_ARRAY: { - _data.packed_array = static_cast *>(p_variant._data.packed_array)->reference(); - if (!_data.packed_array) { - _data.packed_array = PackedArrayRef::create(); - } - } break; - case PACKED_INT64_ARRAY: { - _data.packed_array = static_cast *>(p_variant._data.packed_array)->reference(); - if (!_data.packed_array) { - _data.packed_array = PackedArrayRef::create(); - } - } break; - case PACKED_FLOAT32_ARRAY: { - _data.packed_array = static_cast *>(p_variant._data.packed_array)->reference(); - if (!_data.packed_array) { - _data.packed_array = PackedArrayRef::create(); - } - } break; - case PACKED_FLOAT64_ARRAY: { - _data.packed_array = static_cast *>(p_variant._data.packed_array)->reference(); - if (!_data.packed_array) { - _data.packed_array = PackedArrayRef::create(); - } - } break; - case PACKED_STRING_ARRAY: { - _data.packed_array = static_cast *>(p_variant._data.packed_array)->reference(); - if (!_data.packed_array) { - _data.packed_array = PackedArrayRef::create(); - } - } break; - case PACKED_VECTOR2_ARRAY: { - _data.packed_array = static_cast *>(p_variant._data.packed_array)->reference(); - if (!_data.packed_array) { - _data.packed_array = PackedArrayRef::create(); - } - } break; - case PACKED_VECTOR3_ARRAY: { - _data.packed_array = static_cast *>(p_variant._data.packed_array)->reference(); - if (!_data.packed_array) { - _data.packed_array = PackedArrayRef::create(); - } - } break; - case PACKED_COLOR_ARRAY: { - _data.packed_array = static_cast *>(p_variant._data.packed_array)->reference(); - if (!_data.packed_array) { - _data.packed_array = PackedArrayRef::create(); - } - } break; - case PACKED_VECTOR4_ARRAY: { - _data.packed_array = static_cast *>(p_variant._data.packed_array)->reference(); + // fallthrough + case NIL: + return; + case PACKED_BYTE_ARRAY: + case PACKED_INT32_ARRAY: + case PACKED_INT64_ARRAY: + case PACKED_FLOAT32_ARRAY: + case PACKED_FLOAT64_ARRAY: + case PACKED_STRING_ARRAY: + case PACKED_VECTOR2_ARRAY: + case PACKED_VECTOR3_ARRAY: + case PACKED_COLOR_ARRAY: + case PACKED_VECTOR4_ARRAY: + _data.packed_array = (p_variant._data.packed_array)->reference(); if (!_data.packed_array) { - _data.packed_array = PackedArrayRef::create(); + _data.packed_array = PACKED_ARRAY_CREATE_TBL[p_variant.type - PACKED_BYTE_ARRAY](); } - } break; - default: { - } + return; + default: + dst = _data._mem; + src = (void *)p_variant._data._mem; + break; } + COPY_CTOR_TABLE[p_variant.type](dst, src); } void Variant::zero() { @@ -778,111 +809,45 @@ void destroy(T *s) { reinterpret_cast(s)->~T(); } -template -void bucketFree(PagedAllocator *bucket, void *mem) { - ((PagedAllocator *)bucket)->free((T *)mem); -} - using Destructor = void (*)(void *); using BucketFree = void (*)(void *, void *); +/* + * The following table must line up with Variant::Type + */ +static const std::array DESTRUCTOR_TABLE = { + nullptr, + nullptr, + nullptr, + nullptr, + (Destructor)destroy, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + (Destructor)destroy, + nullptr, + nullptr, + nullptr, + nullptr, + (Destructor)destroy<::AABB>, + (Destructor)destroy, + (Destructor)destroy, + (Destructor)destroy, + nullptr, + (Destructor)destroy, + (Destructor)destroy, + (Destructor)destroy<::RID>, + nullptr, + (Destructor)destroy, + (Destructor)destroy, + (Destructor)destroy, + (Destructor)destroy, +}; + void Variant::_clear_internal() { - /* - * The following tables must line up with Variant::Type - */ - static const std::array DESTRUCTOR_TABLE = { - nullptr, - nullptr, - nullptr, - nullptr, - (Destructor)destroy, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - (Destructor)destroy, - nullptr, - nullptr, - nullptr, - nullptr, - (Destructor)destroy<::AABB>, - (Destructor)destroy, - (Destructor)destroy, - (Destructor)destroy, - nullptr, - (Destructor)destroy, - (Destructor)destroy, - (Destructor)destroy<::RID>, - nullptr, - (Destructor)destroy, - (Destructor)destroy, - (Destructor)destroy, - (Destructor)destroy, - }; - static const std::array BUCKET_FREE_FN_TBL{ - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - (BucketFree)bucketFree, - nullptr, - nullptr, - nullptr, - nullptr, - (BucketFree)bucketFree, - (BucketFree)bucketFree, - (BucketFree)bucketFree, - (BucketFree)bucketFree, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - }; - static const std::array BUCKET_TBL{ - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - (void *)&Pools::_bucket_small, - nullptr, - nullptr, - nullptr, - nullptr, - (void *)&Pools::_bucket_small, - (void *)&Pools::_bucket_medium, - (void *)&Pools::_bucket_medium, - (void *)&Pools::_bucket_large, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - }; switch (type) { case STRING: case STRING_NAME: diff --git a/core/variant/variant.h b/core/variant/variant.h index 62e50d9a87f..ee24879791c 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -65,6 +65,8 @@ #include "core/variant/dictionary.h" #include "core/variant/variant_deep_duplicate.h" +#include + class Object; class RefCounted; @@ -94,6 +96,8 @@ class Variant { // tables in variant.cpp enum Type { NIL, + + // atomic types BOOL, INT, FLOAT, @@ -172,6 +176,20 @@ class Variant { static PagedAllocator _bucket_large; }; + using BucketAlloc = void *(*)(void *); + using BucketFree = void (*)(void *, void *); + template + static void *bucketAlloc(PagedAllocator *bucket) { + return ((PagedAllocator *)bucket)->alloc(); + } + template + static void bucketFree(PagedAllocator *bucket, void *mem) { + ((PagedAllocator *)bucket)->free((T *)mem); + } + static const std::array BUCKET_TBL; + static const std::array BUCKET_ALLOC_FN_TBL; + static const std::array BUCKET_FREE_FN_TBL; + friend struct _VariantCall; friend class VariantInternal; // Variant takes 24 bytes when real_t is float, and 40 bytes if double. @@ -233,6 +251,11 @@ class Variant { _FORCE_INLINE_ virtual ~PackedArrayRefBase() {} //needs virtual destructor, but make inline }; + template + static PackedArrayRefBase *packedArrayCreate() { + return PackedArrayRef::create(); + } + template struct PackedArrayRef : public PackedArrayRefBase { Vector array; From 2dd4524419c9a9bc254576debb2613439b88809b Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Fri, 13 Mar 2026 17:08:03 -0400 Subject: [PATCH 12/13] Fix fallthrough error --- core/variant/variant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 9a080a06e5b..5a98289dd92 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -746,7 +746,7 @@ void Variant::reference(const Variant &p_variant) { case OBJECT: memnew_placement(_data._mem, ObjData); _get_obj().ref(p_variant._get_obj(), is_weak_ref, p_variant.is_weak_ref); - // fallthrough + [[fallthrough]] case NIL: return; case PACKED_BYTE_ARRAY: From 89452215ced53073a311938e9af2a66785fbf47e Mon Sep 17 00:00:00 2001 From: Victor Sohier <1sohiervic@gmail.com> Date: Fri, 13 Mar 2026 17:18:09 -0400 Subject: [PATCH 13/13] Fix missing semi-colon --- core/variant/variant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 5a98289dd92..09830ee456f 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -746,7 +746,7 @@ void Variant::reference(const Variant &p_variant) { case OBJECT: memnew_placement(_data._mem, ObjData); _get_obj().ref(p_variant._get_obj(), is_weak_ref, p_variant.is_weak_ref); - [[fallthrough]] + [[fallthrough]]; case NIL: return; case PACKED_BYTE_ARRAY: