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