]> granicus.if.org Git - icinga2/commitdiff
Implement support for frozen arrays and dictionaries 6044/head
authorGunnar Beutner <gunnar.beutner@icinga.com>
Tue, 30 Jan 2018 11:19:34 +0000 (12:19 +0100)
committerGunnar Beutner <gunnar.beutner@icinga.com>
Tue, 30 Jan 2018 11:22:04 +0000 (12:22 +0100)
doc/18-library-reference.md
lib/base/array-script.cpp
lib/base/array.cpp
lib/base/array.hpp
lib/base/dictionary-script.cpp
lib/base/dictionary.cpp
lib/base/dictionary.hpp

index 758e404070df627885916b745e12f29f16616715..fcef4597bdf1ef59c1ab2454625822b7dc562be2 100644 (file)
@@ -1260,6 +1260,14 @@ Signature:
 
 Returns true if the array contains the specified value, false otherwise.
 
+### Array#freeze <a id="array-freeze"></a>
+
+Signature:
+
+    function freeze()
+
+Disallows further modifications to this array. Trying to modify the array will result in an exception.
+
 ### Array#len <a id="array-len"></a>
 
 Signature:
@@ -1395,6 +1403,14 @@ Signature:
 
 Returns true if a dictionary item with the specified `key` exists, false otherwise.
 
+### Dictionary#freeze <a id="dictionary-freeze"></a>
+
+Signature:
+
+    function freeze()
+
+Disallows further modifications to this dictionary. Trying to modify the dictionary will result in an exception.
+
 ### Dictionary#len <a id="dictionary-len"></a>
 
 Signature:
index 3f7278ff6ba9bfe1e018051c2d9f8ed1a4072699..3a59b7fb8519b624d824b97e63531bca676217c6 100644 (file)
@@ -245,6 +245,13 @@ static Array::Ptr ArrayUnique()
        return Array::FromSet(result);
 }
 
+static void ArrayFreeze()
+{
+       ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
+       Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
+       self->Freeze();
+}
+
 Object::Ptr Array::GetPrototype()
 {
        static Dictionary::Ptr prototype = new Dictionary({
@@ -264,7 +271,8 @@ Object::Ptr Array::GetPrototype()
                { "filter", new Function("Array#filter", ArrayFilter, { "func" }, true) },
                { "any", new Function("Array#any", ArrayAny, { "func" }, true) },
                { "all", new Function("Array#all", ArrayAll, { "func" }, true) },
-               { "unique", new Function("Array#unique", ArrayUnique, {}, true) }
+               { "unique", new Function("Array#unique", ArrayUnique, {}, true) },
+               { "freeze", new Function("Array#freeze", ArrayFreeze, {}) }
        });
 
        return prototype;
index d6e8ee03e11e7d34ec954f47f25680e4e6c51708..ac2ade93e080af6efc129b9a35774f3178146a7c 100644 (file)
@@ -67,6 +67,9 @@ void Array::Set(SizeType index, const Value& value)
 {
        ObjectLock olock(this);
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
+
        m_Data.at(index) = value;
 }
 
@@ -80,6 +83,9 @@ void Array::Set(SizeType index, Value&& value)
 {
        ObjectLock olock(this);
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
+
        m_Data.at(index).Swap(value);
 }
 
@@ -92,6 +98,9 @@ void Array::Add(Value value)
 {
        ObjectLock olock(this);
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
+
        m_Data.push_back(std::move(value));
 }
 
@@ -160,6 +169,9 @@ void Array::Insert(SizeType index, Value value)
 
        ASSERT(index <= m_Data.size());
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
+
        m_Data.insert(m_Data.begin() + index, std::move(value));
 }
 
@@ -172,6 +184,9 @@ void Array::Remove(SizeType index)
 {
        ObjectLock olock(this);
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
+
        m_Data.erase(m_Data.begin() + index);
 }
 
@@ -184,6 +199,9 @@ void Array::Remove(Array::Iterator it)
 {
        ASSERT(OwnsLock());
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
+
        m_Data.erase(it);
 }
 
@@ -191,6 +209,9 @@ void Array::Resize(SizeType newSize)
 {
        ObjectLock olock(this);
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
+
        m_Data.resize(newSize);
 }
 
@@ -198,6 +219,9 @@ void Array::Clear()
 {
        ObjectLock olock(this);
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
+
        m_Data.clear();
 }
 
@@ -205,6 +229,9 @@ void Array::Reserve(SizeType newSize)
 {
        ObjectLock olock(this);
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
+
        m_Data.reserve(newSize);
 }
 
@@ -213,6 +240,9 @@ void Array::CopyTo(const Array::Ptr& dest) const
        ObjectLock olock(this);
        ObjectLock xlock(dest);
 
