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