From: Michael Friedrich Date: Mon, 17 Aug 2015 11:59:49 +0000 (+0200) Subject: Implement Object#clone and rename Array/Dictionary#clone to shallow_clone X-Git-Tag: v2.4.0~407 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=428be72babe3bd99a1359a2e1427c42603efad4e;p=icinga2 Implement Object#clone and rename Array/Dictionary#clone to shallow_clone fixes #9931 --- 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;