Implement Object#clone and rename Array/Dictionary#clone to shallow_clone

fixes #9931
This commit is contained in:
Michael Friedrich 2015-08-17 13:59:49 +02:00
parent 7d6a920b3d
commit 428be72bab
12 changed files with 73 additions and 8 deletions

View File

@ -514,9 +514,9 @@ Signature:
Removes all elements from the array.
### <a id="array-clone"></a> Array#clone
### <a id="array-shallow-clone"></a> Array#shallow_clone
function clone();
function shallow_clone();
Returns a copy of the array. Note that for elements which are reference values (e.g. objects such
as arrays and dictionaries) only the references are copied.
@ -582,11 +582,11 @@ Joins all elements of the array using the specified separator.
## <a id="dictionary-type"></a> Dictionary type
### <a id="dictionary-clone"></a> Dictionary#clone
### <a id="dictionary-shallow-clone"></a> Dictionary#shallow_clone
Signature:
function clone();
function shallow_clone();
Returns a copy of the dictionary. Note that for elements which are reference values (e.g. objects such
as arrays and dictionaries) only the references are copied.

View File

@ -101,7 +101,7 @@ static Array::Ptr ArraySort(const std::vector<Value>& args)
return arr;
}
static Array::Ptr ArrayClone(void)
static Array::Ptr ArrayShallowClone(void)
{
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
@ -144,7 +144,7 @@ Object::Ptr Array::GetPrototype(void)
prototype->Set("contains", new Function(WrapFunction(ArrayContains), true));
prototype->Set("clear", new Function(WrapFunction(ArrayClear)));
prototype->Set("sort", new Function(WrapFunction(ArraySort), true));
prototype->Set("clone", new Function(WrapFunction(ArrayClone), true));
prototype->Set("shallow_clone", new Function(WrapFunction(ArrayShallowClone), true));
prototype->Set("join", new Function(WrapFunction(ArrayJoin), true));
}

View File

@ -182,3 +182,21 @@ Array::Ptr Array::ShallowClone(void) const
return clone;
}
/**
* Makes a deep clone of an array
* and its elements.
*
* @returns a copy of the array.
*/
Object::Ptr Array::Clone(void) const
{
Array::Ptr arr = new Array();
ObjectLock olock(this);
BOOST_FOREACH(const Value& val, m_Data) {
arr->Add(val.Clone());
}
return arr;
}

View File

@ -109,6 +109,8 @@ public:
std::copy(v.begin(), v.end(), std::back_inserter(result->m_Data));
return result;
}
virtual Object::Ptr Clone(void) const;
private:
std::vector<Value> m_Data; /**< The data for the array. */

View File

@ -61,7 +61,7 @@ static bool DictionaryContains(const String& key)
return self->Contains(key);
}
static Dictionary::Ptr DictionaryClone(void)
static Dictionary::Ptr DictionaryShallowClone(void)
{
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self);
@ -91,7 +91,7 @@ Object::Ptr Dictionary::GetPrototype(void)
prototype->Set("get", new Function(WrapFunction(DictionaryGet)));
prototype->Set("remove", new Function(WrapFunction(DictionaryRemove)));
prototype->Set("contains", new Function(WrapFunction(DictionaryContains), true));
prototype->Set("clone", new Function(WrapFunction(DictionaryClone), true));
prototype->Set("shallow_clone", new Function(WrapFunction(DictionaryShallowClone), true));
prototype->Set("keys", new Function(WrapFunction(DictionaryKeys), true));
}

View File

@ -164,6 +164,24 @@ Dictionary::Ptr Dictionary::ShallowClone(void) const
return clone;
}
/**
* Makes a deep clone of a dictionary
* and its elements.
*
* @returns a copy of the dictionary.
*/
Object::Ptr Dictionary::Clone(void) const
{
Dictionary::Ptr dict = new Dictionary();
ObjectLock olock(this);
BOOST_FOREACH(const Dictionary::Pair& kv, m_Data) {
dict->Set(kv.first, kv.second.Clone());
}
return dict;
}
/**
* Returns an array containing all keys
* which are currently set in this directory.

View File

@ -112,6 +112,8 @@ public:
std::vector<String> GetKeys(void) const;
static Object::Ptr GetPrototype(void);
virtual Object::Ptr Clone(void) const;
private:
std::map<String, Value> m_Data; /**< The data for the dictionary. */

View File

@ -39,6 +39,13 @@ static void ObjectNotifyAttribute(const String& attribute)
self->NotifyField(self->GetReflectionType()->GetFieldId(attribute));
}
static Object::Ptr ObjectClone(void)
{
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
Object::Ptr self = static_cast<Object::Ptr>(vframe->Self);
return self->Clone();
}
Object::Ptr Object::GetPrototype(void)
{
static Dictionary::Ptr prototype;
@ -47,6 +54,7 @@ Object::Ptr Object::GetPrototype(void)
prototype = new Dictionary();
prototype->Set("to_string", new Function(WrapFunction(ObjectToString), true));
prototype->Set("notify_attribute", new Function(WrapFunction(ObjectNotifyAttribute), false));
prototype->Set("clone", new Function(WrapFunction(ObjectClone), true));
}
return prototype;

View File

@ -101,3 +101,8 @@ void Object::NotifyField(int id, const Value& cookie)
{
BOOST_THROW_EXCEPTION(std::runtime_error("Invalid field ID."));
}
Object::Ptr Object::Clone(void) const
{
BOOST_THROW_EXCEPTION(std::runtime_error("Object cannot be cloned."));
}

View File

@ -111,6 +111,8 @@ public:
void InflateMutex(void);
static Object::Ptr GetPrototype(void);
virtual Object::Ptr Clone(void) const;
private:
Object(const Object& other);

View File

@ -104,3 +104,11 @@ Type::Ptr Value::GetReflectionType(void) const
}
}
Value Value::Clone(void) const
{
if (IsObject())
return static_cast<Object::Ptr>(*this)->Clone();
else
return *this;
}

View File

@ -234,6 +234,8 @@ public:
String GetTypeName(void) const;
Type::Ptr GetReflectionType(void) const;
Value Clone(void) const;
private:
boost::variant<boost::blank, double, bool, String, Object::Ptr> m_Value;