*
* @param index The index.
* @param value The value.
+ * @param overrideFrozen Whether to allow modifying frozen arrays.
*/
-void Array::Set(SizeType index, const Value& value)
+void Array::Set(SizeType index, const Value& value, bool overrideFrozen)
{
ObjectLock olock(this);
- if (m_Frozen)
- BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
+ if (m_Frozen && !overrideFrozen)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Value in array must not be modified."));
m_Data.at(index) = value;
}
*
* @param index The index.
* @param value The value.
+ * @param overrideFrozen Whether to allow modifying frozen arrays.
*/
-void Array::Set(SizeType index, Value&& value)
+void Array::Set(SizeType index, Value&& value, bool overrideFrozen)
{
ObjectLock olock(this);
- if (m_Frozen)
+ if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.at(index).Swap(value);
* Adds a value to the array.
*
* @param value The value.
+ * @param overrideFrozen Whether to allow modifying frozen arrays.
*/
-void Array::Add(Value value)
+void Array::Add(Value value, bool overrideFrozen)
{
ObjectLock olock(this);
- if (m_Frozen)
+ if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.push_back(std::move(value));
*
* @param index The index
* @param value The value to add
+ * @param overrideFrozen Whether to allow modifying frozen arrays.
*/
-void Array::Insert(SizeType index, Value value)
+void Array::Insert(SizeType index, Value value, bool overrideFrozen)
{
ObjectLock olock(this);
ASSERT(index <= m_Data.size());
- if (m_Frozen)
+ if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.insert(m_Data.begin() + index, std::move(value));
* Removes the specified index from the array.
*
* @param index The index.
+ * @param overrideFrozen Whether to allow modifying frozen arrays.
*/
-void Array::Remove(SizeType index)
+void Array::Remove(SizeType index, bool overrideFrozen)
{
ObjectLock olock(this);
- if (m_Frozen)
+ if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.erase(m_Data.begin() + index);
* Removes the item specified by the iterator from the array.
*
* @param it The iterator.
+ * @param overrideFrozen Whether to allow modifying frozen arrays.
*/
-void Array::Remove(Array::Iterator it)
+void Array::Remove(Array::Iterator it, bool overrideFrozen)
{
ASSERT(OwnsLock());
- if (m_Frozen)
+ if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.erase(it);
}
-void Array::Resize(SizeType newSize)
+void Array::Resize(SizeType newSize, bool overrideFrozen)
{
ObjectLock olock(this);
- if (m_Frozen)
+ if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.resize(newSize);
}
-void Array::Clear()
+void Array::Clear(bool overrideFrozen)
{
ObjectLock olock(this);
- if (m_Frozen)
+ if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.clear();
}
-void Array::Reserve(SizeType newSize)
+void Array::Reserve(SizeType newSize, bool overrideFrozen)
{
ObjectLock olock(this);
- if (m_Frozen)
+ if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
m_Data.reserve(newSize);
return result;
}
-void Array::Sort()
+void Array::Sort(bool overrideFrozen)
{
ObjectLock olock(this);
- if (m_Frozen)
+ if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
std::sort(m_Data.begin(), m_Data.end());
return Get(index);
}
-void Array::SetFieldByName(const String& field, const Value& value, const DebugInfo& debugInfo)
+void Array::SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo)
{
ObjectLock olock(this);
BOOST_THROW_EXCEPTION(ScriptError("Array index '" + Convert::ToString(index) + "' is out of bounds.", debugInfo));
if (static_cast<size_t>(index) >= GetLength())
- Resize(index + 1);
+ Resize(index + 1, overrideFrozen);
- Set(index, value);
+ Set(index, value, overrideFrozen);
}
Array::Iterator icinga::begin(const Array::Ptr& x)
Array(std::initializer_list<Value> init);
Value Get(SizeType index) const;
- void Set(SizeType index, const Value& value);
- void Set(SizeType index, Value&& value);
- void Add(Value value);
+ void Set(SizeType index, const Value& value, bool overrideFrozen = false);
+ void Set(SizeType index, Value&& value, bool overrideFrozen = false);
+ void Add(Value value, bool overrideFrozen = false);
Iterator Begin();
Iterator End();
size_t GetLength() const;
bool Contains(const Value& value) const;
- void Insert(SizeType index, Value value);
- void Remove(SizeType index);
- void Remove(Iterator it);
+ void Insert(SizeType index, Value value, bool overrideFrozen = false);
+ void Remove(SizeType index, bool overrideFrozen = false);
+ void Remove(Iterator it, bool overrideFrozen = false);
- void Resize(SizeType newSize);
- void Clear();
+ void Resize(SizeType newSize, bool overrideFrozen = false);
+ void Clear(bool overrideFrozen = false);
- void Reserve(SizeType newSize);
+ void Reserve(SizeType newSize, bool overrideFrozen = false);
void CopyTo(const Array::Ptr& dest) const;
Array::Ptr ShallowClone() const;
Array::Ptr Reverse() const;
- void Sort();
+ void Sort(bool overrideFrozen = false);
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;
+ void SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo) override;
private:
std::vector<Value> m_Data; /**< The data for the array. */
*
* @param key The key.
* @param value The value.
+ * @param overrideFrozen Whether to allow modifying frozen dictionaries.
*/
-void Dictionary::Set(const String& key, Value value)
+void Dictionary::Set(const String& key, Value value, bool overrideFrozen)
{
ObjectLock olock(this);
- if (m_Frozen)
- BOOST_THROW_EXCEPTION(std::invalid_argument("Dictionary must not be modified."));
+ if (m_Frozen && !overrideFrozen)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Value in dictionary must not be modified."));
m_Data[key] = std::move(value);
}
* Removes the item specified by the iterator from the dictionary.
*
* @param it The iterator.
+ * @param overrideFrozen Whether to allow modifying frozen dictionaries.
*/
-void Dictionary::Remove(Dictionary::Iterator it)
+void Dictionary::Remove(Dictionary::Iterator it, bool overrideFrozen)
{
ASSERT(OwnsLock());
- if (m_Frozen)
+ if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Dictionary must not be modified."));
m_Data.erase(it);
* Removes the specified key from the dictionary.
*
* @param key The key.
+ * @param overrideFrozen Whether to allow modifying frozen dictionaries.
*/
-void Dictionary::Remove(const String& key)
+void Dictionary::Remove(const String& key, bool overrideFrozen)
{
ObjectLock olock(this);
- if (m_Frozen)
+ if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Dictionary must not be modified."));
Dictionary::Iterator it;
/**
* Removes all dictionary items.
+ *
+ * @param overrideFrozen Whether to allow modifying frozen dictionaries.
*/
-void Dictionary::Clear()
+void Dictionary::Clear(bool overrideFrozen)
{
ObjectLock olock(this);
- if (m_Frozen)
+ if (m_Frozen && !overrideFrozen)
BOOST_THROW_EXCEPTION(std::invalid_argument("Dictionary must not be modified."));
m_Data.clear();
return GetPrototypeField(const_cast<Dictionary *>(this), field, false, debugInfo);
}
-void Dictionary::SetFieldByName(const String& field, const Value& value, const DebugInfo&)
+void Dictionary::SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo&)
{
- Set(field, value);
+ Set(field, value, overrideFrozen);
}
bool Dictionary::HasOwnField(const String& field) const
Value Get(const String& key) const;
bool Get(const String& key, Value *result) const;
- void Set(const String& key, Value value);
+ void Set(const String& key, Value value, bool overrideFrozen = false);
bool Contains(const String& key) const;
Iterator Begin();
size_t GetLength() const;
- void Remove(const String& key);
+ void Remove(const String& key, bool overrideFrozen = false);
- void Remove(Iterator it);
+ void Remove(Iterator it, bool overrideFrozen = false);
- void Clear();
+ void Clear(bool overrideFrozen = false);
void CopyTo(const Dictionary::Ptr& dest) const;
Dictionary::Ptr ShallowClone() const;
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;
+ void SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo) override;
bool HasOwnField(const String& field) const override;
bool GetOwnField(const String& field, Value *result) const override;
return GetField(fid);
}
-void Object::SetFieldByName(const String& field, const Value& value, const DebugInfo& debugInfo)
+void Object::SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo)
{
Type::Ptr type = GetReflectionType();
virtual void SetField(int id, const Value& value, bool suppress_events = false, const Value& cookie = Empty);
virtual Value GetField(int id) const;
virtual Value GetFieldByName(const String& field, bool sandboxed, const DebugInfo& debugInfo) const;
- virtual void SetFieldByName(const String& field, const Value& value, const DebugInfo& debugInfo);
+ virtual void SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo);
virtual bool HasOwnField(const String& field) const;
virtual bool GetOwnField(const String& field, Value *result) const;
virtual void ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils);
void Reference::Set(const Value& value)
{
- m_Parent->SetFieldByName(m_Index, value, DebugInfo());
+ m_Parent->SetFieldByName(m_Index, value, false, DebugInfo());
}
Object::Ptr Reference::GetParent() const
}
}
- VMOps::SetField(parent, index, operand2.GetValue(), m_DebugInfo);
+ VMOps::SetField(parent, index, operand2.GetValue(), m_OverrideFrozen, m_DebugInfo);
if (psdhint) {
psdhint->AddMessage("=", m_DebugInfo);
return Empty;
}
+void SetExpression::SetOverrideFrozen()
+{
+ m_OverrideFrozen = true;
+}
+
ExpressionResult ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
Value old_value = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo());
if (old_value.IsEmpty() && !old_value.IsString())
- VMOps::SetField(vparent, vindex, new Dictionary(), m_Operand1->GetDebugInfo());
+ VMOps::SetField(vparent, vindex, new Dictionary(), m_OverrideFrozen, m_Operand1->GetDebugInfo());
}
*parent = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_DebugInfo);
return true;
}
+void IndexerExpression::SetOverrideFrozen()
+{
+ m_OverrideFrozen = true;
+}
+
void icinga::BindToScope(std::unique_ptr<Expression>& expr, ScopeSpecifier scopeSpec)
{
auto *dexpr = dynamic_cast<DictExpression *>(expr.get());
: BinaryExpression(std::move(operand1), std::move(operand2), debugInfo), m_Op(op)
{ }
+ void SetOverrideFrozen();
+
protected:
ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
private:
CombinedSetOp m_Op;
+ bool m_OverrideFrozen{false};
friend void BindToScope(std::unique_ptr<Expression>& expr, ScopeSpecifier scopeSpec);
};
: BinaryExpression(std::move(operand1), std::move(operand2), debugInfo)
{ }
+ void SetOverrideFrozen();
+
protected:
+ bool m_OverrideFrozen{false};
+
ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const override;
return object->GetFieldByName(field, sandboxed, debugInfo);
}
- static inline void SetField(const Object::Ptr& context, const String& field, const Value& value, const DebugInfo& debugInfo = DebugInfo())
+ static inline void SetField(const Object::Ptr& context, const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo = DebugInfo())
{
if (!context)
BOOST_THROW_EXCEPTION(ScriptError("Cannot set field '" + field + "' on a value that is not an object.", debugInfo));
- return context->SetFieldByName(field, value, debugInfo);
+ return context->SetFieldByName(field, value, overrideFrozen, debugInfo);
}
private: