Variant cleanups.

This commit is contained in:
Relintai 2023-12-31 15:46:34 +01:00
parent 985aa8e2fb
commit 533dadacef
8 changed files with 234 additions and 87 deletions

View File

@ -5,10 +5,10 @@
#include "array.h" #include "array.h"
#include "core/containers/hashfuncs.h" #include "core/hashfuncs.h"
#include "core/containers/vector.h" #include "core/vector.h"
#include "core/object/object.h" #include "object/object.h"
#include "core/variant/variant.h" #include "object/variant.h"
class ArrayPrivate { class ArrayPrivate {
public: public:

View File

@ -6,9 +6,9 @@
/* From https://github.com/Relintai/pandemonium_engine (MIT) */ /* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/ /*************************************************************************/
#include "core/containers/list.h" #include "core/list.h"
#include "core/string/ustring.h" #include "core/ustring.h"
#include "core/variant/array.h" #include "object/array.h"
class Variant; class Variant;

13
sfw/object/object_id.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef OBJECTID_H
#define OBJECTID_H
/*************************************************************************/
/* object_id.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
#include "core/int_types.h"
typedef uint64_t ObjectID;
#endif

52
sfw/object/object_rc.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef OBJECTRC_H
#define OBJECTRC_H
/*************************************************************************/
/* object_rc.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
#include "core/memory.h"
#include "core/typedefs.h"
#include <atomic>
class Object;
// Used to track Variants pointing to a non-Reference Object
class ObjectRC {
std::atomic<Object *> _ptr;
std::atomic<uint32_t> _users;
public:
// This is for allowing debug builds to check for instance ID validity,
// so warnings are shown in debug builds when a stray Variant (one pointing
// to a released Object) would have happened.
const ObjectID instance_id;
_FORCE_INLINE_ void increment() {
_users.fetch_add(1, std::memory_order_relaxed);
}
_FORCE_INLINE_ bool decrement() {
return _users.fetch_sub(1, std::memory_order_relaxed) == 1;
}
_FORCE_INLINE_ bool invalidate() {
_ptr.store(nullptr, std::memory_order_release);
return decrement();
}
_FORCE_INLINE_ Object *get_ptr() {
return _ptr.load(std::memory_order_acquire);
}
_FORCE_INLINE_ ObjectRC(Object *p_object) :
instance_id(p_object->get_instance_id()) {
// 1 (the Object) + 1 (the first user)
_users.store(2, std::memory_order_relaxed);
_ptr.store(p_object, std::memory_order_release);
}
};
#endif

97
sfw/object/ref_ptr.cpp Normal file
View File

@ -0,0 +1,97 @@
/*************************************************************************/
/* ref_ptr.cpp */
/*************************************************************************/
/* This file is part of: */
/* PANDEMONIUM ENGINE */
/* https://github.com/Relintai/pandemonium_engine */
/*************************************************************************/
/* Copyright (c) 2022-present Péter Magyar. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "ref_ptr.h"
#include "object/reference.h"
#include "object/resource.h"
void RefPtr::operator=(const RefPtr &p_other) {
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0]));
*ref = *ref_other;
}
bool RefPtr::operator==(const RefPtr &p_other) const {
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0]));
return *ref == *ref_other;
}
bool RefPtr::operator!=(const RefPtr &p_other) const {
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0]));
return *ref != *ref_other;
}
RefPtr::RefPtr(const RefPtr &p_other) {
memnew_placement(&data[0], Ref<Reference>);
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0]));
*ref = *ref_other;
}
bool RefPtr::is_null() const {
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
return ref->is_null();
}
RID RefPtr::get_rid() const {
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
if (ref->is_null()) {
return RID();
}
Resource *res = Object::cast_to<Resource>(ref->ptr());
if (res) {
return res->get_rid();
}
return RID();
}
void RefPtr::unref() {
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
ref->unref();
}
RefPtr::RefPtr() {
ERR_FAIL_COND(sizeof(Ref<Reference>) > DATASIZE);
memnew_placement(&data[0], Ref<Reference>);
}
RefPtr::~RefPtr() {
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
ref->~Ref<Reference>();
}

36
sfw/object/ref_ptr.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef REF_PTR_H
#define REF_PTR_H
/*************************************************************************/
/* ref_ptr.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
/**
@author Juan Linietsky <reduzio@gmail.com>
* This class exists to workaround a limitation in C++ but keep the design OK.
* It's basically an opaque container of a Reference reference, so Variant can use it.
*/
#include "core/typedefs.h"
class RefPtr {
enum {
DATASIZE = sizeof(void *) //*4 -ref was shrunk
};
mutable char data[DATASIZE]; // too much probably, virtual class + pointer
public:
bool is_null() const;
void operator=(const RefPtr &p_other);
bool operator==(const RefPtr &p_other) const;
bool operator!=(const RefPtr &p_other) const;
void unref();
_FORCE_INLINE_ void *get_data() const { return data; }
RefPtr(const RefPtr &p_other);
RefPtr();
~RefPtr();
};
#endif // REF_PTR_H

View File

@ -5,15 +5,14 @@
#include "variant.h" #include "variant.h"
#include "core/core_string_names.h" //#include "core/core_string_names.h"
#include "core/io/marshalls.h" //#include "core/io/marshalls.h"
#include "core/math/math_funcs.h"
#include "core/object/object_rc.h" #include "core/math_funcs.h"
#include "core/object/resource.h"
#include "core/string/print_string.h" #include "object/object_rc.h"
#include "core/variant/variant_parser.h" #include "object/resource.h"
#include "scene/main/control.h"
#include "scene/main/node.h"
String Variant::get_type_name(Variant::Type p_type) { String Variant::get_type_name(Variant::Type p_type) {
switch (p_type) { switch (p_type) {

View File

@ -6,31 +6,26 @@
/* From https://github.com/Relintai/pandemonium_engine (MIT) */ /* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/ /*************************************************************************/
#include "core/pool_vector.h"
#include "core/aabb.h" #include "core/aabb.h"
#include "core/basis.h" #include "core/basis.h"
#include "core/color.h" #include "core/color.h"
#include "face3.h" #include "core/face3.h"
#include "core/plane.h" #include "core/plane.h"
#include "core/pool_vector.h"
#include "core/projection.h" #include "core/projection.h"
#include "core/quaternion.h" #include "core/quaternion.h"
#include "core/transform.h" #include "core/transform.h"
#include "core/transform_2d.h" #include "core/transform_2d.h"
#include "core/ustring.h"
#include "core/vector3.h" #include "core/vector3.h"
#include "core/vector3i.h" #include "core/vector3i.h"
#include "core/vector4.h" #include "core/vector4.h"
#include "core/vector4i.h" #include "core/vector4i.h"
#include "core/ustring.h" #include "object/array.h"
#include "array.h" #include "object/dictionary.h"
#include "dictionary.h"
class Object; class Object;
class ObjectRC; class ObjectRC;
class Node; // helper
class Control; // helper
struct PropertyInfo;
struct MethodInfo;
typedef PoolVector<uint8_t> PoolByteArray; typedef PoolVector<uint8_t> PoolByteArray;
typedef PoolVector<int> PoolIntArray; typedef PoolVector<int> PoolIntArray;
@ -72,42 +67,40 @@ public:
STRING, STRING,
// math types // math types
RECT2, // 5 RECT2,
RECT2I, RECT2I,
VECTOR2, VECTOR2,
VECTOR2I, VECTOR2I,
VECTOR3, VECTOR3,
VECTOR3I, // 10 VECTOR3I,
VECTOR4, VECTOR4,
VECTOR4I, VECTOR4I,
PLANE, PLANE,
QUATERNION, QUATERNION,
AABB, // 15 AABB,
BASIS, BASIS,
TRANSFORM, TRANSFORM,
TRANSFORM2D, TRANSFORM2D,
PROJECTION, PROJECTION,
// misc types // misc types
COLOR, // 20 COLOR,
NODE_PATH,
RID,
OBJECT, OBJECT,
STRING_NAME, STRING_NAME,
DICTIONARY, // 25 DICTIONARY,
ARRAY, ARRAY,
// arrays // arrays
POOL_BYTE_ARRAY, POOL_BYTE_ARRAY,
POOL_INT_ARRAY, POOL_INT_ARRAY,
POOL_REAL_ARRAY, POOL_REAL_ARRAY,
POOL_STRING_ARRAY, //30 POOL_STRING_ARRAY,
POOL_VECTOR2_ARRAY, POOL_VECTOR2_ARRAY,
POOL_VECTOR2I_ARRAY, POOL_VECTOR2I_ARRAY,
POOL_VECTOR3_ARRAY, POOL_VECTOR3_ARRAY,
POOL_VECTOR3I_ARRAY, POOL_VECTOR3I_ARRAY,
POOL_VECTOR4_ARRAY, //35 POOL_VECTOR4_ARRAY,
POOL_VECTOR4I_ARRAY, POOL_VECTOR4I_ARRAY,
POOL_COLOR_ARRAY, POOL_COLOR_ARRAY,
@ -121,7 +114,6 @@ public:
}; };
private: private:
friend struct _VariantCall;
// Variant takes 20 bytes when real_t is float, and 36 if double // Variant takes 20 bytes when real_t is float, and 36 if double
// it only allocates extra memory for aabb/matrix. // it only allocates extra memory for aabb/matrix.
@ -209,12 +201,9 @@ public:
operator Projection() const; operator Projection() const;
operator Color() const; operator Color() const;
operator NodePath() const;
operator RefPtr() const; operator RefPtr() const;
operator Object *() const; operator Object *() const;
operator Node *() const;
operator Control *() const;
operator Dictionary() const; operator Dictionary() const;
operator Array() const; operator Array() const;
@ -328,7 +317,6 @@ public:
// If this changes the table in variant_op must be updated // If this changes the table in variant_op must be updated
enum Operator { enum Operator {
//comparison //comparison
OP_EQUAL, OP_EQUAL,
OP_NOT_EQUAL, OP_NOT_EQUAL,
@ -360,9 +348,14 @@ public:
//containment //containment
OP_IN, OP_IN,
OP_MAX OP_MAX
}; };
//Maybe add helper methods that use these
//Like max()
//add()
//maybe operators like with add
//?
static String get_operator_name(Operator p_op); static String get_operator_name(Operator p_op);
static void evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b, Variant &r_ret, bool &r_valid); static void evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b, Variant &r_ret, bool &r_valid);
static _FORCE_INLINE_ Variant evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b) { static _FORCE_INLINE_ Variant evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b) {
@ -378,39 +371,12 @@ public:
static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst); static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst);
static void sub(const Variant &a, const Variant &b, Variant &r_dst); static void sub(const Variant &a, const Variant &b, Variant &r_dst);
struct CallError { //Maybe add helper methods that call this? like get_x(), set_x() etc Or just x(), x(value)?
enum Error { //Check if operator[] can take strings and ints that might work too
CALL_OK,
CALL_ERROR_INVALID_METHOD,
CALL_ERROR_INVALID_ARGUMENT,
CALL_ERROR_TOO_MANY_ARGUMENTS,
CALL_ERROR_TOO_FEW_ARGUMENTS,
CALL_ERROR_INSTANCE_IS_NULL,
};
Error error;
int argument;
Type expected;
};
void call_ptr(const StringName &p_method, const Variant **p_args, int p_argcount, Variant *r_ret, CallError &r_error);
Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, CallError &r_error);
Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant(), const Variant &p_arg6 = Variant(), const Variant &p_arg7 = Variant(), const Variant &p_arg8 = Variant());
static String get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Variant::CallError &ce);
static Variant construct(const Variant::Type, const Variant **p_args, int p_argcount, CallError &r_error, bool p_strict = true);
void get_method_list(List<MethodInfo> *p_list) const;
bool has_method(const StringName &p_method) const;
static Vector<Variant::Type> get_method_argument_types(Variant::Type p_type, const StringName &p_method);
static Vector<Variant> get_method_default_arguments(Variant::Type p_type, const StringName &p_method);
static Variant::Type get_method_return_type(Variant::Type p_type, const StringName &p_method, bool *r_has_return = nullptr);
static Vector<StringName> get_method_argument_names(Variant::Type p_type, const StringName &p_method);
static bool is_method_const(Variant::Type p_type, const StringName &p_method);
void set_named(const StringName &p_index, const Variant &p_value, bool *r_valid = nullptr); void set_named(const StringName &p_index, const Variant &p_value, bool *r_valid = nullptr);
Variant get_named(const StringName &p_index, bool *r_valid = nullptr) const; Variant get_named(const StringName &p_index, bool *r_valid = nullptr) const;
//Implement operator[]s that use these?
void set(const Variant &p_index, const Variant &p_value, bool *r_valid = nullptr); void set(const Variant &p_index, const Variant &p_value, bool *r_valid = nullptr);
Variant get(const Variant &p_index, bool *r_valid = nullptr) const; Variant get(const Variant &p_index, bool *r_valid = nullptr) const;
bool in(const Variant &p_index, bool *r_valid = nullptr) const; bool in(const Variant &p_index, bool *r_valid = nullptr) const;
@ -419,10 +385,6 @@ public:
bool iter_next(Variant &r_iter, bool &r_valid) const; bool iter_next(Variant &r_iter, bool &r_valid) const;
Variant iter_get(const Variant &r_iter, bool &r_valid) const; Variant iter_get(const Variant &r_iter, bool &r_valid) const;
void get_property_list(List<PropertyInfo> *p_list) const;
//argsVariant call()
bool deep_equal(const Variant &p_variant, int p_recursion_count = 0) const; bool deep_equal(const Variant &p_variant, int p_recursion_count = 0) const;
bool operator==(const Variant &p_variant) const; bool operator==(const Variant &p_variant) const;
bool operator!=(const Variant &p_variant) const; bool operator!=(const Variant &p_variant) const;
@ -434,18 +396,6 @@ public:
bool booleanize() const; bool booleanize() const;
String stringify(List<const void *> &stack) const; String stringify(List<const void *> &stack) const;
void static_assign(const Variant &p_variant);
static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list);
static void get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants);
static bool has_constant(Variant::Type p_type, const StringName &p_value);
static Variant get_constant_value(Variant::Type p_type, const StringName &p_value, bool *r_valid = nullptr);
typedef String (*ObjectDeConstruct)(const Variant &p_object, void *ud);
typedef void (*ObjectConstruct)(const String &p_text, void *ud, Variant &r_value);
String get_construct_string() const;
static void construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct = nullptr, void *p_construct_ud = nullptr);
void operator=(const Variant &p_variant); // only this is enough for all the other types void operator=(const Variant &p_variant); // only this is enough for all the other types
Variant(const Variant &p_variant); Variant(const Variant &p_variant);
_FORCE_INLINE_ Variant() { _FORCE_INLINE_ Variant() {