diff --git a/lib/base/namespace.cpp b/lib/base/namespace.cpp index 33cca7d6a..001fa33d1 100644 --- a/lib/base/namespace.cpp +++ b/lib/base/namespace.cpp @@ -48,6 +48,18 @@ void Namespace::Set(const String& field, const Value& value, bool overrideFrozen return SetFieldByName(field, value, overrideFrozen, DebugInfo()); } +/** + * Returns the number of elements in the namespace. + * + * @returns Number of elements. + */ +size_t Namespace::GetLength() const +{ + ObjectLock olock(this); + + return m_Data.size(); +} + bool Namespace::Contains(const String& field) const { ObjectLock olock(this); diff --git a/lib/base/namespace.hpp b/lib/base/namespace.hpp index 310dba7b0..6a53cb17d 100644 --- a/lib/base/namespace.hpp +++ b/lib/base/namespace.hpp @@ -88,6 +88,8 @@ public: Iterator Begin(); Iterator End(); + size_t GetLength() const; + Value GetFieldByName(const String& field, bool sandboxed, const DebugInfo& debugInfo) const override; void SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo) override; bool HasOwnField(const String& field) const override; diff --git a/lib/base/serializer.cpp b/lib/base/serializer.cpp index c081c440d..dc6069e97 100644 --- a/lib/base/serializer.cpp +++ b/lib/base/serializer.cpp @@ -9,6 +9,7 @@ #include "base/namespace.hpp" #include #include +#include using namespace icinga; @@ -64,13 +65,15 @@ struct SerializeStack } }; -static Value SerializeInternal(const Value& value, int attributeTypes, SerializeStack& stack); +static Value SerializeInternal(const Value& value, int attributeTypes, SerializeStack& stack, bool dryRun); -static Array::Ptr SerializeArray(const Array::Ptr& input, int attributeTypes, SerializeStack& stack) +static Array::Ptr SerializeArray(const Array::Ptr& input, int attributeTypes, SerializeStack& stack, bool dryRun) { ArrayData result; - result.reserve(input->GetLength()); + if (!dryRun) { + result.reserve(input->GetLength()); + } ObjectLock olock(input); @@ -78,48 +81,72 @@ static Array::Ptr SerializeArray(const Array::Ptr& input, int attributeTypes, Se for (const Value& value : input) { stack.Push(Convert::ToString(index), value); - result.emplace_back(SerializeInternal(value, attributeTypes, stack)); + + auto serialized (SerializeInternal(value, attributeTypes, stack, dryRun)); + + if (!dryRun) { + result.emplace_back(std::move(serialized)); + } + stack.Pop(); index++; } - return new Array(std::move(result)); + return dryRun ? nullptr : new Array(std::move(result)); } -static Dictionary::Ptr SerializeDictionary(const Dictionary::Ptr& input, int attributeTypes, SerializeStack& stack) +static Dictionary::Ptr SerializeDictionary(const Dictionary::Ptr& input, int attributeTypes, SerializeStack& stack, bool dryRun) { DictionaryData result; - result.reserve(input->GetLength()); + if (!dryRun) { + result.reserve(input->GetLength()); + } ObjectLock olock(input); for (const Dictionary::Pair& kv : input) { stack.Push(kv.first, kv.second); - result.emplace_back(kv.first, SerializeInternal(kv.second, attributeTypes, stack)); + + auto serialized (SerializeInternal(kv.second, attributeTypes, stack, dryRun)); + + if (!dryRun) { + result.emplace_back(kv.first, std::move(serialized)); + } + stack.Pop(); } - return new Dictionary(std::move(result)); + return dryRun ? nullptr : new Dictionary(std::move(result)); } -static Dictionary::Ptr SerializeNamespace(const Namespace::Ptr& input, int attributeTypes, SerializeStack& stack) +static Dictionary::Ptr SerializeNamespace(const Namespace::Ptr& input, int attributeTypes, SerializeStack& stack, bool dryRun) { DictionaryData result; + if (!dryRun) { + result.reserve(input->GetLength()); + } + ObjectLock olock(input); for (const Namespace::Pair& kv : input) { Value val = kv.second->Get(); stack.Push(kv.first, val); - result.emplace_back(kv.first, Serialize(val, attributeTypes)); + + auto serialized (SerializeInternal(val, attributeTypes, stack, dryRun)); + + if (!dryRun) { + result.emplace_back(kv.first, std::move(serialized)); + } + stack.Pop(); } - return new Dictionary(std::move(result)); + return dryRun ? nullptr : new Dictionary(std::move(result)); } -static Object::Ptr SerializeObject(const Object::Ptr& input, int attributeTypes, SerializeStack& stack) +static Object::Ptr SerializeObject(const Object::Ptr& input, int attributeTypes, SerializeStack& stack, bool dryRun) { Type::Ptr type = input->GetReflectionType(); @@ -127,7 +154,10 @@ static Object::Ptr SerializeObject(const Object::Ptr& input, int attributeTypes, return nullptr; DictionaryData fields; - fields.reserve(type->GetFieldCount() + 1); + + if (!dryRun) { + fields.reserve(type->GetFieldCount() + 1); + } ObjectLock olock(input); @@ -142,13 +172,21 @@ static Object::Ptr SerializeObject(const Object::Ptr& input, int attributeTypes, Value value = input->GetField(i); stack.Push(field.Name, value); - fields.emplace_back(field.Name, SerializeInternal(value, attributeTypes, stack)); + + auto serialized (SerializeInternal(value, attributeTypes, stack, dryRun)); + + if (!dryRun) { + fields.emplace_back(field.Name, std::move(serialized)); + } + stack.Pop(); } - fields.emplace_back("type", type->GetName()); + if (!dryRun) { + fields.emplace_back("type", type->GetName()); + } - return new Dictionary(std::move(fields)); + return dryRun ? nullptr : new Dictionary(std::move(fields)); } static Array::Ptr DeserializeArray(const Array::Ptr& input, bool safe_mode, int attributeTypes) @@ -228,35 +266,35 @@ static Object::Ptr DeserializeObject(const Object::Ptr& object, const Dictionary return instance; } -static Value SerializeInternal(const Value& value, int attributeTypes, SerializeStack& stack) +static Value SerializeInternal(const Value& value, int attributeTypes, SerializeStack& stack, bool dryRun) { if (!value.IsObject()) - return value; + return dryRun ? Empty : value; Object::Ptr input = value; Array::Ptr array = dynamic_pointer_cast(input); if (array) - return SerializeArray(array, attributeTypes, stack); + return SerializeArray(array, attributeTypes, stack, dryRun); Dictionary::Ptr dict = dynamic_pointer_cast(input); if (dict) - return SerializeDictionary(dict, attributeTypes, stack); + return SerializeDictionary(dict, attributeTypes, stack, dryRun); Namespace::Ptr ns = dynamic_pointer_cast(input); if (ns) - return SerializeNamespace(ns, attributeTypes, stack); + return SerializeNamespace(ns, attributeTypes, stack, dryRun); - return SerializeObject(input, attributeTypes, stack); + return SerializeObject(input, attributeTypes, stack, dryRun); } Value icinga::Serialize(const Value& value, int attributeTypes) { SerializeStack stack; - return SerializeInternal(value, attributeTypes, stack); + return SerializeInternal(value, attributeTypes, stack, false); } Value icinga::Deserialize(const Value& value, bool safe_mode, int attributeTypes)