1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
3 #include "base/array.hpp"
4 #include "base/objectlock.hpp"
5 #include "base/debug.hpp"
6 #include "base/primitivetype.hpp"
7 #include "base/dictionary.hpp"
8 #include "base/configwriter.hpp"
9 #include "base/convert.hpp"
10 #include "base/exception.hpp"
12 using namespace icinga;
14 template class std::vector<Value>;
16 REGISTER_PRIMITIVE_TYPE(Array, Object, Array::GetPrototype());
18 Array::Array(const ArrayData& other)
22 Array::Array(ArrayData&& other)
23 : m_Data(std::move(other))
26 Array::Array(std::initializer_list<Value> init)
31 * Restrieves a value from an array.
33 * @param index The index.
36 Value Array::Get(SizeType index) const
38 ObjectLock olock(this);
40 return m_Data.at(index);
44 * Sets a value in the array.
46 * @param index The index.
47 * @param value The value.
48 * @param overrideFrozen Whether to allow modifying frozen arrays.
50 void Array::Set(SizeType index, const Value& value, bool overrideFrozen)
52 ObjectLock olock(this);
54 if (m_Frozen && !overrideFrozen)
55 BOOST_THROW_EXCEPTION(std::invalid_argument("Value in array must not be modified."));
57 m_Data.at(index) = value;
61 * Sets a value in the array.
63 * @param index The index.
64 * @param value The value.
65 * @param overrideFrozen Whether to allow modifying frozen arrays.
67 void Array::Set(SizeType index, Value&& value, bool overrideFrozen)
69 ObjectLock olock(this);
71 if (m_Frozen && !overrideFrozen)
72 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
74 m_Data.at(index).Swap(value);
78 * Adds a value to the array.
80 * @param value The value.
81 * @param overrideFrozen Whether to allow modifying frozen arrays.
83 void Array::Add(Value value, bool overrideFrozen)
85 ObjectLock olock(this);
87 if (m_Frozen && !overrideFrozen)
88 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
90 m_Data.push_back(std::move(value));
94 * Returns an iterator to the beginning of the array.
96 * Note: Caller must hold the object lock while using the iterator.
98 * @returns An iterator.
100 Array::Iterator Array::Begin()
104 return m_Data.begin();
108 * Returns an iterator to the end of the array.
110 * Note: Caller must hold the object lock while using the iterator.
112 * @returns An iterator.
114 Array::Iterator Array::End()
122 * Returns the number of elements in the array.
124 * @returns Number of elements.
126 size_t Array::GetLength() const
128 ObjectLock olock(this);
130 return m_Data.size();
134 * Checks whether the array contains the specified value.
136 * @param value The value.
137 * @returns true if the array contains the value, false otherwise.
139 bool Array::Contains(const Value& value) const
141 ObjectLock olock(this);
143 return (std::find(m_Data.begin(), m_Data.end(), value) != m_Data.end());
147 * Insert the given value at the specified index
149 * @param index The index
150 * @param value The value to add
151 * @param overrideFrozen Whether to allow modifying frozen arrays.
153 void Array::Insert(SizeType index, Value value, bool overrideFrozen)
155 ObjectLock olock(this);
157 ASSERT(index <= m_Data.size());
159 if (m_Frozen && !overrideFrozen)
160 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
162 m_Data.insert(m_Data.begin() + index, std::move(value));
166 * Removes the specified index from the array.
168 * @param index The index.
169 * @param overrideFrozen Whether to allow modifying frozen arrays.
171 void Array::Remove(SizeType index, bool overrideFrozen)
173 ObjectLock olock(this);
175 if (m_Frozen && !overrideFrozen)
176 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
178 m_Data.erase(m_Data.begin() + index);
182 * Removes the item specified by the iterator from the array.
184 * @param it The iterator.
185 * @param overrideFrozen Whether to allow modifying frozen arrays.
187 void Array::Remove(Array::Iterator it, bool overrideFrozen)
191 if (m_Frozen && !overrideFrozen)
192 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
197 void Array::Resize(SizeType newSize, bool overrideFrozen)
199 ObjectLock olock(this);
201 if (m_Frozen && !overrideFrozen)
202 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
204 m_Data.resize(newSize);
207 void Array::Clear(bool overrideFrozen)
209 ObjectLock olock(this);
211 if (m_Frozen && !overrideFrozen)
212 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
217 void Array::Reserve(SizeType newSize, bool overrideFrozen)
219 ObjectLock olock(this);
221 if (m_Frozen && !overrideFrozen)
222 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
224 m_Data.reserve(newSize);
227 void Array::CopyTo(const Array::Ptr& dest) const
229 ObjectLock olock(this);
230 ObjectLock xlock(dest);
233 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
235 std::copy(m_Data.begin(), m_Data.end(), std::back_inserter(dest->m_Data));
239 * Makes a shallow copy of an array.
241 * @returns a copy of the array.
243 Array::Ptr Array::ShallowClone() const
245 Array::Ptr clone = new Array();
251 * Makes a deep clone of an array
254 * @returns a copy of the array.
256 Object::Ptr Array::Clone() const
260 ObjectLock olock(this);
261 for (const Value& val : m_Data) {
262 arr.push_back(val.Clone());
265 return new Array(std::move(arr));
268 Array::Ptr Array::Reverse() const
270 Array::Ptr result = new Array();
272 ObjectLock olock(this);
273 ObjectLock xlock(result);
275 std::copy(m_Data.rbegin(), m_Data.rend(), std::back_inserter(result->m_Data));
280 void Array::Sort(bool overrideFrozen)
282 ObjectLock olock(this);
284 if (m_Frozen && !overrideFrozen)
285 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
287 std::sort(m_Data.begin(), m_Data.end());
290 String Array::ToString() const
292 std::ostringstream msgbuf;
293 ConfigWriter::EmitArray(msgbuf, 1, const_cast<Array *>(this));
297 Array::Ptr Array::Unique() const
299 std::set<Value> result;
301 ObjectLock olock(this);
303 for (const Value& item : m_Data) {
307 return Array::FromSet(result);
312 ObjectLock olock(this);
316 Value Array::GetFieldByName(const String& field, bool sandboxed, const DebugInfo& debugInfo) const
321 index = Convert::ToLong(field);
323 return Object::GetFieldByName(field, sandboxed, debugInfo);
326 ObjectLock olock(this);
328 if (index < 0 || static_cast<size_t>(index) >= GetLength())
329 BOOST_THROW_EXCEPTION(ScriptError("Array index '" + Convert::ToString(index) + "' is out of bounds.", debugInfo));
334 void Array::SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo)
336 ObjectLock olock(this);
338 int index = Convert::ToLong(field);
341 BOOST_THROW_EXCEPTION(ScriptError("Array index '" + Convert::ToString(index) + "' is out of bounds.", debugInfo));
343 if (static_cast<size_t>(index) >= GetLength())
344 Resize(index + 1, overrideFrozen);
346 Set(index, value, overrideFrozen);
349 Array::Iterator icinga::begin(const Array::Ptr& x)
354 Array::Iterator icinga::end(const Array::Ptr& x)