dbf94dffe9f1f708df27cd2f5a732414eea27177
[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 }