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