Merge branch 'master' of /home/elanthis/Source/janssonxx
[jansson.git] / src / jansson-impl.hpp
1 // janssonxx - C++ wrapper for jansson, implementation file
2 //
3 // author: Sean Middleditch <sean@middleditch.us>
4 //
5 // janssonxx is free software; you can redistribute it and/or modify
6 // it under the terms of the MIT license. See LICENSE for details.
7
8 #if !defined(IN_JANSSON_HPP)
9 #       error "jansson-impl.hpp may only by included from jansson.hpp"
10 #endif
11
12 namespace json {
13         namespace _private {
14                 // assignment operator
15                 template <typename _Base>
16                 ValueBase<_Base>& ValueBase<_Base>::operator=(const Value& value) {
17                         _Base::operator=(value);
18                         return *this;
19                 }
20
21                 // check value type
22                 template <typename _Base>
23                 bool ValueBase<_Base>::is_undefined() const {
24                         return _Base::as_json() == 0;
25                 }
26
27                 template <typename _Base>
28                 bool ValueBase<_Base>::is_object() const {
29                         return json_is_object(_Base::as_json());
30                 }
31
32                 template <typename _Base>
33                 bool ValueBase<_Base>::is_array() const {
34                         return json_is_array(_Base::as_json());
35                 }
36
37                 template <typename _Base>
38                 bool ValueBase<_Base>::is_string() const {
39                         return json_is_string(_Base::as_json());
40                 }
41
42                 template <typename _Base>
43                 bool ValueBase<_Base>::is_integer() const {
44                         return json_is_integer(_Base::as_json());
45                 }
46
47                 template <typename _Base>
48                 bool ValueBase<_Base>::is_real() const {
49                         return json_is_real(_Base::as_json());
50                 }
51
52                 template <typename _Base>
53                 bool ValueBase<_Base>::is_number() const {
54                         return json_is_number(_Base::as_json());
55                 }
56
57                 template <typename _Base>
58                 bool ValueBase<_Base>::is_true() const {
59                         return json_is_true(_Base::as_json());
60                 }
61
62                 template <typename _Base>
63                 bool ValueBase<_Base>::is_false() const {
64                         return json_is_false(_Base::as_json());
65                 }
66
67                 template <typename _Base>
68                 bool ValueBase<_Base>::is_boolean() const {
69                         return json_is_boolean(_Base::as_json());
70                 }
71
72                 template <typename _Base>
73                 bool ValueBase<_Base>::is_null() const {
74                         return json_is_null(_Base::as_json());
75                 }
76
77                 // get size of array or object
78                 template <typename _Base>
79                 unsigned int ValueBase<_Base>::size() const {
80                         if (is_object())
81                                 return json_object_size(_Base::as_json());
82                         else
83                                 return json_array_size(_Base::as_json());
84                 }
85
86                 // get value at array index (const version)
87                 template <typename _Base>
88                 const Value ValueBase<_Base>::at(unsigned int index) const {
89                         return Value(json_array_get(_Base::as_json(), index));
90                 }
91
92                 template <typename _Base>
93                 const Value ValueBase<_Base>::operator[](signed int index) const { return at(index); }
94                 template <typename _Base>
95                 const Value ValueBase<_Base>::operator[](unsigned int index) const { return at(index); }
96                 template <typename _Base>
97                 const Value ValueBase<_Base>::operator[](signed short index) const { return at(index); }
98                 template <typename _Base>
99                 const Value ValueBase<_Base>::operator[](unsigned short index) const { return at(index); }
100                 template <typename _Base>
101                 const Value ValueBase<_Base>::operator[](signed long index) const { return at(index); }
102                 template <typename _Base>
103                 const Value ValueBase<_Base>::operator[](unsigned long index) const { return at(index); }
104
105                 // get value at array index (non-const version)
106                 template <typename _Base>
107                 ValueBase<ElementProxy> ValueBase<_Base>::at(unsigned int index) {
108                         return ElementProxy(_Base::as_json(), index);
109                 }
110
111                 template <typename _Base>
112                 ValueBase<ElementProxy> ValueBase<_Base>::operator[](signed int index) {
113                         return at(index);
114                 }
115
116                 template <typename _Base>
117                 ValueBase<ElementProxy> ValueBase<_Base>::operator[](unsigned int index) {
118                         return at(index);
119                 }
120
121                 template <typename _Base>
122                 ValueBase<ElementProxy> ValueBase<_Base>::operator[](signed short index) {
123                         return at(index);
124                 }
125
126                 template <typename _Base>
127                 ValueBase<ElementProxy> ValueBase<_Base>::operator[](unsigned short index) {
128                         return at(index);
129                 }
130
131                 template <typename _Base>
132                 ValueBase<ElementProxy> ValueBase<_Base>::operator[](signed long index) {
133                         return at(index);
134                 }
135
136                 template <typename _Base>
137                 ValueBase<ElementProxy> ValueBase<_Base>::operator[](unsigned long index) {
138                         return at(index);
139                 }
140
141                 // get object property (const version)
142                 template <typename _Base>
143                 const Value ValueBase<_Base>::get(const char* key) const {
144                         return Value(json_object_get(_Base::as_json(), key));
145                 }
146
147                 template <typename _Base>
148                 const Value ValueBase<_Base>::get(const std::string& key) const {
149                         return get(key.c_str());
150                 }
151
152                 template <typename _Base>
153                 const Value ValueBase<_Base>::operator[](const char* key) const {
154                         return get(key);
155                 }
156
157                 template <typename _Base>
158                 const Value ValueBase<_Base>::operator[](const std::string& key) const {
159                         return get(key.c_str());
160                 }
161
162                 // get object property (non-const version)
163                 template <typename _Base>
164                 ValueBase<PropertyProxy> ValueBase<_Base>::get(const char* key) {
165                         return PropertyProxy(_Base::as_json(), key);
166                 }
167
168                 template <typename _Base>
169                 ValueBase<PropertyProxy> ValueBase<_Base>::get(const std::string& key) {
170                         return get(key.c_str());
171                 }
172
173                 template <typename _Base>
174                 ValueBase<PropertyProxy> ValueBase<_Base>::operator[](const char* key) {
175                         return get(key);
176                 }
177
178                 template <typename _Base>
179                 ValueBase<PropertyProxy> ValueBase<_Base>::operator[](const std::string& key) {
180                         return get(key.c_str());
181                 }
182
183                 // clear all array/object values
184                 template <typename _Base>
185                 void ValueBase<_Base>::clear() {
186                         if (is_object())
187                                 json_object_clear(_Base::as_json());
188                         else
189                                 json_array_clear(_Base::as_json());
190                 }
191
192                 // get value cast to specified type
193                 template <typename _Base>
194                 const char* ValueBase<_Base>::as_cstring() const {
195                         return json_string_value(_Base::as_json());
196                 }
197
198                 template <typename _Base>
199                 std::string ValueBase<_Base>::as_string() const {
200                         const char* tmp = as_cstring();
201                         return tmp == 0 ? "" : tmp;
202                 }
203
204                 template <typename _Base>
205                 int ValueBase<_Base>::as_integer() const {
206                         return json_integer_value(_Base::as_json());
207                 }
208
209                 template <typename _Base>
210                 double ValueBase<_Base>::as_real() const {
211                         return json_real_value(_Base::as_json());
212                 }
213
214                 template <typename _Base>
215                 double ValueBase<_Base>::as_number() const {
216                         return json_number_value(_Base::as_json());
217                 }
218
219                 template <typename _Base>
220                 bool ValueBase<_Base>::as_boolean() const {
221                         return is_true();
222                 }
223
224                 // set an object property (converts value to object is not one already)
225                 template <typename _Base>
226                 _Base& ValueBase<_Base>::set_key(const char* key, const Value& value) {
227                         json_object_set(_Base::as_json(), key, value._Base::as_json());
228                         return *this;
229                 }
230
231                 template <typename _Base>
232                 _Base& ValueBase<_Base>::set_key(const std::string& key, const Value& value) {
233                         return set_key(key.c_str(), value);
234                 }
235
236                 // set an array index (converts value to object is not one already)
237                 template <typename _Base>
238                 _Base& ValueBase<_Base>::set_at(unsigned int index, const Value& value) {
239                         if (index == size())
240                                 json_array_append(_Base::as_json(), value._Base::as_json());
241                         else
242                                 json_array_set(_Base::as_json(), index, value._Base::as_json());
243                         return *this;
244                 }
245
246                 // delete an object key
247                 template <typename _Base>
248                 _Base& ValueBase<_Base>::del_key(const char* key) {
249                         json_object_del(_Base::as_json(), key);
250                         return *this;
251                 }
252
253                 template <typename _Base>
254                 _Base& ValueBase<_Base>::del_key(const std::string& key) {
255                         return del_key(key.c_str());
256                 }
257
258                 // delete an item from an array by index
259                 template <typename _Base>
260                 _Base& ValueBase<_Base>::del_at(unsigned int index) {
261                         json_array_remove(_Base::as_json(), index);
262                         return *this;
263                 }
264
265                 // insert an item into an array at a given index
266                 template <typename _Base>
267                 _Base& ValueBase<_Base>::insert_at(unsigned int index, const Value& value) {
268                         json_array_insert(_Base::as_json(), index, value._Base::as_json());
269                         return *this;
270                 }
271
272                 // write the value to a file
273                 template <typename _Base>
274                 int ValueBase<_Base>::save_file(const char* path, int flags) const {
275                         return json_dump_file(_Base::as_json(), path, flags);
276                 }
277
278                 // write the value to a string (caller must deallocate with free()!)
279                 template <typename _Base>
280                 char* ValueBase<_Base>::save_string(int flags) const {
281                         return json_dumps(_Base::as_json(), flags);
282                 }
283
284                 Basic::~Basic() {
285                         json_decref(_value);
286                 }
287
288                 // copy an existing Value
289                 Basic& Basic::operator=(const Basic& e) {
290                         if (&e != this) {
291                                 json_decref(_value);
292                                 _value = json_incref(e._value);
293                         }
294                         return *this;
295                 }
296
297                 // get the underlying json_t
298                 json_t* Basic::as_json() const {
299                         return _value;
300                 }
301
302                 // take ownership of a json_t (does not increase reference count)
303                 Basic Basic::take_ownership(json_t* json) {
304                         Basic v;
305                         v._value = json;
306                         return v;
307                 }
308
309                 // assign value to proxied array element
310                 ElementProxy& ElementProxy::operator=(const Value& value) {
311                         json_array_set(_array, _index, value.as_json());
312                         return *this;
313                 }
314
315                 // get the proxied element
316                 json_t* ElementProxy::as_json() const {
317                         return json_array_get(_array, _index);
318                 }
319
320                 // assign value to proxied object property
321                 PropertyProxy& PropertyProxy::operator=(const Value& value) {
322                         json_object_set(_object, _key, value.as_json());
323                         return *this;
324                 }
325
326                 json_t* PropertyProxy::as_json() const {
327                         return json_object_get(_object, _key);
328                 }
329
330         } // namespace json::_private
331
332         // construct Value::Value input
333         Value::Value(const char* value) {
334                 _value = json_string(value);
335         }
336
337         Value::Value(const std::string& value) {
338                 _value = json_string(value.c_str());
339         }
340
341         Value::Value(bool value) {
342                 _value = value ? json_true() : json_false();
343         }
344
345         Value::Value(signed int value) {
346                 _value = json_integer(value);
347         }
348
349         Value::Value(unsigned int value) {
350                 _value = json_integer(value);
351         }
352
353         Value::Value(signed short value) {
354                 _value = json_integer(value);
355         }
356
357         Value::Value(unsigned short value) {
358                 _value = json_integer(value);
359         }
360
361         Value::Value(signed long value) {
362                 _value = json_integer(value);
363         }
364
365         Value::Value(unsigned long value) {
366                 _value = json_integer(value);
367         }
368
369         Value::Value(float value) {
370                 _value = json_real(value);
371         }
372
373         Value::Value(double value) {
374                 _value = json_real(value);
375         }
376         
377         // construct a new iterator for a given object
378         Iterator::Iterator(const Value& value) : _object(value), _iter(0) {
379                 _iter = json_object_iter(_object.as_json());
380         }
381
382         // construct a new iterator for a given object
383         Iterator::Iterator(const _private::ValueBase<_private::PropertyProxy>& value) :
384                         _object(value.as_json()), _iter(0) {
385                 _iter = json_object_iter(_object.as_json());
386         }
387
388         // increment iterator
389         void Iterator::next() {
390                 _iter = json_object_iter_next(_object.as_json(), _iter);
391         }
392
393         Iterator& Iterator::operator++() { next(); return *this; }
394
395         // test if iterator is still valid
396         bool Iterator::valid() const {
397                 return _iter != 0;
398         }
399
400         Iterator::operator bool() const {
401                 return valid();
402         }
403
404         // get key
405         const char* Iterator::ckey() const {
406                 return json_object_iter_key(_iter);
407         }
408
409         std::string Iterator::key() const {
410                 return ckey();
411         }
412
413         // get value
414         const Value Iterator::value() const {
415                 return Value(json_object_iter_value(_iter));
416         }
417
418         // dereference value
419         const Value Iterator::operator*() const {
420                 return value();
421         }
422
423         // create a new empty object
424         Value object() {
425                 return Value::take_ownership(json_object());
426         }
427
428         // create a new empty array
429         Value array() {
430                 return Value::take_ownership(json_array());
431         }
432
433         // create a new null value
434         Value null() {
435                 return Value::take_ownership(json_null());
436         }
437
438         // load a file as a JSON value
439         Value load_file(const char* path, json_error_t* error) {
440                 return Value::take_ownership(json_load_file(path, error));
441         }
442
443         // load a string as a JSON value
444         Value load_string(const char* string, json_error_t* error) {
445                 return Value::take_ownership(json_loads(string, error));
446         }
447
448 } // namespace json
449
450 // stream JSON value out
451 std::ostream& operator<<(std::ostream& os, const json::Value& value) {
452         // get the temporary serialize string
453         char* tmp = value.save_string();
454         if (tmp != 0) {
455                 // stream temp string out and release it
456                 os << tmp;
457                 free(tmp);
458         }
459         return os;
460 }
461
462 // read JSON value
463 std::istream& operator>>(std::istream& is, json::Value& value) {
464         // buffer the remaining bytes into a single string for Jansson
465         std::stringstream tmp;
466         while (is)
467                 tmp << static_cast<char>(is.get());
468         // parse the buffered string
469         value = json::load_string(tmp.str().c_str());
470         return is;
471 }