remove some unnecessary checks
[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
94                         return json_array_size(_value);
95         }
96
97         // get value at array index (const version)
98         const Value at(unsigned int index) const {
99                 return Value(json_array_get(_value, index));
100         }
101
102         const Value operator[](signed int index) const { return at(index); }
103         const Value operator[](unsigned int index) const { return at(index); }
104         const Value operator[](signed short index) const { return at(index); }
105         const Value operator[](unsigned short index) const { return at(index); }
106         const Value operator[](signed long index) const { return at(index); }
107         const Value operator[](unsigned long index) const { return at(index); }
108
109         // get value at array index (non-const version)
110         Value at(unsigned int index) {
111                 return Value(json_array_get(_value, index));
112         }
113
114         Value operator[](signed int index) { return at(index); }
115         Value operator[](unsigned int index) { return at(index); }
116         Value operator[](signed short index) { return at(index); }
117         Value operator[](unsigned short index) { return at(index); }
118         Value operator[](signed long index) { return at(index); }
119         Value operator[](unsigned long index) { return at(index); }
120
121         // get object property
122         const Value get(const char* key) const {
123                 return Value(json_object_get(_value, key));
124         }
125
126         const Value get(const std::string& key) const { return get(key.c_str()); }
127         const Value operator[](const char* key) const { return get(key); }
128         const Value operator[](const std::string& key) const { return get(key.c_str()); }
129
130         // clear all array/object values
131         void clear() {
132                 if (is_object())
133                         json_object_clear(_value);
134                 else
135                         json_array_clear(_value);
136         }
137
138         // get value cast to specified type
139         const char* as_cstring() const { return json_string_value(_value); }
140         std::string as_string() const { return as_cstring(); }
141         int as_integer() const { return json_integer_value(_value); }
142         double as_real() const { return json_real_value(_value); }
143         double as_number() const { return json_number_value(_value); }
144         bool as_boolean() const { return is_true(); }
145
146         // set an object property (converts value to object is not one already)
147         Value& set(const char* key, const Value& value) {
148                 if (!is_object()) {
149                         json_decref(_value);
150                         _value = json_object();
151                 }
152
153                 json_object_set(_value, key, value.as_json_t());
154
155                 return *this;
156         }
157
158         // set an array index (converts value to object is not one already)
159         Value& set(unsigned int index, const Value& value) {
160                 if (!is_array()) {
161                         json_decref(_value);
162                         _value = json_array();
163                 }
164
165                 if (index == size())
166                         json_array_append(_value, value.as_json_t());
167                 else
168                         json_array_set(_value, index, value.as_json_t());
169
170                 return *this;
171         }
172
173         Value& set(int index, const Value& value) { return set(static_cast<unsigned int>(index), value); }
174
175 private:
176         // take ownership of a json_t (does not increase reference count)
177         static Value _take(json_t* json) {
178                 Value v;
179                 v._value = json;
180                 return v;
181         }
182
183         // internal value pointer
184         json_t* _value;
185 };
186
187 // iterators over a JSON object
188 class Iterator {
189 public:
190         // construct a new iterator for a given object
191         Iterator(const Value& value) : _object(value), _iter(0) {
192                 _iter = json_object_iter(_object.as_json_t());
193         }
194
195         // increment iterator
196         void next() {
197                 _iter = json_object_iter_next(_object.as_json_t(), _iter);
198         }
199
200         Iterator& operator++() { next(); return *this; }
201
202         // test if iterator is still valid
203         bool valid() const { return _iter != 0; }
204         operator bool() const { return valid(); }
205
206         // get key
207         const char* ckey() const {
208                 return json_object_iter_key(_iter);
209         }
210
211         std::string key() const { return ckey(); }
212
213         // get value
214         const Value value() const {
215                 return Value(json_object_iter_value(_iter));
216         }
217
218         // dereference value
219         const Value operator*() const { return value(); }
220
221 private:
222         // disallow copying
223         Iterator(const Iterator&);
224         Iterator& operator=(const Iterator&);
225
226         // object being iterated over
227         Value _object;
228
229         // iterator value
230         void* _iter;
231 };
232
233 } // namespace jansson
234
235 #endif