fix uninitialized variable major
[mech_eap.git] / util_json.cpp
1 /*
2  * Copyright (c) 2011, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of JANET(UK) nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 /*
34  * JSONObject utilities.
35  */
36
37 #include "gssapiP_eap.h"
38
39 #include <typeinfo>
40 #include <string>
41 #include <sstream>
42 #include <exception>
43 #include <stdexcept>
44 #include <new>
45
46 #define JSON_INIT(obj) do {                                     \
47         if ((obj) == NULL)                                      \
48             throw new std::bad_alloc;                           \
49         m_obj = (obj);                                          \
50     } while (0)
51
52 #define JSON_CHECK_CONTAINER() do {                             \
53         if (!json_is_object(m_obj) && !json_is_array(m_obj)) {  \
54             std::string s("JSONObject is not a container");     \
55             throw new std::runtime_error(s);                    \
56         }                                                       \
57     } while (0)
58
59 #define JSON_CHECK_OBJECT() do {                                \
60         if (!json_is_object(m_obj)) {                           \
61             std::string s("JSONObject is not a dictionary");    \
62             throw new std::runtime_error(s);                    \
63         }                                                       \
64     } while (0)
65
66 #define JSON_CHECK_ARRAY() do {                                 \
67         if (!json_is_array(m_obj)) {                            \
68             std::string s("JSONObject is not an array");        \
69             throw new std::runtime_error(s);                    \
70         }                                                       \
71     } while (0)
72
73 #define JSON_CHECK(s) do {              \
74         if ((s) != 0)                   \
75             throw new std::bad_alloc;   \
76     } while (0)
77
78 JSONObject
79 JSONObject::load(const char *input, size_t flags, json_error_t *error)
80 {
81     json_t *obj;
82
83     obj = json_loads(input, flags, error);
84
85     return JSONObject(obj, false);
86 }
87
88 JSONObject
89 JSONObject::load(FILE *fp, size_t flags, json_error_t *error)
90 {
91     json_t *obj;
92
93     obj = json_loadf(fp, flags, error);
94
95     return JSONObject(obj, false);
96 }
97
98 char *
99 JSONObject::dump(size_t flags) const
100 {
101     char *s = json_dumps(m_obj, flags);
102
103     if (s == NULL)
104         throw new std::bad_alloc;
105
106     return s;
107 }
108
109 void
110 JSONObject::dump(FILE *fp, size_t flags) const
111 {
112     int r = json_dumpf(m_obj, fp, flags);
113
114     if (r != 0)
115         throw new std::bad_alloc;
116 }
117
118 size_t
119 JSONObject::size(void) const
120 {
121     if (json_is_object(m_obj))
122         return json_object_size(m_obj);
123     else if (json_is_array(m_obj))
124         return json_array_size(m_obj);
125     else
126         return 0;
127 }
128
129 JSONObject::JSONObject(json_t *obj, bool retain)
130 {
131     if (retain)
132         json_incref(obj);
133     JSON_INIT(obj);
134 }
135
136 JSONObject::JSONObject(const char *value)
137 {
138     json_t *obj = json_string(value);
139
140     JSON_INIT(obj);
141 }
142
143 JSONObject::JSONObject(json_int_t value)
144 {
145     json_t *obj = json_integer(value);
146
147     JSON_INIT(obj);
148 }
149
150 JSONObject::JSONObject(double value)
151 {
152     json_t *obj = json_real(value);
153
154     JSON_INIT(obj);
155 }
156
157 JSONObject::JSONObject(bool value)
158 {
159     json_t *obj = value ? json_true() : json_false();
160
161     JSON_INIT(obj);
162 }
163
164 JSONObject::JSONObject(void)
165 {
166     json_t *obj = json_object();
167
168     JSON_INIT(obj);
169 }
170
171 JSONObject
172 JSONObject::object(void)
173 {
174     return JSONObject();
175 }
176
177 JSONObject
178 JSONObject::null(void)
179 {
180     return JSONObject(json_null(), false);
181 }
182
183 JSONObject
184 JSONObject::array(void)
185 {
186     return JSONObject(json_array(), false);
187 }
188
189 void
190 JSONObject::set(const char *key, JSONObject &value)
191 {
192     JSON_CHECK_OBJECT();
193     JSON_CHECK(json_object_set_new(m_obj, key, value.get()));
194 }
195
196 void
197 JSONObject::set(const char *key, const char *value)
198 {
199     JSONObject jobj(value);
200     set(key, jobj);
201 }
202
203 void
204 JSONObject::set(const char *key, json_int_t value)
205 {
206     JSONObject jobj(value);
207     set(key, jobj);
208 }
209
210 void
211 JSONObject::del(const char *key)
212 {
213     json_object_del(m_obj, key);
214 }
215
216 JSONObject
217 JSONObject::get(const char *key) const
218 {
219     json_t *obj;
220
221     obj = json_object_get(m_obj, key);
222     if (obj == NULL)
223         return JSONObject::null();
224
225     return JSONObject(obj, true);
226 }
227
228 JSONObject
229 JSONObject::get(size_t index) const
230 {
231     json_t *obj;
232
233     obj = json_array_get(m_obj, index);
234     if (obj == NULL)
235         return JSONObject::null();
236
237     return JSONObject(obj, true);
238 }
239
240 void
241 JSONObject::update(JSONObject &value)
242 {
243     JSON_CHECK_OBJECT();
244     json_t *other = value.get();
245     JSON_CHECK(json_object_update(m_obj, other));
246     json_decref(other);
247 }
248
249 JSONObject
250 JSONObject::operator[](size_t index) const
251 {
252     return get(index);
253 }
254
255 JSONObject
256 JSONObject::operator[](const char *key) const
257 {
258     return get(key);
259 }
260
261 void
262 JSONObject::append(JSONObject &value)
263 {
264     JSON_CHECK_ARRAY();
265     JSON_CHECK(json_array_append_new(m_obj, value.get()));
266 }
267
268 void
269 JSONObject::insert(size_t index, JSONObject &value)
270 {
271     JSON_CHECK_ARRAY();
272     JSON_CHECK(json_array_insert_new(m_obj, index, value.get()));
273 }
274
275 void
276 JSONObject::remove(size_t index)
277 {
278     JSON_CHECK_ARRAY();
279     JSON_CHECK(json_array_remove(m_obj, index));
280 }
281
282 void
283 JSONObject::clear(void)
284 {
285     JSON_CHECK_CONTAINER();
286
287     if (json_is_object(m_obj)) {
288         JSON_CHECK(json_object_clear(m_obj));
289     } else if (json_is_array(m_obj)) {
290         JSON_CHECK(json_array_clear(m_obj));
291     }
292 }
293
294 void
295 JSONObject::extend(JSONObject &value)
296 {
297     JSON_CHECK_ARRAY();
298     json_t *other = value.get();
299     JSON_CHECK(json_array_extend(m_obj, other));
300     json_decref(other);
301 }
302
303 const char *
304 JSONObject::string(void) const
305 {
306     return json_string_value(m_obj);
307 }
308
309 json_int_t
310 JSONObject::integer(void) const
311 {
312     return json_integer_value(m_obj);
313 }
314
315 double
316 JSONObject::real(void) const
317 {
318     return json_real_value(m_obj);
319 }
320
321 double
322 JSONObject::number(void) const
323 {
324     return json_number_value(m_obj);
325 }
326
327 JSONObject
328 JSONObject::ddf(DDF &ddf)
329 {
330     if (ddf.isstruct()) {
331         DDF elem = ddf.first();
332         JSONObject jobj = JSONObject::object();
333
334         while (!elem.isnull()) {
335             JSONObject jtmp = JSONObject::ddf(elem);
336             jobj.set(elem.name(), jtmp);
337             elem = ddf.next();
338         }
339
340         return jobj;
341     } else if (ddf.islist()) {
342         DDF elem = ddf.first();
343         JSONObject jobj = JSONObject::array();
344
345         while (!elem.isnull()) {
346             JSONObject jtmp = JSONObject::ddf(elem);
347             jobj.append(jtmp);
348             elem = ddf.next();
349         }
350
351         return jobj;
352     } else if (ddf.isstring()) {
353         return JSONObject(ddf.string());
354     } else if (ddf.isint()) {
355         return JSONObject((json_int_t)ddf.integer());
356     } else if (ddf.isfloat()) {
357         return JSONObject(ddf.floating());
358     } else if (ddf.isempty() || ddf.ispointer()) {
359         return JSONObject::object();
360     } else if (ddf.isnull()) {
361         return JSONObject::null();
362     }
363
364     std::string s("Unbridgeable DDF object");
365     throw new std::runtime_error(s);
366 }
367
368 DDF
369 JSONObject::ddf(void) const
370 {
371     DDF ddf(NULL);
372
373     switch (type()) {
374     case JSON_OBJECT: {
375         JSONIterator iter = iterator();
376
377         do {
378             const char *key = iter.key();
379             DDF value = iter.value().ddf();
380             ddf.addmember(key).swap(value);
381         } while (iter.next());
382         break;
383     }
384     case JSON_ARRAY: {
385         size_t i, nelems = size();
386
387         for (i = 0; i < nelems; i++) {
388             DDF value = get(i).ddf();
389             ddf.add(value);
390         }
391         break;
392     }
393     case JSON_STRING:
394         ddf.string(string());
395         break;
396     case JSON_INTEGER:
397         ddf.integer(integer());
398         break;
399     case JSON_REAL:
400         ddf.floating(real());
401         break;
402     case JSON_TRUE:
403         ddf.integer(1L);
404         break;
405     case JSON_FALSE:
406         ddf.integer(0L);
407         break;
408     case JSON_NULL:
409         break;
410     }
411
412     return ddf;
413 }
414
415 bool JSONObject::isObject(void) const
416 {
417     return json_is_object(m_obj);
418 }
419
420 bool JSONObject::isArray(void) const
421 {
422     return json_is_array(m_obj);
423 }
424
425 bool JSONObject::isString(void) const
426 {
427     return json_is_string(m_obj);
428 }
429
430 bool JSONObject::isInteger(void) const
431 {
432     return json_is_integer(m_obj);
433 }
434
435 bool JSONObject::isNumber(void) const
436 {
437     return json_is_number(m_obj);
438 }
439
440 bool JSONObject::isBoolean(void) const
441 {
442     return json_is_boolean(m_obj);
443 }
444
445 bool JSONObject::isNull(void) const
446 {
447     return json_is_null(m_obj);
448 }
449
450 JSONIterator::JSONIterator(const JSONObject &obj)
451 {
452     m_obj = obj.get();
453     m_iter = json_object_iter(m_obj);
454 }
455
456 JSONIterator::~JSONIterator(void)
457 {
458     json_decref(m_obj);
459 }
460
461 const char *
462 JSONIterator::key(void) const
463 {
464     return json_object_iter_key(m_iter);
465 }
466
467 JSONObject
468 JSONIterator::value(void) const
469 {
470     return JSONObject(json_object_iter_value(m_iter));
471 }
472
473 bool
474 JSONIterator::next(void)
475 {
476     m_iter = json_object_iter_next(m_obj, m_iter);
477     return m_iter != NULL;
478 }