cleanup the take_ownership function a bit
[jansson.git] / janssonxx.h
1 #if !defined(JANSSONXX_H)
2 #define JANSSONXX_H 1
3
4 #include <string>
5
6 namespace jansson {
7
8 // include in the jansson namespace
9 #include <jansson.h>
10
11 class Iterator;
12
13 // represents any JSON value
14 class Value {
15 public:
16         // construct new Value with an undefined value
17         Value() : _value(0) {}
18
19         // free Value resources
20         ~Value() { json_decref(_value); }
21
22         // copy an existing Value
23         Value(const Value& e) : _value(json_incref(e._value)) {}
24
25         // make a reference to an existing json_t value
26         explicit Value(json_t* value) : _value(json_incref(value)) {}
27
28         // copy an existing Value
29         Value& operator=(const Value& e) {
30                 if (&e != this) {
31                         json_decref(_value);
32                         _value = json_incref(e._value);
33                 }
34                 return *this;
35         }
36
37         // load a file as a JSON value
38         static Value load_file(const char* path, json_error_t* error = 0) {
39                 return Value::_take(json_load_file(path, error));
40         }
41
42         // load a string as a JSON value
43         static Value load_string(const char* string, json_error_t* error = 0) {
44                 return Value::_take(json_loads(string, error));
45         }
46
47         // write the value to a file
48         int save_file(const char* path, int flags = JSON_INDENT(2)) const {
49                 return json_dump_file(_value, path, flags);
50         }
51
52         // write the value to a string (caller must deallocate with free()!)
53         char* save_string(int flags = JSON_INDENT(2)) const {
54                 return json_dumps(_value, flags);
55         }
56
57         // construct Value from input
58         static Value from(const char* value) { return Value::_take(json_string(value)); }
59         static Value from(const std::string& value) { return from(value.c_str()); }
60         static Value from(bool value) { return Value::_take(value ? json_true() : json_false()); }
61         static Value from(int value) { return Value::_take(json_integer(value)); }
62         static Value from(double value) { return Value::_take(json_real(value)); }
63
64         // create a new empty object
65         static Value object() { return Value::_take(json_object()); }
66
67         // create a new empty array
68         static Value array() { return Value::_take(json_array()); }
69
70         // create a new null value
71         static Value null() { return Value::_take(json_null()); }
72
73         // get the underlying json_t
74         json_t* as_json_t() const { return _value; }
75
76         // check value type
77         bool is_undefined() const { return _value == 0; }
78         bool is_object() const { return json_is_object(_value); }
79         bool is_array() const { return json_is_array(_value); }
80         bool is_string() const { return json_is_string(_value); }
81         bool is_integer() const { return json_is_integer(_value); }
82         bool is_real() const { return json_is_real(_value); }
83         bool is_number() const { return json_is_number(_value); }
84         bool is_true() const { return json_is_true(_value); }
85         bool is_false() const { return json_is_false(_value); }
86         bool is_boolean() const { return json_is_boolean(_value); }
87         bool is_null() const { return json_is_null(_value); }
88
89         // get size of array or object
90         unsigned int size() const {
91                 if (is_object())
92                         return json_object_size(_value);
93                 else if (is_array())
94                         return json_array_size(_value);
95                 else
96                         return 0;
97         }
98
99         // get value at array index (const version)
100         const Value at(unsigned int index) const {
101                 if (is_array())
102                         return Value(json_array_get(_value, index));
103                 else
104                         return Value();
105         }
106
107         const Value operator[](signed int index) const { return at(index); }
108         const Value operator[](unsigned int index) const { return at(index); }
109         const Value operator[](signed short index) const { return at(index); }
110         const Value operator[](unsigned short index) const { return at(index); }
111         const Value operator[](signed long index) const { return at(index); }
112         const Value operator[](unsigned long index) const { return at(index); }
113
114         // get value at array index (non-const version)
115         Value at(unsigned int index) {
116                 if (is_array())
117                         return Value(json_array_get(_value, index));
118                 else
119                         return Value();
120         }
121
122         Value operator[](signed int index) { return at(index); }
123         Value operator[](unsigned int index) { return at(index); }
124         Value operator[](signed short index) { return at(index); }
125         Value operator[](unsigned short index) { return at(index); }
126         Value operator[](signed long index) { return at(index); }
127         Value operator[](unsigned long index) { return at(index); }
128
129         // get object property
130         const Value get(const char* key) const {
131                 if (is_object())
132                         return Value(json_object_get(_value, key));
133                 else
134                         return Value();
135         }
136
137         const Value get(const std::string& key) const { return get(key.c_str()); }
138         const Value operator[](const char* key) const { return get(key); }
139         const Value operator[](const std::string& key) const { return get(key.c_str()); }
140
141         // clear all array/object values
142         void clear() {
143                 if (is_object())
144                         json_object_clear(_value);
145                 else if (is_array())
146                         json_array_clear(_value);
147         }
148
149         // get value cast to specified type
150         const char* as_cstring() const { return json_string_value(_value); }
151         std::string as_string() const { return as_cstring(); }
152         int as_integer() const { return json_integer_value(_value); }
153         double as_real() const { return json_real_value(_value); }
154         double as_number() const { return json_number_value(_value); }
155         bool as_boolean() const { return is_true(); }
156
157         // set an object property (converts value to object is not one already)
158         Value& set(const char* key, const Value& value) {
159                 if (!is_object()) {
160                         json_decref(_value);
161                         _value = json_object();
162                 }
163
164                 json_object_set(_value, key, value.as_json_t());
165
166                 return *this;
167         }
168
169         // set an array index (converts value to object is not one already)
170         Value& set(unsigned int index, const Value& value) {
171                 if (!is_array()) {
172                         json_decref(_value);
173                         _value = json_array();
174                 }
175
176                 if (index == size())
177                         json_array_append(_value, value.as_json_t());
178                 else
179                         json_array_set(_value, index, value.as_json_t());
180
181                 return *this;
182         }
183
184         Value& set(int index, const Value& value) { return set(static_cast<unsigned int>(index), value); }
185
186 private:
187         // take ownership of a json_t (does not increase reference count)
188         static Value _take(json_t* json) {
189                 Value v;
190                 v._value = json;
191                 return v;
192         }
193
194         // internal value pointer
195         json_t* _value;
196 };
197
198 // iterators over a JSON object
199 class Iterator {
200 public:
201         // construct a new iterator for a given object
202         Iterator(const Value& value) : _object(value), _iter(0) {
203                 _iter = json_object_iter(_object.as_json_t());
204         }
205
206         // increment iterator
207         void next() {
208                 if (_iter != 0)
209                         _iter = json_object_iter_next(_object.as_json_t(), _iter);
210         }
211
212         Iterator& operator++() { next(); return *this; }
213
214         // test if iterator is still valid
215         bool valid() const { return _iter != 0; }
216         operator bool() const { return valid(); }
217
218         // get key
219         const char* ckey() const {
220                 if (_iter != 0)
221                         return json_object_iter_key(_iter);
222                 else
223                         return "";
224         }
225
226         std::string key() const { return ckey(); }
227
228         // get value
229         const Value value() const {
230                 if (_iter != 0)
231                         return Value(json_object_iter_value(_iter));
232                 else
233                         return Value();
234         }
235
236         // dereference value
237         const Value operator*() const { return value(); }
238
239 private:
240         // disallow copying
241         Iterator(const Iterator&);
242         Iterator& operator=(const Iterator&);
243
244         // object being iterated over
245         Value _object;
246
247         // iterator value
248         void* _iter;
249 };
250
251 } // namespace jansson
252
253 #endif