diff --git a/doc/20-library-reference.md b/doc/20-library-reference.md
index 22e695040..dca6294cd 100644
--- a/doc/20-library-reference.md
+++ b/doc/20-library-reference.md
@@ -514,9 +514,9 @@ Signature:
Removes all elements from the array.
-### Array#clone
+### 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.
## Dictionary type
-### Dictionary#clone
+### 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.
diff --git a/lib/base/array-script.cpp b/lib/base/array-script.cpp
index 2efde98b6..e80042aad 100644
--- a/lib/base/array-script.cpp
+++ b/lib/base/array-script.cpp
@@ -101,7 +101,7 @@ static Array::Ptr ArraySort(const std::vector& args)
return arr;
}
-static Array::Ptr ArrayClone(void)
+static Array::Ptr ArrayShallowClone(void)
{
ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
Array::Ptr self = static_cast(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));
}
diff --git a/lib/base/array.cpp b/lib/base/array.cpp
index 4365b3dd8..399d442b8 100644
--- a/lib/base/array.cpp
+++ b/lib/base/array.cpp
@@ -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;
+}
+
diff --git a/lib/base/array.hpp b/lib/base/array.hpp
index b224fba31..88eb3fdde 100644
--- a/lib/base/array.hpp
+++ b/lib/base/array.hpp
@@ -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 m_Data; /**< The data for the array. */
diff --git a/lib/base/dictionary-script.cpp b/lib/base/dictionary-script.cpp
index 8636783a1..2fedf4b31 100644
--- a/lib/base/dictionary-script.cpp
+++ b/lib/base/dictionary-script.cpp
@@ -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(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));
}
diff --git a/lib/base/dictionary.cpp b/lib/base/dictionary.cpp
index 33d043b6d..c4b9d2e45 100644
--- a/lib/base/dictionary.cpp
+++ b/lib/base/dictionary.cpp
@@ -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.
diff --git a/lib/base/dictionary.hpp b/lib/base/dictionary.hpp
index 6a39f44a2..152956ac1 100644
--- a/lib/base/dictionary.hpp
+++ b/lib/base/dictionary.hpp
@@ -112,6 +112,8 @@ public:
std::vector GetKeys(void) const;
static Object::Ptr GetPrototype(void);
+
+ virtual Object::Ptr Clone(void) const;
private:
std::map m_Data; /**< The data for the dictionary. */
diff --git a/lib/base/object-script.cpp b/lib/base/object-script.cpp
index 0a2440894..1ed5eaec5 100644
--- a/lib/base/object-script.cpp
+++ b/lib/base/object-script.cpp
@@ -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(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;
diff --git a/lib/base/object.cpp b/lib/base/object.cpp
index 1eff59e21..062cb9c77 100644
--- a/lib/base/object.cpp
+++ b/lib/base/object.cpp
@@ -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."));
+}
diff --git a/lib/base/object.hpp b/lib/base/object.hpp
index 3b8f41b1d..7d4f2a358 100644
--- a/lib/base/object.hpp
+++ b/lib/base/object.hpp
@@ -111,6 +111,8 @@ public:
void InflateMutex(void);
static Object::Ptr GetPrototype(void);
+
+ virtual Object::Ptr Clone(void) const;
private:
Object(const Object& other);
diff --git a/lib/base/value.cpp b/lib/base/value.cpp
index 549c5cc54..99d679865 100644
--- a/lib/base/value.cpp
+++ b/lib/base/value.cpp
@@ -104,3 +104,11 @@ Type::Ptr Value::GetReflectionType(void) const
}
}
+Value Value::Clone(void) const
+{
+ if (IsObject())
+ return static_cast(*this)->Clone();
+ else
+ return *this;
+}
+
diff --git a/lib/base/value.hpp b/lib/base/value.hpp
index b2e12cc2c..ad75dcf59 100644
--- a/lib/base/value.hpp
+++ b/lib/base/value.hpp
@@ -234,6 +234,8 @@ public:
String GetTypeName(void) const;
Type::Ptr GetReflectionType(void) const;
+
+ Value Clone(void) const;
private:
boost::variant m_Value;