]> granicus.if.org Git - icinga2/blob - lib/base/array.cpp
Merge pull request #7185 from Icinga/bugfix/gelfwriter-wrong-log-facility
[icinga2] / lib / base / array.cpp
1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
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"
11
12 using namespace icinga;
13
14 template class std::vector<Value>;
15
16 REGISTER_PRIMITIVE_TYPE(Array, Object, Array::GetPrototype());
17
18 Array::Array(const ArrayData& other)
19         : m_Data(other)
20 { }
21
22 Array::Array(ArrayData&& other)
23         : m_Data(std::move(other))
24 { }
25
26 Array::Array(std::initializer_list<Value> init)
27         : m_Data(init)
28 { }
29
30 /**
31  * Restrieves a value from an array.
32  *
33  * @param index The index.
34  * @returns The value.
35  */
36 Value Array::Get(SizeType index) const
37 {
38         ObjectLock olock(this);
39
40         return m_Data.at(index);
41 }
42
43 /**
44  * Sets a value in the array.
45  *
46  * @param index The index.
47  * @param value The value.
48  * @param overrideFrozen Whether to allow modifying frozen arrays.
49  */
50 void Array::Set(SizeType index, const Value& value, bool overrideFrozen)
51 {
52         ObjectLock olock(this);
53
54         if (m_Frozen && !overrideFrozen)
55                 BOOST_THROW_EXCEPTION(std::invalid_argument("Value in array must not be modified."));
56
57         m_Data.at(index) = value;
58 }
59
60 /**
61  * Sets a value in the array.
62  *
63  * @param index The index.
64  * @param value The value.
65  * @param overrideFrozen Whether to allow modifying frozen arrays.
66  */
67 void Array::Set(SizeType index, Value&& value, bool overrideFrozen)
68 {
69         ObjectLock olock(this);
70
71         if (m_Frozen && !overrideFrozen)
72                 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
73
74         m_Data.at(index).Swap(value);
75 }
76
77 /**
78  * Adds a value to the array.
79  *
80  * @param value The value.
81  * @param overrideFrozen Whether to allow modifying frozen arrays.
82  */
83 void Array::Add(Value value, bool overrideFrozen)
84 {
85         ObjectLock olock(this);
86
87         if (m_Frozen && !overrideFrozen)
88                 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
89
90         m_Data.push_back(std::move(value));
91 }
92
93 /**
94  * Returns an iterator to the beginning of the array.
95  *
96  * Note: Caller must hold the object lock while using the iterator.
97  *
98  * @returns An iterator.
99  */
100 Array::Iterator Array::Begin()
101 {
102         ASSERT(OwnsLock());
103
104         return m_Data.begin();
105 }
106
107 /**
108  * Returns an iterator to the end of the array.
109  *
110  * Note: Caller must hold the object lock while using the iterator.
111  *
112  * @returns An iterator.
113  */
114 Array::Iterator Array::End()
115 {
116         ASSERT(OwnsLock());
117
118         return m_Data.end();
119 }
120
121 /**
122  * Returns the number of elements in the array.
123  *
124  * @returns Number of elements.
125  */
126 size_t Array::GetLength() const
127 {
128         ObjectLock olock(this);
129
130         return m_Data.size();
131 }
132
133 /**
134  * Checks whether the array contains the specified value.
135  *
136  * @param value The value.
137  * @returns true if the array contains the value, false otherwise.
138  */
139 bool Array::Contains(const Value& value) const
140 {
141         ObjectLock olock(this);
142
143         return (std::find(m_Data.begin(), m_Data.end(), value) != m_Data.end());
144 }
145
146 /**
147  * Insert the given value at the specified index
148  *
149  * @param index The index
150  * @param value The value to add
151  * @param overrideFrozen Whether to allow modifying frozen arrays.
152  */
153 void Array::Insert(SizeType index, Value value, bool overrideFrozen)
154 {
155         ObjectLock olock(this);
156
157         ASSERT(index <= m_Data.size());
158
159         if (m_Frozen && !overrideFrozen)
160                 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
161
162         m_Data.insert(m_Data.begin() + index, std::move(value));
163 }
164
165 /**
166  * Removes the specified index from the array.
167  *
168  * @param index The index.
169  * @param overrideFrozen Whether to allow modifying frozen arrays.
170  */
171 void Array::Remove(SizeType index, bool overrideFrozen)
172 {
173         ObjectLock olock(this);
174
175         if (m_Frozen && !overrideFrozen)
176                 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
177
178         m_Data.erase(m_Data.begin() + index);
179 }
180
181 /**
182  * Removes the item specified by the iterator from the array.
183  *
184  * @param it The iterator.
185  * @param overrideFrozen Whether to allow modifying frozen arrays.
186  */
187 void Array::Remove(Array::Iterator it, bool overrideFrozen)
188 {
189         ASSERT(OwnsLock());
190
191         if (m_Frozen && !overrideFrozen)
192                 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
193
194         m_Data.erase(it);
195 }
196
197 void Array::Resize(SizeType newSize, bool overrideFrozen)
198 {
199         ObjectLock olock(this);
200
201         if (m_Frozen && !overrideFrozen)
202                 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
203
204         m_Data.resize(newSize);
205 }
206
207 void Array::Clear(bool overrideFrozen)
208 {
209         ObjectLock olock(this);
210
211         if (m_Frozen && !overrideFrozen)
212                 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
213
214         m_Data.clear();
215 }
216
217 void Array::Reserve(SizeType newSize, bool overrideFrozen)
218 {
219         ObjectLock olock(this);
220
221         if (m_Frozen && !overrideFrozen)
222                 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
223
224         m_Data.reserve(newSize);
225 }
226
227 void Array::CopyTo(const Array::Ptr& dest) const
228 {
229         ObjectLock olock(this);
230         ObjectLock xlock(dest);
231
232         if (dest->m_Frozen)
233                 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
234
235         std::copy(m_Data.begin(), m_Data.end(), std::back_inserter(dest->m_Data));
236 }
237
238 /**
239  * Makes a shallow copy of an array.
240  *
241  * @returns a copy of the array.
242  */
243 Array::Ptr Array::ShallowClone() const
244 {
245         Array::Ptr clone = new Array();
246         CopyTo(clone);
247         return clone;
248 }
249
250 /**
251  * Makes a deep clone of an array
252  * and its elements.
253  *
254  * @returns a copy of the array.
255  */
256 Object::Ptr Array::Clone() const
257 {
258         ArrayData arr;
259
260         ObjectLock olock(this);
261         for (const Value& val : m_Data) {
262                 arr.push_back(val.Clone());
263         }
264
265         return new Array(std::move(arr));
266 }
267
268 Array::Ptr Array::Reverse() const
269 {
270         Array::Ptr result = new Array();
271
272         ObjectLock olock(this);
273         ObjectLock xlock(result);
274
275         std::copy(m_Data.rbegin(), m_Data.rend(), std::back_inserter(result->m_Data));
276
277         return result;
278 }
279
280 void Array::Sort(bool overrideFrozen)
281 {
282         ObjectLock olock(this);
283
284         if (m_Frozen && !overrideFrozen)
285                 BOOST_THROW_EXCEPTION(std::invalid_argument("Array must not be modified."));
286
287         std::sort(m_Data.begin(), m_Data.end());
288 }
289
290 String Array::ToString() const
291 {
292         std::ostringstream msgbuf;
293         ConfigWriter::EmitArray(msgbuf, 1, const_cast<Array *>(this));
294         return msgbuf.str();
295 }
296
297 Array::Ptr Array::Unique() const
298 {
299         std::set<Value> result;
300
301         ObjectLock olock(this);
302
303         for (const Value& item : m_Data) {
304                 result.insert(item);
305         }
306
307         return Array::FromSet(result);
308 }
309
310 void Array::Freeze()
311 {
312         ObjectLock olock(this);
313         m_Frozen = true;
314 }
315
316 Value Array::GetFieldByName(const String& field, bool sandboxed, const DebugInfo& debugInfo) const
317 {
318         int index;
319
320         try {
321                 index = Convert::ToLong(field);
322         } catch (...) {
323                 return Object::GetFieldByName(field, sandboxed, debugInfo);
324         }
325
326         ObjectLock olock(this);
327
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));
330
331         return Get(index);
332 }
333
334 void Array::SetFieldByName(const String& field, const Value& value, bool overrideFrozen, const DebugInfo& debugInfo)
335 {
336         ObjectLock olock(this);
337
338         int index = Convert::ToLong(field);
339
340         if (index < 0)
341                 BOOST_THROW_EXCEPTION(ScriptError("Array index '" + Convert::ToString(index) + "' is out of bounds.", debugInfo));
342
343         if (static_cast<size_t>(index) >= GetLength())
344                 Resize(index + 1, overrideFrozen);
345
346         Set(index, value, overrideFrozen);
347 }
348
349 Array::Iterator icinga::begin(const Array::Ptr& x)
350 {
351         return x->Begin();
352 }
353
354 Array::Iterator icinga::end(const Array::Ptr& x)
355 {
356         return x->End();
357 }