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