1 /******************************************************************************
3 * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License *
7 * as published by the Free Software Foundation; either version 2 *
8 * of the License, or (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software Foundation *
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ******************************************************************************/
20 #include "base/array.hpp"
21 #include "base/objectlock.hpp"
22 #include "base/debug.hpp"
23 #include "base/primitivetype.hpp"
24 #include "base/dictionary.hpp"
25 #include "base/configwriter.hpp"
26 #include "base/convert.hpp"
27 #include "base/exception.hpp"
29 using namespace icinga;
31 template class std::vector<Value>;
33 REGISTER_PRIMITIVE_TYPE(Array, Object, Array::GetPrototype());
35 Array::Array(const ArrayData& other)
39 Array::Array(ArrayData&& other)
40 : m_Data(std::move(other))
43 Array::Array(std::initializer_list<Value> init)
48 * Restrieves a value from an array.
50 * @param index The index.
53 Value Array::Get(SizeType index) const
55 ObjectLock olock(this);
57 return m_Data.at(index);
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, const Value& value, bool overrideFrozen)
69 ObjectLock olock(this);
71 if (m_Frozen && !overrideFrozen)
72 BOOST_THROW_EXCEPTION(std::invalid_argument("Value in array must not be modified."));
74 m_Data.at(index) = value;
78 * Sets a value in the array.
80 * @param index The index.
81 * @param value The value.
82 * @param overrideFrozen Whether to allow modifying frozen arrays.
84 void Array::Set(SizeType index, Value&& value, bool overrideFrozen)
86 ObjectLock olock(this);
88 if (m_Frozen && !overrideFrozen)
89 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
91 m_Data.at(index).Swap(value);
95 * Adds a value to the array.
97 * @param value The value.
98 * @param overrideFrozen Whether to allow modifying frozen arrays.
100 void Array::Add(Value value, bool overrideFrozen)
102 ObjectLock olock(this);
104 if (m_Frozen && !overrideFrozen)
105 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
107 m_Data.push_back(std::move(value));
111 * Returns an iterator to the beginning of the array.
113 * Note: Caller must hold the object lock while using the iterator.
115 * @returns An iterator.
117 Array::Iterator Array::Begin()
121 return m_Data.begin();
125 * Returns an iterator to the end of the array.
127 * Note: Caller must hold the object lock while using the iterator.
129 * @returns An iterator.
131 Array::Iterator Array::End()
139 * Returns the number of elements in the array.
141 * @returns Number of elements.
143 size_t Array::GetLength() const
145 ObjectLock olock(this);
147 return m_Data.size();
151 * Checks whether the array contains the specified value.
153 * @param value The value.
154 * @returns true if the array contains the value, false otherwise.
156 bool Array::Contains(const Value& value) const
158 ObjectLock olock(this);
160 return (std::find(m_Data.begin(), m_Data.end(), value) != m_Data.end());
164 * Insert the given value at the specified index
166 * @param index The index
167 * @param value The value to add
168 * @param overrideFrozen Whether to allow modifying frozen arrays.
170 void Array::Insert(SizeType index, Value value, bool overrideFrozen)
172 ObjectLock olock(this);
174 ASSERT(index <= m_Data.size());
176 if (m_Frozen && !overrideFrozen)
177 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
179 m_Data.insert(m_Data.begin() + index, std::move(value));
183 * Removes the specified index from the array.
185 * @param index The index.
186 * @param overrideFrozen Whether to allow modifying frozen arrays.
188 void Array::Remove(SizeType index, bool overrideFrozen)
190 ObjectLock olock(this);
192 if (m_Frozen && !overrideFrozen)
193 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
195 m_Data.erase(m_Data.begin() + index);
199 * Removes the item specified by the iterator from the array.
201 * @param it The iterator.
202 * @param overrideFrozen Whether to allow modifying frozen arrays.
204 void Array::Remove(Array::Iterator it, bool overrideFrozen)
208 if (m_Frozen && !overrideFrozen)
209 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
214 void Array::Resize(SizeType newSize, bool overrideFrozen)
216 ObjectLock olock(this);
218 if (m_Frozen && !overrideFrozen)
219 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
221 m_Data.resize(newSize);
224 void Array::Clear(bool overrideFrozen)
226 ObjectLock olock(this);
228 if (m_Frozen && !overrideFrozen)
229 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
234 void Array::Reserve(SizeType newSize, bool overrideFrozen)
236 ObjectLock olock(this);
238 if (m_Frozen && !overrideFrozen)
239 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
241 m_Data.reserve(newSize);
244 void Array::CopyTo(const Array::Ptr& dest) const
246 ObjectLock olock(this);
247 ObjectLock xlock(dest);
250 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
252 std::copy(m_Data.begin(), m_Data.end(), std::back_inserter(dest->m_Data));
256 * Makes a shallow copy of an array.
258 * @returns a copy of the array.
260 Array::Ptr Array::ShallowClone() const
262 Array::Ptr clone = new Array();
268 * Makes a deep clone of an array
271 * @returns a copy of the array.
273 Object::Ptr Array::Clone() const
277 ObjectLock olock(this);
278 for (const Value& val : m_Data) {
279 arr.push_back(val.Clone());
282 return new Array(std::move(arr));
285 Array::Ptr Array::Reverse() const
287 Array::Ptr result = new Array();
289 ObjectLock olock(this);
290 ObjectLock xlock(result);
292 std::copy(m_Data.rbegin(), m_Data.rend(), std::back_inserter(result->m_Data));
297 void Array::Sort(bool overrideFrozen)
299 ObjectLock olock(this);
301 if (m_Frozen && !overrideFrozen)
302 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
304 std::sort(m_Data.begin(), m_Data.end());
307 String Array::ToString() const
309 std::ostringstream msgbuf;
310 ConfigWriter::EmitArray(msgbuf, 1, const_cast<Array *>(this));
314 Array::Ptr Array::Unique() const
316 std::set<Value> result;
318 ObjectLock olock(this);
320 for (const Value& item : m_Data) {
324 return Array::FromSet(result);
329 ObjectLock olock(this);
333 Value Array::GetFieldByName(const String& field, bool sandboxed, const DebugInfo& debugInfo) const
338 index = Convert::ToLong(field);
340 return Object::GetFieldByName(field, sandboxed, debugInfo);
343 ObjectLock olock(this);
345 if (index < 0 || static_cast<size_t>(index) >= GetLength())
346 BOOST_THROW_EXCEPTION(ScriptError("Array index '" + Convert::ToString(index) + "' is out of bounds.", debugInfo));
351 void Array::SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo)
353 ObjectLock olock(this);
355 int index = Convert::ToLong(field);
358 BOOST_THROW_EXCEPTION(ScriptError("Array index '" + Convert::ToString(index) + "' is out of bounds.", debugInfo));
360 if (static_cast<size_t>(index) >= GetLength())
361 Resize(index + 1, overrideFrozen);
363 Set(index, value, overrideFrozen);
366 Array::Iterator icinga::begin(const Array::Ptr& x)
371 Array::Iterator icinga::end(const Array::Ptr& x)