C++: #include <cstdio> in jansson.hpp
[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>::save_file(const char* path, int flags) const {
274             return json_dump_file(_Base::as_json(), path, flags);
275         }
276
277         // write the value to a string (caller must deallocate with free()!)
278         template <typename _Base>
279         char* ValueBase<_Base>::save_string(int flags) const {
280             return json_dumps(_Base::as_json(), flags);
281         }
282
283         Basic::~Basic() {
284             json_decref(_value);
285         }
286
287         // copy an existing Value
288         Basic& Basic::operator=(const Basic& e) {
289             if (&e != this) {
290                 json_decref(_value);
291                 _value = json_incref(e._value);
292             }
293             return *this;
294         }
295
296         // get the underlying json_t
297         json_t* Basic::as_json() const {
298             return _value;
299         }
300
301         // take ownership of a json_t (does not increase reference count)
302         Basic Basic::take_ownership(json_t* json) {
303             Basic v;
304             v._value = json;
305             return v;
306         }
307
308         // assign value to proxied array element
309         ElementProxy& ElementProxy::operator=(const Value& value) {
310             json_array_set(_array, _index, value.as_json());
311             return *this;
312         }
313
314         // get the proxied element
315         json_t* ElementProxy::as_json() const {
316             return json_array_get(_array, _index);
317         }
318
319         // assign value to proxied object property
320         PropertyProxy& PropertyProxy::operator=(const Value& value) {
321             json_object_set(_object, _key, value.as_json());
322             return *this;
323         }
324
325         json_t* PropertyProxy::as_json() const {
326             return json_object_get(_object, _key);
327         }
328
329     } // namespace json::detail
330
331     // construct Value::Value input
332     Value::Value(const char* value) {
333         _value = json_string(value);
334     }
335
336     Value::Value(const std::string& value) {
337         _value = json_string(value.c_str());
338     }
339
340     Value::Value(bool value) {
341         _value = value ? json_true() : json_false();
342     }
343
344     Value::Value(signed int value) {
345         _value = json_integer(value);
346     }
347
348     Value::Value(unsigned int value) {
349         _value = json_integer(value);
350     }
351
352     Value::Value(signed short value) {
353         _value = json_integer(value);
354     }
355
356     Value::Value(unsigned short value) {
357         _value = json_integer(value);
358     }
359
360     Value::Value(signed long value) {
361         _value = json_integer(value);
362     }
363
364     Value::Value(unsigned long value) {
365         _value = json_integer(value);
366     }
367
368     Value::Value(float value) {
369         _value = json_real(value);
370     }
371
372     Value::Value(double value) {
373         _value = json_real(value);
374     }
375
376     // construct a new iterator for a given object
377     Iterator::Iterator(const Value& value) : _object(value), _iter(0) {
378         _iter = json_object_iter(_object.as_json());
379     }
380
381     // construct a new iterator for a given object
382     Iterator::Iterator(const detail::ValueBase<detail::PropertyProxy>& value) :
383         _object(value.as_json()), _iter(0) {
384         _iter = json_object_iter(_object.as_json());
385     }
386
387     // increment iterator
388     void Iterator::next() {
389         _iter = json_object_iter_next(_object.as_json(), _iter);
390     }
391
392     Iterator& Iterator::operator++() { next(); return *this; }
393
394     // test if iterator is still valid
395     bool Iterator::valid() const {
396         return _iter != 0;
397     }
398
399     Iterator::operator bool() const {
400         return valid();
401     }
402
403     // get key
404     const char* Iterator::ckey() const {
405         return json_object_iter_key(_iter);
406     }
407
408     std::string Iterator::key() const {
409         return ckey();
410     }
411
412     // get value
413     const Value Iterator::value() const {
414         return Value(json_object_iter_value(_iter));
415     }
416
417     // dereference value
418     const Value Iterator::operator*() const {
419         return value();
420     }
421
422     // create a new empty object
423     Value object() {
424         return Value::take_ownership(json_object());
425     }
426
427     // create a new empty array
428     Value array() {
429         return Value::take_ownership(json_array());
430     }
431
432     // create a new null value
433     Value null() {
434         return Value::take_ownership(json_null());
435     }
436
437     // load a file as a JSON value
438     Value load_file(const char* path, json_error_t* error) {
439         return Value::take_ownership(json_load_file(path, error));
440     }
441
442     // load a string as a JSON value
443     Value load_string(const char* string, json_error_t* error) {
444         return Value::take_ownership(json_loads(string, error));
445     }
446
447 } // namespace json
448
449 // stream JSON value out
450 std::ostream& operator<<(std::ostream& os, const json::Value& value) {
451     // get the temporary serialize string
452     char* tmp = value.save_string();
453     if (tmp != 0) {
454         // stream temp string out and release it
455         os << tmp;
456         free(tmp);
457     }
458     return os;
459 }
460
461 // read JSON value
462 std::istream& operator>>(std::istream& is, json::Value& value) {
463     // buffer the remaining bytes into a single string for Jansson
464     std::stringstream tmp;
465     while (is)
466         tmp << static_cast<char>(is.get());
467     // parse the buffered string
468     value = json::load_string(tmp.str().c_str());
469     return is;
470 }