Fix container and string leaks

Some functions return a new instance of such containers,
but instead we made a copy of them, without taking ownership of the
original created by the function.
Now we use a specific constructor taking ownership on the godot_* struct.
pull/490/head
Marc Gilleron 2021-01-07 01:05:12 +00:00
parent 43828ebb39
commit fb71edd45b
11 changed files with 124 additions and 83 deletions

View File

@ -58,6 +58,8 @@ class Array {
godot_array _godot_array; godot_array _godot_array;
friend class Variant; friend class Variant;
friend class Dictionary;
friend class String;
inline explicit Array(const godot_array &other) { inline explicit Array(const godot_array &other) {
_godot_array = other; _godot_array = other;
} }
@ -88,7 +90,7 @@ public:
Variant &operator[](const int idx); Variant &operator[](const int idx);
Variant operator[](const int idx) const; const Variant &operator[](const int idx) const;
void append(const Variant &v); void append(const Variant &v);

View File

@ -10,6 +10,11 @@ namespace godot {
class NodePath { class NodePath {
godot_node_path _node_path; godot_node_path _node_path;
friend class Variant;
inline explicit NodePath(godot_node_path node_path) {
_node_path = node_path;
}
public: public:
NodePath(); NodePath();

View File

@ -18,6 +18,12 @@ class Array;
class PoolByteArray { class PoolByteArray {
godot_pool_byte_array _godot_array; godot_pool_byte_array _godot_array;
friend class String;
friend class Variant;
inline explicit PoolByteArray(godot_pool_byte_array a) {
_godot_array = a;
}
public: public:
class Read { class Read {
@ -116,6 +122,11 @@ public:
class PoolIntArray { class PoolIntArray {
godot_pool_int_array _godot_array; godot_pool_int_array _godot_array;
friend class Variant;
explicit inline PoolIntArray(godot_pool_int_array a) {
_godot_array = a;
}
public: public:
class Read { class Read {
friend class PoolIntArray; friend class PoolIntArray;
@ -213,6 +224,11 @@ public:
class PoolRealArray { class PoolRealArray {
godot_pool_real_array _godot_array; godot_pool_real_array _godot_array;
friend class Variant;
explicit inline PoolRealArray(godot_pool_real_array a) {
_godot_array = a;
}
public: public:
class Read { class Read {
friend class PoolRealArray; friend class PoolRealArray;
@ -310,6 +326,12 @@ public:
class PoolStringArray { class PoolStringArray {
godot_pool_string_array _godot_array; godot_pool_string_array _godot_array;
friend class String;
friend class Variant;
explicit inline PoolStringArray(godot_pool_string_array a) {
_godot_array = a;
}
public: public:
class Read { class Read {
friend class PoolStringArray; friend class PoolStringArray;
@ -407,6 +429,11 @@ public:
class PoolVector2Array { class PoolVector2Array {
godot_pool_vector2_array _godot_array; godot_pool_vector2_array _godot_array;
friend class Variant;
explicit inline PoolVector2Array(godot_pool_vector2_array a) {
_godot_array = a;
}
public: public:
class Read { class Read {
friend class PoolVector2Array; friend class PoolVector2Array;
@ -504,6 +531,11 @@ public:
class PoolVector3Array { class PoolVector3Array {
godot_pool_vector3_array _godot_array; godot_pool_vector3_array _godot_array;
friend class Variant;
explicit inline PoolVector3Array(godot_pool_vector3_array a) {
_godot_array = a;
}
public: public:
class Read { class Read {
friend class PoolVector3Array; friend class PoolVector3Array;
@ -601,6 +633,11 @@ public:
class PoolColorArray { class PoolColorArray {
godot_pool_color_array _godot_array; godot_pool_color_array _godot_array;
friend class Variant;
explicit inline PoolColorArray(godot_pool_color_array a) {
_godot_array = a;
}
public: public:
class Read { class Read {
friend class PoolColorArray; friend class PoolColorArray;

View File

@ -29,7 +29,10 @@ public:
class String { class String {
godot_string _godot_string; godot_string _godot_string;
String(godot_string contents) : friend class Dictionary;
friend class NodePath;
friend class Variant;
explicit inline String(godot_string contents) :
_godot_string(contents) {} _godot_string(contents) {}
public: public:

View File

@ -31,6 +31,11 @@ class Array;
class Variant { class Variant {
godot_variant _godot_variant; godot_variant _godot_variant;
friend class Array;
inline explicit Variant(godot_variant v) {
_godot_variant = v;
}
public: public:
enum Type { enum Type {
@ -226,7 +231,9 @@ public:
operator NodePath() const; operator NodePath() const;
operator RID() const; operator RID() const;
operator godot_object *() const; operator godot_object *() const;
template <typename T> operator T*() const { return static_cast<T*>(T::___get_from_variant(*this)); }
template <typename T>
operator T *() const { return static_cast<T *>(T::___get_from_variant(*this)); }
operator Dictionary() const; operator Dictionary() const;
operator Array() const; operator Array() const;

View File

@ -5,6 +5,7 @@
namespace godot { namespace godot {
// This is an internal base class used by the bindings. You should not need to access its members.
class _Wrapped { class _Wrapped {
public: public:
godot_object *_owner; godot_object *_owner;

View File

@ -52,14 +52,16 @@ Array::Array(const PoolColorArray &a) {
Variant &Array::operator[](const int idx) { Variant &Array::operator[](const int idx) {
godot_variant *v = godot::api->godot_array_operator_index(&_godot_array, idx); godot_variant *v = godot::api->godot_array_operator_index(&_godot_array, idx);
return *(Variant *)v; // We assume it's ok to reinterpret because the value is a pointer whose data is already owned by the array,
// so can return a reference without constructing a Variant
return *reinterpret_cast<Variant *>(v);
} }
Variant Array::operator[](const int idx) const { const Variant &Array::operator[](const int idx) const {
// Yes, I'm casting away the const... you can hate me now. // Yes, I'm casting away the const... you can hate me now.
// since the result is // since the result is
godot_variant *v = godot::api->godot_array_operator_index((godot_array *)&_godot_array, idx); godot_variant *v = godot::api->godot_array_operator_index((godot_array *)&_godot_array, idx);
return *(Variant *)v; return *reinterpret_cast<const Variant *>(v);
} }
void Array::append(const Variant &v) { void Array::append(const Variant &v) {
@ -84,12 +86,12 @@ void Array::erase(const Variant &v) {
Variant Array::front() const { Variant Array::front() const {
godot_variant v = godot::api->godot_array_front(&_godot_array); godot_variant v = godot::api->godot_array_front(&_godot_array);
return *(Variant *)&v; return Variant(v);
} }
Variant Array::back() const { Variant Array::back() const {
godot_variant v = godot::api->godot_array_back(&_godot_array); godot_variant v = godot::api->godot_array_back(&_godot_array);
return *(Variant *)&v; return Variant(v);
} }
int Array::find(const Variant &what, const int from) { int Array::find(const Variant &what, const int from) {
@ -118,12 +120,12 @@ void Array::invert() {
Variant Array::pop_back() { Variant Array::pop_back() {
godot_variant v = godot::api->godot_array_pop_back(&_godot_array); godot_variant v = godot::api->godot_array_pop_back(&_godot_array);
return *(Variant *)&v; return Variant(v);
} }
Variant Array::pop_front() { Variant Array::pop_front() {
godot_variant v = godot::api->godot_array_pop_front(&_godot_array); godot_variant v = godot::api->godot_array_pop_front(&_godot_array);
return *(Variant *)&v; return Variant(v);
} }
void Array::push_back(const Variant &v) { void Array::push_back(const Variant &v) {
@ -170,17 +172,17 @@ int Array::bsearch_custom(const Variant &value, const Object *obj,
Array Array::duplicate(const bool deep) const { Array Array::duplicate(const bool deep) const {
godot_array arr = godot::core_1_1_api->godot_array_duplicate(&_godot_array, deep); godot_array arr = godot::core_1_1_api->godot_array_duplicate(&_godot_array, deep);
return *(Array *)&arr; return Array(arr);
} }
Variant Array::max() const { Variant Array::max() const {
godot_variant v = godot::core_1_1_api->godot_array_max(&_godot_array); godot_variant v = godot::core_1_1_api->godot_array_max(&_godot_array);
return *(Variant *)&v; return Variant(v);
} }
Variant Array::min() const { Variant Array::min() const {
godot_variant v = godot::core_1_1_api->godot_array_min(&_godot_array); godot_variant v = godot::core_1_1_api->godot_array_min(&_godot_array);
return *(Variant *)&v; return Variant(v);
} }
void Array::shuffle() { void Array::shuffle() {

View File

@ -45,16 +45,18 @@ uint32_t Dictionary::hash() const {
Array Dictionary::keys() const { Array Dictionary::keys() const {
godot_array a = godot::api->godot_dictionary_keys(&_godot_dictionary); godot_array a = godot::api->godot_dictionary_keys(&_godot_dictionary);
return *(Array *)&a; return Array(a);
} }
Variant &Dictionary::operator[](const Variant &key) { Variant &Dictionary::operator[](const Variant &key) {
return *(Variant *)godot::api->godot_dictionary_operator_index(&_godot_dictionary, (godot_variant *)&key); godot_variant *v = godot::api->godot_dictionary_operator_index(&_godot_dictionary, (godot_variant *)&key);
return *reinterpret_cast<Variant *>(v);
} }
const Variant &Dictionary::operator[](const Variant &key) const { const Variant &Dictionary::operator[](const Variant &key) const {
// oops I did it again // oops I did it again
return *(Variant *)godot::api->godot_dictionary_operator_index((godot_dictionary *)&_godot_dictionary, (godot_variant *)&key); godot_variant *v = godot::api->godot_dictionary_operator_index((godot_dictionary *)&_godot_dictionary, (godot_variant *)&key);
return *reinterpret_cast<Variant *>(v);
} }
int Dictionary::size() const { int Dictionary::size() const {
@ -63,12 +65,12 @@ int Dictionary::size() const {
String Dictionary::to_json() const { String Dictionary::to_json() const {
godot_string s = godot::api->godot_dictionary_to_json(&_godot_dictionary); godot_string s = godot::api->godot_dictionary_to_json(&_godot_dictionary);
return *(String *)&s; return String(s);
} }
Array Dictionary::values() const { Array Dictionary::values() const {
godot_array a = godot::api->godot_dictionary_values(&_godot_dictionary); godot_array a = godot::api->godot_dictionary_values(&_godot_dictionary);
return *(Array *)&a; return Array(a);
} }
Dictionary::~Dictionary() { Dictionary::~Dictionary() {

View File

@ -27,8 +27,7 @@ NodePath::NodePath(const char *contents) {
String NodePath::get_name(const int idx) const { String NodePath::get_name(const int idx) const {
godot_string str = godot::api->godot_node_path_get_name(&_node_path, idx); godot_string str = godot::api->godot_node_path_get_name(&_node_path, idx);
return String(str);
return *(String *)&str;
} }
int NodePath::get_name_count() const { int NodePath::get_name_count() const {
@ -37,7 +36,7 @@ int NodePath::get_name_count() const {
String NodePath::get_subname(const int idx) const { String NodePath::get_subname(const int idx) const {
godot_string str = godot::api->godot_node_path_get_subname(&_node_path, idx); godot_string str = godot::api->godot_node_path_get_subname(&_node_path, idx);
return *(String *)&str; return String(str);
} }
int NodePath::get_subname_count() const { int NodePath::get_subname_count() const {
@ -54,17 +53,16 @@ bool NodePath::is_empty() const {
NodePath NodePath::get_as_property_path() const { NodePath NodePath::get_as_property_path() const {
godot_node_path path = godot::core_1_1_api->godot_node_path_get_as_property_path(&_node_path); godot_node_path path = godot::core_1_1_api->godot_node_path_get_as_property_path(&_node_path);
return *(NodePath *)&path; return NodePath(path);
} }
String NodePath::get_concatenated_subnames() const { String NodePath::get_concatenated_subnames() const {
godot_string str = godot::api->godot_node_path_get_concatenated_subnames(&_node_path); godot_string str = godot::api->godot_node_path_get_concatenated_subnames(&_node_path);
return *(String *)&str; return String(str);
} }
NodePath::operator String() const { NodePath::operator String() const {
godot_string str = godot::api->godot_node_path_as_string(&_node_path); godot_string str = godot::api->godot_node_path_as_string(&_node_path);
return String(str);
return *(String *)&str;
} }
bool NodePath::operator==(const NodePath &other) { bool NodePath::operator==(const NodePath &other) {

View File

@ -195,8 +195,7 @@ bool String::begins_with_char_array(const char *p_char_array) const {
PoolStringArray String::bigrams() const { PoolStringArray String::bigrams() const {
godot_array arr = godot::api->godot_string_bigrams(&_godot_string); godot_array arr = godot::api->godot_string_bigrams(&_godot_string);
return Array(arr);
return *(Array *)&arr;
} }
String String::c_escape() const { String String::c_escape() const {
@ -329,7 +328,7 @@ bool String::matchn(String expr) const {
PoolByteArray String::md5_buffer() const { PoolByteArray String::md5_buffer() const {
godot_pool_byte_array arr = godot::api->godot_string_md5_buffer(&_godot_string); godot_pool_byte_array arr = godot::api->godot_string_md5_buffer(&_godot_string);
return *(PoolByteArray *)&arr; return PoolByteArray(arr);
} }
String String::md5_text() const { String String::md5_text() const {
@ -382,8 +381,7 @@ String String::right(int position) const {
PoolByteArray String::sha256_buffer() const { PoolByteArray String::sha256_buffer() const {
godot_pool_byte_array arr = godot::api->godot_string_sha256_buffer(&_godot_string); godot_pool_byte_array arr = godot::api->godot_string_sha256_buffer(&_godot_string);
return PoolByteArray(arr);
return *(PoolByteArray *)&arr;
} }
String String::sha256_text() const { String String::sha256_text() const {
@ -396,20 +394,19 @@ float String::similarity(String text) const {
PoolStringArray String::split(String divisor, bool allow_empty) const { PoolStringArray String::split(String divisor, bool allow_empty) const {
godot_array arr = godot::api->godot_string_split(&_godot_string, &divisor._godot_string); godot_array arr = godot::api->godot_string_split(&_godot_string, &divisor._godot_string);
return Array(arr);
return *(Array *)&arr;
} }
PoolIntArray String::split_ints(String divisor, bool allow_empty) const { PoolIntArray String::split_ints(String divisor, bool allow_empty) const {
godot_array arr = godot::api->godot_string_split_floats(&_godot_string, &divisor._godot_string); godot_array arr = godot::api->godot_string_split_floats(&_godot_string, &divisor._godot_string);
return Array(arr);
return *(Array *)&arr;
} }
PoolRealArray String::split_floats(String divisor, bool allow_empty) const { PoolRealArray String::split_floats(String divisor, bool allow_empty) const {
// TODO The GDNative API returns godot_array, when according to the doc, it should have been godot_pool_real_array
godot_array arr = godot::api->godot_string_split_floats(&_godot_string, &divisor._godot_string); godot_array arr = godot::api->godot_string_split_floats(&_godot_string, &divisor._godot_string);
Array wrapped_array(arr);
return *(Array *)&arr; return PoolRealArray(wrapped_array);
} }
String String::strip_edges(bool left, bool right) const { String String::strip_edges(bool left, bool right) const {
@ -457,33 +454,29 @@ signed char String::naturalnocasecmp_to(String p_str) const {
} }
String String::dedent() const { String String::dedent() const {
String new_string; godot_string s = godot::core_1_1_api->godot_string_dedent(&_godot_string);
new_string._godot_string = godot::core_1_1_api->godot_string_dedent(&_godot_string); return String(s);
return new_string;
} }
PoolStringArray String::rsplit(const String &divisor, const bool allow_empty, PoolStringArray String::rsplit(const String &divisor, const bool allow_empty, const int maxsplit) const {
const int maxsplit) const { godot_pool_string_array arr =
godot_pool_string_array arr = godot::core_1_1_api->godot_string_rsplit(&_godot_string, &divisor._godot_string, allow_empty, maxsplit); godot::core_1_1_api->godot_string_rsplit(&_godot_string, &divisor._godot_string, allow_empty, maxsplit);
return *(PoolStringArray *)&arr; return PoolStringArray(arr);
} }
String String::rstrip(const String &chars) const { String String::rstrip(const String &chars) const {
String new_string; godot_string s = godot::core_1_1_api->godot_string_rstrip(&_godot_string, &chars._godot_string);
new_string._godot_string = godot::core_1_1_api->godot_string_rstrip(&_godot_string, &chars._godot_string); return String(s);
return new_string;
} }
String String::trim_prefix(const String &prefix) const { String String::trim_prefix(const String &prefix) const {
String new_string; godot_string s = godot::core_1_1_api->godot_string_trim_prefix(&_godot_string, &prefix._godot_string);
new_string._godot_string = godot::core_1_1_api->godot_string_trim_prefix(&_godot_string, &prefix._godot_string); return String(s);
return new_string;
} }
String String::trim_suffix(const String &suffix) const { String String::trim_suffix(const String &suffix) const {
String new_string; godot_string s = godot::core_1_1_api->godot_string_trim_suffix(&_godot_string, &suffix._godot_string);
new_string._godot_string = godot::core_1_1_api->godot_string_trim_suffix(&_godot_string, &suffix._godot_string); return String(s);
return new_string;
} }
} // namespace godot } // namespace godot

View File

@ -205,9 +205,8 @@ Variant::operator double() const {
return godot::api->godot_variant_as_real(&_godot_variant); return godot::api->godot_variant_as_real(&_godot_variant);
} }
Variant::operator String() const { Variant::operator String() const {
String ret; godot_string s = godot::api->godot_variant_as_string(&_godot_variant);
*(godot_string *)&ret = godot::api->godot_variant_as_string(&_godot_variant); return String(s);
return ret;
} }
Variant::operator Vector2() const { Variant::operator Vector2() const {
godot_vector2 s = godot::api->godot_variant_as_vector2(&_godot_variant); godot_vector2 s = godot::api->godot_variant_as_vector2(&_godot_variant);
@ -251,9 +250,8 @@ Variant::operator Color() const {
return *(Color *)&s; return *(Color *)&s;
} }
Variant::operator NodePath() const { Variant::operator NodePath() const {
NodePath ret; godot_node_path ret = godot::api->godot_variant_as_node_path(&_godot_variant);
*(godot_node_path *)&ret = godot::api->godot_variant_as_node_path(&_godot_variant); return NodePath(ret);
return ret;
} }
Variant::operator RID() const { Variant::operator RID() const {
godot_rid s = godot::api->godot_variant_as_rid(&_godot_variant); godot_rid s = godot::api->godot_variant_as_rid(&_godot_variant);
@ -271,52 +269,45 @@ Variant::operator Array() const {
} }
Variant::operator PoolByteArray() const { Variant::operator PoolByteArray() const {
PoolByteArray ret; godot_pool_byte_array ret = godot::api->godot_variant_as_pool_byte_array(&_godot_variant);
*(godot_pool_byte_array *)&ret = godot::api->godot_variant_as_pool_byte_array(&_godot_variant); return PoolByteArray(ret);
return ret;
} }
Variant::operator PoolIntArray() const { Variant::operator PoolIntArray() const {
PoolIntArray ret; godot_pool_int_array ret = godot::api->godot_variant_as_pool_int_array(&_godot_variant);
*(godot_pool_int_array *)&ret = godot::api->godot_variant_as_pool_int_array(&_godot_variant); return PoolIntArray(ret);
return ret;
} }
Variant::operator PoolRealArray() const { Variant::operator PoolRealArray() const {
PoolRealArray ret; godot_pool_real_array ret = godot::api->godot_variant_as_pool_real_array(&_godot_variant);
*(godot_pool_real_array *)&ret = godot::api->godot_variant_as_pool_real_array(&_godot_variant); return PoolRealArray(ret);
return ret;
} }
Variant::operator PoolStringArray() const { Variant::operator PoolStringArray() const {
PoolStringArray ret; godot_pool_string_array ret = godot::api->godot_variant_as_pool_string_array(&_godot_variant);
*(godot_pool_string_array *)&ret = godot::api->godot_variant_as_pool_string_array(&_godot_variant); return PoolStringArray(ret);
return ret;
} }
Variant::operator PoolVector2Array() const { Variant::operator PoolVector2Array() const {
PoolVector2Array ret; godot_pool_vector2_array ret = godot::api->godot_variant_as_pool_vector2_array(&_godot_variant);
*(godot_pool_vector2_array *)&ret = godot::api->godot_variant_as_pool_vector2_array(&_godot_variant); return PoolVector2Array(ret);
return ret;
} }
Variant::operator PoolVector3Array() const { Variant::operator PoolVector3Array() const {
PoolVector3Array ret; godot_pool_vector3_array ret = godot::api->godot_variant_as_pool_vector3_array(&_godot_variant);
*(godot_pool_vector3_array *)&ret = godot::api->godot_variant_as_pool_vector3_array(&_godot_variant); return PoolVector3Array(ret);
return ret;
} }
Variant::operator PoolColorArray() const { Variant::operator PoolColorArray() const {
PoolColorArray ret; godot_pool_color_array ret = godot::api->godot_variant_as_pool_color_array(&_godot_variant);
*(godot_pool_color_array *)&ret = godot::api->godot_variant_as_pool_color_array(&_godot_variant); return PoolColorArray(ret);
return ret;
} }
Variant::operator godot_object *() const { Variant::operator godot_object *() const {
return godot::api->godot_variant_as_object(&_godot_variant); return godot::api->godot_variant_as_object(&_godot_variant);
} }
Variant::Type Variant::get_type() const { Variant::Type Variant::get_type() const {
return (Type)godot::api->godot_variant_get_type(&_godot_variant); return static_cast<Type>(godot::api->godot_variant_get_type(&_godot_variant));
} }
Variant Variant::call(const String &method, const Variant **args, const int arg_count) { Variant Variant::call(const String &method, const Variant **args, const int arg_count) {
Variant v; godot_variant v = godot::api->godot_variant_call(
*(godot_variant *)&v = godot::api->godot_variant_call(&_godot_variant, (godot_string *)&method, (const godot_variant **)args, arg_count, nullptr); &_godot_variant, (godot_string *)&method, (const godot_variant **)args, arg_count, nullptr);
return v; return Variant(v);
} }
bool Variant::has_method(const String &method) { bool Variant::has_method(const String &method) {