Don't crash on printing nested types
When adding an Array or Dictionary to itself operator String() got in an infinite loop. This commit adds a stack to operator String() (Through the use of a new 'stringify method'). This stack keeps track of all unique Arrays and Dictionaries it has seen. When a duplicate is found only a static string is printed '[...]' or '{...}'. This mirror Python's behavior in a similar case.
This commit is contained in:
parent
8e652a1400
commit
8b1e297fc6
|
@ -401,6 +401,10 @@ Variant Array::max() const {
|
||||||
return maxval;
|
return maxval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const void *Array::id() const {
|
||||||
|
return _p->array.ptr();
|
||||||
|
}
|
||||||
|
|
||||||
Array::Array(const Array &p_from) {
|
Array::Array(const Array &p_from) {
|
||||||
|
|
||||||
_p = NULL;
|
_p = NULL;
|
||||||
|
|
|
@ -94,6 +94,8 @@ public:
|
||||||
Variant min() const;
|
Variant min() const;
|
||||||
Variant max() const;
|
Variant max() const;
|
||||||
|
|
||||||
|
const void *id() const;
|
||||||
|
|
||||||
Array(const Array &p_from);
|
Array(const Array &p_from);
|
||||||
Array();
|
Array();
|
||||||
~Array();
|
~Array();
|
||||||
|
|
|
@ -270,6 +270,10 @@ void Dictionary::operator=(const Dictionary &p_dictionary) {
|
||||||
_ref(p_dictionary);
|
_ref(p_dictionary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const void *Dictionary::id() const {
|
||||||
|
return _p->variant_map.id();
|
||||||
|
}
|
||||||
|
|
||||||
Dictionary::Dictionary(const Dictionary &p_from) {
|
Dictionary::Dictionary(const Dictionary &p_from) {
|
||||||
_p = NULL;
|
_p = NULL;
|
||||||
_ref(p_from);
|
_ref(p_from);
|
||||||
|
|
|
@ -82,6 +82,8 @@ public:
|
||||||
|
|
||||||
Dictionary duplicate(bool p_deep = false) const;
|
Dictionary duplicate(bool p_deep = false) const;
|
||||||
|
|
||||||
|
const void *id() const;
|
||||||
|
|
||||||
Dictionary(const Dictionary &p_from);
|
Dictionary(const Dictionary &p_from);
|
||||||
Dictionary();
|
Dictionary();
|
||||||
~Dictionary();
|
~Dictionary();
|
||||||
|
|
|
@ -691,6 +691,10 @@ public:
|
||||||
memdelete_arr(aux_buffer);
|
memdelete_arr(aux_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const void *id() const {
|
||||||
|
return (void *)_data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* copy constructor for the list
|
* copy constructor for the list
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -274,6 +274,10 @@ public:
|
||||||
inline bool empty() const { return list.empty(); }
|
inline bool empty() const { return list.empty(); }
|
||||||
inline int size() const { return list.size(); }
|
inline int size() const { return list.size(); }
|
||||||
|
|
||||||
|
const void *id() const {
|
||||||
|
return list.id();
|
||||||
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
map.clear();
|
map.clear();
|
||||||
list.clear();
|
list.clear();
|
||||||
|
|
|
@ -1415,7 +1415,12 @@ struct _VariantStrPair {
|
||||||
};
|
};
|
||||||
|
|
||||||
Variant::operator String() const {
|
Variant::operator String() const {
|
||||||
|
List<const void *> stack;
|
||||||
|
|
||||||
|
return stringify(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
String Variant::stringify(List<const void *> &stack) const {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
||||||
case NIL: return "Null";
|
case NIL: return "Null";
|
||||||
|
@ -1467,6 +1472,12 @@ Variant::operator String() const {
|
||||||
case DICTIONARY: {
|
case DICTIONARY: {
|
||||||
|
|
||||||
const Dictionary &d = *reinterpret_cast<const Dictionary *>(_data._mem);
|
const Dictionary &d = *reinterpret_cast<const Dictionary *>(_data._mem);
|
||||||
|
if (stack.find(d.id())) {
|
||||||
|
return "{...}";
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.push_back(d.id());
|
||||||
|
|
||||||
//const String *K=NULL;
|
//const String *K=NULL;
|
||||||
String str("{");
|
String str("{");
|
||||||
List<Variant> keys;
|
List<Variant> keys;
|
||||||
|
@ -1477,8 +1488,9 @@ Variant::operator String() const {
|
||||||
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
|
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
|
||||||
|
|
||||||
_VariantStrPair sp;
|
_VariantStrPair sp;
|
||||||
sp.key = String(E->get());
|
sp.key = E->get().stringify(stack);
|
||||||
sp.value = d[E->get()];
|
sp.value = d[E->get()].stringify(stack);
|
||||||
|
|
||||||
pairs.push_back(sp);
|
pairs.push_back(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1561,12 +1573,19 @@ Variant::operator String() const {
|
||||||
case ARRAY: {
|
case ARRAY: {
|
||||||
|
|
||||||
Array arr = operator Array();
|
Array arr = operator Array();
|
||||||
|
if (stack.find(arr.id())) {
|
||||||
|
return "[...]";
|
||||||
|
}
|
||||||
|
stack.push_back(arr.id());
|
||||||
|
|
||||||
String str("[");
|
String str("[");
|
||||||
for (int i = 0; i < arr.size(); i++) {
|
for (int i = 0; i < arr.size(); i++) {
|
||||||
if (i)
|
if (i)
|
||||||
str += ", ";
|
str += ", ";
|
||||||
str += String(arr[i]);
|
|
||||||
};
|
str += arr[i].stringify(stack);
|
||||||
|
}
|
||||||
|
|
||||||
str += "]";
|
str += "]";
|
||||||
return str;
|
return str;
|
||||||
|
|
||||||
|
|
|
@ -401,6 +401,7 @@ public:
|
||||||
|
|
||||||
bool hash_compare(const Variant &p_variant) const;
|
bool hash_compare(const Variant &p_variant) const;
|
||||||
bool booleanize() const;
|
bool booleanize() const;
|
||||||
|
String stringify(List<const void *> &stack) const;
|
||||||
|
|
||||||
void static_assign(const Variant &p_variant);
|
void static_assign(const Variant &p_variant);
|
||||||
static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list);
|
static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list);
|
||||||
|
|
Loading…
Reference in New Issue