Merge branch '1.2'
[jansson.git] / src / jansson.ipp
1 // Copyright (c) 2010 Sean Middleditch <sean@middleditch.us>
2 // Copyright (c) 2010 Petri Lehtinen <petri@digip.org>
3 //
4 // Jansson is free software; you can redistribute it and/or modify
5 // it under the terms of the MIT license. See LICENSE for details.
6
7 #ifndef IN_JANSSON_HPP
8 #error "jansson.ipp may only be included from jansson.hpp"
9 #endif
10
11 namespace json {
12     namespace detail {
13         // assignment operator
14         template <typename _Base>
15         ValueBase<_Base>& ValueBase<_Base>::operator=(const Value& value) {
16             _Base::operator=(value);
17             return *this;
18         }
19
20         // check value type
21         template <typename _Base>
22         bool ValueBase<_Base>::is_undefined() const {
23             return _Base::as_json() == 0;
24         }
25
26         template <typename _Base>
27         bool ValueBase<_Base>::is_object() const {
28             return json_is_object(_Base::as_json());
29         }
30
31         template <typename _Base>
32         bool ValueBase<_Base>::is_array() const {
33             return json_is_array(_Base::as_json());
34         }
35
36         template <typename _Base>
37         bool ValueBase<_Base>::is_string() const {
38             return json_is_string(_Base::as_json());
39         }
40
41         template <typename _Base>
42         bool ValueBase<_Base>::is_integer() const {
43             return json_is_integer(_Base::as_json());
44         }
45
46         template <typename _Base>
47         bool ValueBase<_Base>::is_real() const {
48             return json_is_real(_Base::as_json());
49         }
50
51         template <typename _Base>
52         bool ValueBase<_Base>::is_number() const {
53             return json_is_number(_Base::as_json());
54         }
55
56         template <typename _Base>
57         bool ValueBase<_Base>::is_true() const {
58             return json_is_true(_Base::as_json());
59         }
60
61         template <typename _Base>
62         bool ValueBase<_Base>::is_false() const {
63             return json_is_false(_Base::as_json());
64         }
65
66         template <typename _Base>
67         bool ValueBase<_Base>::is_boolean() const {
68             return json_is_boolean(_Base::as_json());
69         }
70
71         template <typename _Base>
72         bool ValueBase<_Base>::is_null() const {
73             return json_is_null(_Base::as_json());
74         }
75
76         // get size of array or object
77         template <typename _Base>
78         unsigned int ValueBase<_Base>::size() const {
79             if (is_object())
80                 return json_object_size(_Base::as_json());
81             else
82                 return json_array_size(_Base::as_json());
83         }
84
85         // get value at array index (const version)
86         template <typename _Base>
87         const Value ValueBase<_Base>::at(unsigned int index) const {
88             return Value(json_array_get(_Base::as_json(), index));
89         }
90
91         template <typename _Base>
92         const Value ValueBase<_Base>::operator[](signed int index) const { return at(index); }
93         template <typename _Base>
94         const Value ValueBase<_Base>::operator[](unsigned int index) const { return at(index); }
95         template <typename _Base>
96         const Value ValueBase<_Base>::operator[](signed short index) const { return at(index); }
97         template <typename _Base>
98         const Value ValueBase<_Base>::operator[](unsigned short index) const { return at(index); }
99         template <typename _Base>
100         const Value ValueBase<_Base>::operator[](signed long index) const { return at(index); }
101         template <typename _Base>
102         const Value ValueBase<_Base>::operator[](unsigned long index) const { return at(index); }
103
104         // get value at array index (non-const version)
105         template <typename _Base>
106         ValueBase<ElementProxy> ValueBase<_Base>::at(unsigned int index) {
107             return ElementProxy(_Base::as_json(), index);
108         }
109
110         template <typename _Base>
111         ValueBase<ElementProxy> ValueBase<_Base>::operator[](signed int index) {
112             return at(index);
113         }
114
115         template <typename _Base>
116         ValueBase<ElementProxy> ValueBase<_Base>::operator[](unsigned int index) {
117             return at(index);
118         }
119
120         template <typename _Base>
121         ValueBase<ElementProxy> ValueBase<_Base>::operator[](signed short index) {
122             return at(index);
123         }
124
125         template <typename _Base>
126         ValueBase<ElementProxy> ValueBase<_Base>::operator[](unsigned short index) {
127             return at(index);
128         }
129
130         template <typename _Base>
131         ValueBase<ElementProxy> ValueBase<_Base>::operator[](signed long index) {
132             return at(index);
133         }
134
135         template <typename _Base>
136         ValueBase<ElementProxy> ValueBase<_Base>::operator[](unsigned long index) {
137             return at(index);
138         }
139
140         // get object property (const version)
141         template <typename _Base>
142         const Value ValueBase<_Base>::get(const char* key) const {
143             return Value(json_object_get(_Base::as_json(), key));
144         }
145
146         template <typename _Base>
147         const Value ValueBase<_Base>::get(const std::string& key) const {
148             return get(key.c_str());
149         }
150
151         template <typename _Base>
152         const Value ValueBase<_Base>::operator[](const char* key) const {
153             return get(key);
154         }
155
156         template <typename _Base>
157         const Value ValueBase<_Base>::operator[](const std::string& key) const {
158             return get(key.c_str());
159         }
160
161         // get object property (non-const version)
162         template <typename _Base>
163         ValueBase<PropertyProxy> ValueBase<_Base>::get(const char* key) {
164             return PropertyProxy(_Base::as_json(), key);
165         }
166
167         template <typename _Base>
168         ValueBase<PropertyProxy> ValueBase<_Base>::get(const std::string& key) {
169             return get(key.c_str());
170         }
171
172         template <typename _Base>
173         ValueBase<PropertyProxy> ValueBase<_Base>::operator[](const char* key) {
174             return get(key);
175         }
176
177         template <typename _Base>
178         ValueBase<PropertyProxy> ValueBase<_Base>::operator[](const std::string& key) {
179             return get(key.c_str());
180         }
181
182         // clear all array/object values
183         template <typename _Base>
184         void ValueBase<_Base>::clear() {
185             if (is_object())
186                 json_object_clear(_Base::as_json());
187             else
188                 json_array_clear(_Base::as_json());
189         }
190
191         // get value cast to specified type
192         template <typename _Base>
193         const char* ValueBase<_Base>::as_cstring() const {
194             return json_string_value(_Base::as_json());
195         }
196
197         template <typename _Base>
198         std::string ValueBase<_Base>::as_string() const {
199             const char* tmp = as_cstring();
200             return tmp == 0 ? "" : tmp;
201         }
202
203         template <typename _Base>
204         int ValueBase<_Base>::as_integer() const {
205             return json_integer_value(_Base::as_json());
206         }
207
208         template <typename _Base>
209         double ValueBase<_Base>::as_real() const {
210             return json_real_value(_Base::as_json());
211         }
212
213         template <typename _Base>
214         double ValueBase<_Base>::as_number() const {
215             return json_number_value(_Base::as_json());
216         }
217
218         template <typename _Base>
219         bool ValueBase<_Base>::as_boolean() const {
220             return is_true();
221         }
222
223         // set an object property (converts value to object is not one already)
224         template <typename _Base>
225         _Base& ValueBase<_Base>::set_key(const char* key, const Value& value) {
226             json_object_set(_Base::as_json(), key, value._Base::as_json());
227             return *this;
228         }
229
230         template <typename _Base>
231         _Base& ValueBase<_Base>::set_key(const std::string& key, const Value& value) {
232             return set_key(key.c_str(), value);
233         }
234
235         // set an array index (converts value to object is not one already)
236         template <typename _Base>
237         _Base& ValueBase<_Base>::set_at(unsigned int index, const Value& value) {
238             if (index == size())
239                 json_array_append(_Base::as_json(), value._Base::as_json());
240             else
241                 json_array_set(_Base::as_json(), index, value._Base::as_json());
242             return *this;
243         }
244
245         // delete an object key
246         template <typename _Base>
247         _Base& ValueBase<_Base>::del_key(const char* key) {
248             json_object_del(_Base::as_json(), key);
249             return *this;
250         }
251
252         template <typename _Base>
253         _Base& ValueBase<_Base>::del_key(const std::string& key) {
254             return del_key(key.c_str());
255         }
256
257         // delete an item from an array by index
258         template <typename _Base>
259         _Base& ValueBase<_Base>::del_at(unsigned int index) {
260             json_array_remove(_Base::as_json(), index);
261             return *this;
262         }
263
264         // insert an item into an array at a given index
265         template <typename _Base>
266         _Base& ValueBase<_Base>::insert_at(unsigned int index, const Value& value) {
267             json_array_insert(_Base::as_json(), index, value._Base::as_json());
268             return *this;
269         }
270
271         // write the value to a file
272         template <typename _Base>
273         int ValueBase<_Base>::dump_file(const char* path, int flags) const {
274             return json_dump_file(_Base::as_json(), path, flags);
275         }
276
277         template <typename _Base>
278         int ValueBase<_Base>::dump_file(const std::string& path, int flags) const {
279             return dump_file(path.c_str(), flags);
280         }
281
282         // write the value to a string (caller must deallocate with free()!)
283         template <typename _Base>
284         char* ValueBase<_Base>::dumps(int flags) const {
285             return json_dumps(_Base::as_json(), flags);
286         }
287
288         Basic::~Basic() {
289             json_decref(_value);
290         }
291
292         // copy an existing Value
293         Basic& Basic::operator=(const Basic& e) {
294             if (&e != this) {
295                 json_decref(_value);
296                 _value = json_incref(e._value);
297             }
298             return *this;
299         }
300
301         // get the underlying json_t
302         json_t* Basic::as_json() const {
303             return _value;
304         }
305
306         // take ownership of a json_t (does not increase reference count)
307         Basic Basic::take_ownership(json_t* json) {
308             Basic v;
309             v._value = json;
310             return v;
311         }
312
313         // assign value to proxied array element
314         ElementProxy& ElementProxy::operator=(const Value& value) {
315             json_array_set(_array, _index, value.as_json());
316             return *this;
317         }
318
319         // get the proxied element
320         json_t* ElementProxy::as_json() const {
321             return json_array_get(_array, _index);
322         }
323
324         // assign value to proxied object property
325         PropertyProxy& PropertyProxy::operator=(const Value& value) {
326             json_object_set(_object, _key, value.as_json());
327             return *this;
328         }
329
330         json_t* PropertyProxy::as_json() const {
331             return json_object_get(_object, _key);
332         }
333
334     } // namespace json::detail
335
336     // construct Value::Value input
337     Value::Value(const char* value) {
338         _value = json_string(value);
339     }
340
341     Value::Value(const std::string& value) {
342         _value = json_string(value.c_str());
343     }
344
345     Value::Value(bool value) {
346         _value = value ? json_true() : json_false();
347     }
348
349     Value::Value(signed int value) {
350         _value = json_integer(value);
351     }
352
353     Value::Value(unsigned int value) {
354         _value = json_integer(value);
355     }
356
357     Value::Value(signed short value) {
358         _value = json_integer(value);
359     }
360
361     Value::Value(unsigned short value) {
362         _value = json_integer(value);
363     }
364
365     Value::Value(signed long value) {
366         _value = json_integer(value);
367     }
368
369     Value::Value(unsigned long value) {
370         _value = json_integer(value);
371     }
372
373     Value::Value(float value) {
374         _value = json_real(value);
375     }
376
377     Value::Value(double value) {
378         _value = json_real(value);
379     }
380
381     // construct a new iterator for a given object
382     Iterator::Iterator(const Value& value) : _object(value), _iter(0) {
383         _iter = json_object_iter(_object.as_json());
384     }
385
386     // construct a new iterator for a given object
387     Iterator::Iterator(const detail::ValueBase<detail::PropertyProxy>& value) :
388         _object(value.as_json()), _iter(0) {
389         _iter = json_object_iter(_object.as_json());
390     }
391
392     // increment iterator
393     void Iterator::next() {
394         _iter = json_object_iter_next(_object.as_json(), _iter);
395     }
396
397     Iterator& Iterator::operator++() { next(); return *this; }
398
399     // test if iterator is still valid
400     bool Iterator::valid() const {
401         return _iter != 0;
402     }
403
404     Iterator::operator bool() const {
405         return valid();
406     }
407
408     // get key
409     const char* Iterator::ckey() const {
410         return json_object_iter_key(_iter);
411     }
412
413     std::string Iterator::key() const {
414         return ckey();
415     }
416
417     // get value
418     const Value Iterator::value() const {
419         return Value(json_object_iter_value(_iter));
420     }
421
422     // dereference value
423     const Value Iterator::operator*() const {
424         return value();
425     }
426
427     // create a new empty object
428     Value object() {
429         return Value::take_ownership(json_object());
430     }
431
432     // create a new empty array
433     Value array() {
434         return Value::take_ownership(json_array());
435     }
436
437     // create a new null value
438     Value null() {
439         return Value::take_ownership(json_null());
440     }
441
442     // load a file as a JSON value
443     Value load_file(const char* path, json_error_t* error) {
444         return Value::take_ownership(json_load_file(path, error));
445     }
446
447     Value load_file(const std::string& path, json_error_t* error) {
448         return load_file(path.c_str(), error);
449     }
450
451     // load a string as a JSON value
452     Value loads(const char* string, json_error_t* error) {
453         return Value::take_ownership(json_loads(string, error));
454     }
455
456     Value loads(const std::string& string, json_error_t* error) {
457         return loads(string.c_str(), error);
458     }
459
460 } // namespace json
461
462 // stream JSON value out
463 std::ostream& operator<<(std::ostream& os, const json::Value& value) {
464     // get the temporary serialize string
465     char* tmp = value.dumps();
466     if (tmp != 0) {
467         // stream temp string out and release it
468         os << tmp;
469         free(tmp);
470     }
471     return os;
472 }
473
474 // read JSON value
475 std::istream& operator>>(std::istream& is, json::Value& value) {
476     // buffer the remaining bytes into a single string for Jansson
477     std::stringstream tmp;
478     while (is)
479         tmp << static_cast<char>(is.get());
480     // parse the buffered string
481     value = json::loads(tmp.str().c_str());
482     return is;
483 }