+       if (dest->m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
+
        std::copy(m_Data.begin(), m_Data.end(), std::back_inserter(dest->m_Data));
 }
 
@@ -261,6 +291,10 @@ Array::Ptr Array::Reverse() const
 void Array::Sort()
 {
        ObjectLock olock(this);
+
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
+
        std::sort(m_Data.begin(), m_Data.end());
 }
 
@@ -271,6 +305,12 @@ String Array::ToString() const
        return msgbuf.str();
 }
 
+void Array::Freeze()
+{
+       ObjectLock olock(this);
+       m_Frozen = true;
+}
+
 Value Array::GetFieldByName(const String& field, bool sandboxed, const DebugInfo& debugInfo) const
 {
        int index;
index 6fd1abae5a361ef84cc0be66ebb13dffcdb0cec7..768cee131a89e3c1021616863e82ac5a3fbfc064 100644 (file)
@@ -112,11 +112,14 @@ public:
 
        String ToString() const override;
 
+       void Freeze();
+
        Value GetFieldByName(const String& field, bool sandboxed, const DebugInfo& debugInfo) const override;
        void SetFieldByName(const String& field, const Value& value, const DebugInfo& debugInfo) override;
 
 private:
        std::vector<Value> m_Data; /**< The data for the array. */
+       bool m_Frozen{false};
 };
 
 Array::Iterator begin(const Array::Ptr& x);
index a45afa826260959e94e31f00fa8fb5a25df67fb9..547f814b1000e42fcda63d11c9d329606a71120b 100644 (file)
@@ -91,6 +91,13 @@ static Array::Ptr DictionaryValues()
        return new Array(std::move(values));
 }
 
+static void DictionaryFreeze()
+{
+       ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
+       Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self);
+       self->Freeze();
+}
+
 Object::Ptr Dictionary::GetPrototype()
 {
        static Dictionary::Ptr prototype = new Dictionary({
@@ -101,7 +108,8 @@ Object::Ptr Dictionary::GetPrototype()
                { "contains", new Function("Dictionary#contains", DictionaryContains, { "key" }, true) },
                { "shallow_clone", new Function("Dictionary#shallow_clone", DictionaryShallowClone, {}, true) },
                { "keys", new Function("Dictionary#keys", DictionaryKeys, {}, true) },
-               { "values", new Function("Dictionary#values", DictionaryValues, {}, true) }
+               { "values", new Function("Dictionary#values", DictionaryValues, {}, true) },
+               { "freeze", new Function("Dictionary#freeze", DictionaryFreeze, {}) }
        });
 
        return prototype;
index 50fb5d7507caf4c1e952bfa1b68f8fde51a081e6..a645404044ce94f1a21c61918928bdc9fccf7a4a 100644 (file)
@@ -94,6 +94,9 @@ void Dictionary::Set(const String& key, Value value)
 {
        ObjectLock olock(this);
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Dictionary must not be modified."));
+
        m_Data[key] = std::move(value);
 }
 
@@ -159,6 +162,9 @@ void Dictionary::Remove(Dictionary::Iterator it)
 {
        ASSERT(OwnsLock());
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Dictionary must not be modified."));
+
        m_Data.erase(it);
 }
 
@@ -171,6 +177,9 @@ void Dictionary::Remove(const String& key)
 {
        ObjectLock olock(this);
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Dictionary must not be modified."));
+
        Dictionary::Iterator it;
        it = m_Data.find(key);
 
@@ -187,6 +196,9 @@ void Dictionary::Clear()
 {
        ObjectLock olock(this);
 
+       if (m_Frozen)
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Dictionary must not be modified."));
+
        m_Data.clear();
 }
 
@@ -260,6 +272,12 @@ String Dictionary::ToString() const
        return msgbuf.str();
 }
 
+void Dictionary::Freeze()
+{
+       ObjectLock olock(this);
+       m_Frozen = true;
+}
+
 Value Dictionary::GetFieldByName(const String& field, bool, const DebugInfo& debugInfo) const
 {
        Value value;
index 7854573a6f01a2e474c8ae629ca47c6e278bbf68..97ca81b78513082e53fa8e9cace638fcc15d2fe1 100644 (file)
@@ -83,6 +83,8 @@ public:
 
        String ToString() const override;
 
+       void Freeze();
+
        Value GetFieldByName(const String& field, bool sandboxed, const DebugInfo& debugInfo) const override;
        void SetFieldByName(const String& field, const Value& value, const DebugInfo& debugInfo) override;
        bool HasOwnField(const String& field) const override;
@@ -90,6 +92,7 @@ public:
 
 private:
        std::map<String, Value> m_Data; /**< The data for the dictionary. */
+       bool m_Frozen{false};
 };
 
 Dictionary::Iterator begin(const Dictionary::Ptr& x);