]> granicus.if.org Git - icinga2/blob - lib/base/dictionary.cpp
eed8588568851876feee0ac1bb6e47719738785d
[icinga2] / lib / base / dictionary.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
4  *                                                                            *
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.                     *
9  *                                                                            *
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.                               *
14  *                                                                            *
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  ******************************************************************************/
19
20 #include "base/dictionary.h"
21 #include "base/objectlock.h"
22 #include "base/debug.h"
23 #include <cJSON.h>
24 #include <boost/make_shared.hpp>
25 #include <boost/foreach.hpp>
26
27 using namespace icinga;
28
29 /**
30  * Compares dictionary keys using the less operator.
31  */
32 struct DictionaryKeyLessComparer
33 {
34         /**
35          * Compares two keys.
36          *
37          * @param a The first key.
38          * @param b The second key.
39          * @returns true if the first key is less than the second key, false
40          *               otherwise
41          */
42         bool operator()(const std::pair<String, Value>& a, const char *b)
43         {
44                 return a.first < b;
45         }
46
47         /**
48          * Compares two keys.
49          *
50          * @param a The first key.
51          * @param b The second key.
52          * @returns true if the first key is less than the second key, false
53          *               otherwise
54          */
55         bool operator()(const char *a, const std::pair<String, Value>& b)
56         {
57                 return a < b.first;
58         }
59 };
60
61 /**
62  * Retrieves a value from a dictionary.
63  *
64  * @param key The key whose value should be retrieved.
65  * @returns The value of an empty value if the key was not found.
66  */
67 Value Dictionary::Get(const char *key) const
68 {
69         ASSERT(!OwnsLock());
70         ObjectLock olock(this);
71
72         std::map<String, Value>::const_iterator it;
73
74         it = std::lower_bound(m_Data.begin(), m_Data.end(), key, DictionaryKeyLessComparer());
75
76         if (it == m_Data.end() || DictionaryKeyLessComparer()(key, *it))
77                 return Empty;
78
79         return it->second;
80 }
81
82 /**
83  * Retrieves a value from the dictionary.
84  *
85  * @param key The key whose value should be retrieved.
86  * @returns The value or an empty value if the key was not found.
87  */
88 Value Dictionary::Get(const String& key) const
89 {
90         return Get(key.CStr());
91 }
92
93 /**
94  * Sets a value in the dictionary.
95  *
96  * @param key The key.
97  * @param value The value.
98  */
99 void Dictionary::Set(const String& key, const Value& value)
100 {
101         if (value.IsEmpty()) {
102                 Remove(key);
103                 return;
104         }
105
106         ASSERT(!OwnsLock());
107         ObjectLock olock(this);
108
109         std::pair<std::map<String, Value>::iterator, bool> ret;
110         ret = m_Data.insert(std::make_pair(key, value));
111         if (!ret.second)
112                 ret.first->second = value;
113 }
114
115 /**
116  * Returns an iterator to the beginning of the dictionary.
117  *
118  * Note: Caller must hold the object lock while using the iterator.
119  *
120  * @returns An iterator.
121  */
122 Dictionary::Iterator Dictionary::Begin(void)
123 {
124         ASSERT(OwnsLock());
125
126         return m_Data.begin();
127 }
128
129 /**
130  * Returns an iterator to the end of the dictionary.
131  *
132  * Note: Caller must hold the object lock while using the iterator.
133  *
134  * @returns An iterator.
135  */
136 Dictionary::Iterator Dictionary::End(void)
137 {
138         ASSERT(OwnsLock());
139
140         return m_Data.end();
141 }
142
143 /**
144  * Returns the number of elements in the dictionary.
145  *
146  * @returns Number of elements.
147  */
148 size_t Dictionary::GetLength(void) const
149 {
150         ASSERT(!OwnsLock());
151         ObjectLock olock(this);
152
153         return m_Data.size();
154 }
155
156 /**
157  * Checks whether the dictionary contains the specified key.
158  *
159  * @param key The key.
160  * @returns true if the dictionary contains the key, false otherwise.
161  */
162 bool Dictionary::Contains(const String& key) const
163 {
164         ASSERT(!OwnsLock());
165         ObjectLock olock(this);
166
167         return (m_Data.find(key) != m_Data.end());
168 }
169
170 /**
171  * Removes the specified key from the dictionary.
172  *
173  * @param key The key.
174  */
175 void Dictionary::Remove(const String& key)
176 {
177         ASSERT(!OwnsLock());
178         ObjectLock olock(this);
179
180         Dictionary::Iterator it;
181         it = m_Data.find(key);
182
183         if (it == m_Data.end())
184                 return;
185
186         m_Data.erase(it);
187 }
188
189 /**
190  * Removes the item specified by the iterator from the dictionary.
191  *
192  * @param it The iterator.
193  */
194 void Dictionary::Remove(Dictionary::Iterator it)
195 {
196         ASSERT(OwnsLock());
197
198         m_Data.erase(it);
199 }
200
201 void Dictionary::CopyTo(const Dictionary::Ptr& dest) const
202 {
203         ASSERT(!OwnsLock());
204         ObjectLock olock(this);
205
206         BOOST_FOREACH(const Dictionary::Pair& kv, m_Data) {
207                 dest->Set(kv.first, kv.second);
208         }
209 }
210
211 /**
212  * Makes a shallow copy of a dictionary.
213  *
214  * @returns a copy of the dictionary.
215  */
216 Dictionary::Ptr Dictionary::ShallowClone(void) const
217 {
218         Dictionary::Ptr clone = make_shared<Dictionary>();
219         CopyTo(clone);
220         return clone;
221 }
222
223 /**
224  * Converts a JSON object to a dictionary.
225  *
226  * @param json The JSON object.
227  * @returns A dictionary that is equivalent to the JSON object.
228  */
229 Dictionary::Ptr Dictionary::FromJson(cJSON *json)
230 {
231         Dictionary::Ptr dictionary = make_shared<Dictionary>();
232
233         ASSERT(json->type == cJSON_Object);
234
235         for (cJSON *i = json->child; i != NULL; i = i->next) {
236                 dictionary->Set(i->string, Value::FromJson(i));
237         }
238
239         return dictionary;
240 }
241
242 /**
243  * Converts this dictionary to a JSON object.
244  *
245  * @returns A JSON object that is equivalent to the dictionary. Values that
246  *          cannot be represented in JSON are omitted.
247  */
248 cJSON *Dictionary::ToJson(void) const
249 {
250         cJSON *json = cJSON_CreateObject();
251
252         try {
253                 ObjectLock olock(this);
254
255                 BOOST_FOREACH(const Dictionary::Pair& kv, m_Data) {
256                         cJSON_AddItemToObject(json, kv.first.CStr(), kv.second.ToJson());
257                 }
258         } catch (...) {
259                 cJSON_Delete(json);
260                 throw;
261         }
262
263         return json;
264 }