]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_json.inl
Initial vogl checkin
[vogl] / src / voglcore / vogl_json.inl
1 // File: vogl_json.inl\r
2 \r
3 namespace vogl\r
4 {\r
5 \r
6     inline json_value::json_value()\r
7         : m_type(cJSONValueTypeNull), m_line(0)\r
8     {\r
9         m_data.m_nVal = 0;\r
10     }\r
11 \r
12     inline json_value::json_value(bool val)\r
13         : m_type(cJSONValueTypeBool), m_line(0)\r
14     {\r
15         m_data.m_nVal = val;\r
16     }\r
17 \r
18     inline json_value::json_value(int32 nVal)\r
19         : m_type(cJSONValueTypeInt), m_line(0)\r
20     {\r
21         m_data.m_nVal = nVal;\r
22     }\r
23 \r
24     inline json_value::json_value(uint32 nVal)\r
25         : m_type(cJSONValueTypeInt), m_line(0)\r
26     {\r
27         m_data.m_nVal = nVal;\r
28     }\r
29 \r
30     inline json_value::json_value(int64_t nVal)\r
31         : m_type(cJSONValueTypeInt), m_line(0)\r
32     {\r
33         m_data.m_nVal = nVal;\r
34     }\r
35 \r
36     // Note uint64_t values may be encoded as hex strings or int64_t\r
37     inline json_value::json_value(uint64_t nVal)\r
38         : m_type(cJSONValueTypeNull), m_line(0)\r
39     {\r
40         m_data.m_nVal = 0;\r
41         set_value(nVal);\r
42     }\r
43 \r
44     inline json_value::json_value(double flVal)\r
45         : m_type(cJSONValueTypeDouble), m_line(0)\r
46     {\r
47         m_data.m_flVal = flVal;\r
48     }\r
49 \r
50     inline json_value::json_value(char *pStr)\r
51         : m_type(cJSONValueTypeString), m_line(0)\r
52     {\r
53         m_data.m_pStr = vogl_strdup(pStr);\r
54     }\r
55 \r
56     inline json_value::json_value(const char *pStr)\r
57         : m_type(cJSONValueTypeString), m_line(0)\r
58     {\r
59         m_data.m_pStr = vogl_strdup(pStr);\r
60     }\r
61 \r
62     inline json_value::json_value(const dynamic_string &str)\r
63         : m_type(cJSONValueTypeString), m_line(0)\r
64     {\r
65         m_data.m_pStr = vogl_strdup(str.get_ptr());\r
66     }\r
67 \r
68     inline json_value::json_value(const json_node *pNode)\r
69         : m_type(cJSONValueTypeNode), m_line(0)\r
70     {\r
71         m_data.m_pNode = get_json_node_pool()->alloc(*pNode);\r
72     }\r
73 \r
74     inline json_value::json_value(json_value_type_t type)\r
75         : m_type(type),\r
76           m_line(0)\r
77     {\r
78         m_data.m_nVal = 0;\r
79         if (type == cJSONValueTypeNode)\r
80             m_data.m_pNode = get_json_node_pool()->alloc();\r
81         else if (type == cJSONValueTypeString)\r
82             m_data.m_pStr = vogl_strdup("");\r
83     }\r
84 \r
85     inline json_value::~json_value()\r
86     {\r
87         free_data();\r
88     }\r
89 \r
90     inline json_value_type_t json_value::get_type() const\r
91     {\r
92         return m_type;\r
93     }\r
94 \r
95     inline const json_value_data_t &json_value::get_raw_data() const\r
96     {\r
97         return m_data;\r
98     }\r
99 \r
100     inline json_value_data_t &json_value::get_raw_data()\r
101     {\r
102         return m_data;\r
103     }\r
104 \r
105     inline bool json_value::is_null() const\r
106     {\r
107         return m_type == cJSONValueTypeNull;\r
108     }\r
109 \r
110     inline bool json_value::is_valid() const\r
111     {\r
112         return m_type != cJSONValueTypeNull;\r
113     }\r
114 \r
115     inline bool json_value::is_bool() const\r
116     {\r
117         return m_type == cJSONValueTypeBool;\r
118     }\r
119 \r
120     inline bool json_value::is_int() const\r
121     {\r
122         return m_type == cJSONValueTypeInt;\r
123     }\r
124 \r
125     inline bool json_value::is_double() const\r
126     {\r
127         return m_type == cJSONValueTypeDouble;\r
128     }\r
129 \r
130     inline bool json_value::is_numeric() const\r
131     {\r
132         return (m_type == cJSONValueTypeInt) || (m_type == cJSONValueTypeDouble);\r
133     }\r
134 \r
135     inline bool json_value::is_string() const\r
136     {\r
137         return m_type == cJSONValueTypeString;\r
138     }\r
139 \r
140     inline bool json_value::is_node() const\r
141     {\r
142         return m_type == cJSONValueTypeNode;\r
143     }\r
144 \r
145     inline bool json_value::is_object_or_array() const\r
146     {\r
147         return m_type == cJSONValueTypeNode;\r
148     }\r
149 \r
150     inline const json_node *json_value::get_node_ptr() const\r
151     {\r
152         return (m_type == cJSONValueTypeNode) ? m_data.m_pNode : NULL;\r
153     }\r
154     inline json_node *json_value::get_node_ptr()\r
155     {\r
156         return (m_type == cJSONValueTypeNode) ? m_data.m_pNode : NULL;\r
157     }\r
158 \r
159     inline void json_value::clear()\r
160     {\r
161         set_value_to_null();\r
162         m_line = 0;\r
163     }\r
164 \r
165     inline void json_value::assume_ownership(json_value &src_val)\r
166     {\r
167         set_value_to_null();\r
168         swap(src_val);\r
169     }\r
170 \r
171     inline void json_value::release_ownership(json_value &dst_value)\r
172     {\r
173         dst_value.set_value_to_null();\r
174         dst_value.swap(*this);\r
175     }\r
176 \r
177     inline void json_value::init(json_value_type_t type)\r
178     {\r
179         free_data();\r
180         m_type = type;\r
181         m_data.m_nVal = 0;\r
182         if (type == cJSONValueTypeNode)\r
183             m_data.m_pNode = get_json_node_pool()->alloc();\r
184         else if (type == cJSONValueTypeString)\r
185             m_data.m_pStr = vogl_strdup("");\r
186         m_line = 0;\r
187     }\r
188 \r
189     inline json_node *json_value::init_object()\r
190     {\r
191         return set_value_to_node(true);\r
192     }\r
193 \r
194     inline json_node *json_value::init_array()\r
195     {\r
196         return set_value_to_node(false);\r
197     }\r
198 \r
199     inline json_node *json_value::set_value_to_object(json_node *pParent)\r
200     {\r
201         json_node *pRoot = get_json_node_pool()->alloc(pParent, true);\r
202         set_value_assume_ownership(pRoot);\r
203         return pRoot;\r
204     }\r
205 \r
206     inline json_node *json_value::set_value_to_array(json_node *pParent)\r
207     {\r
208         json_node *pRoot = get_json_node_pool()->alloc(pParent, false);\r
209         set_value_assume_ownership(pRoot);\r
210         return pRoot;\r
211     }\r
212 \r
213     inline json_node *json_value::set_value_to_node(bool is_object, json_node *pParent)\r
214     {\r
215         json_node *pRoot = get_json_node_pool()->alloc(pParent, is_object);\r
216         set_value_assume_ownership(pRoot);\r
217         return pRoot;\r
218     }\r
219 \r
220     inline void json_value::set_value_to_null()\r
221     {\r
222         free_data();\r
223         m_data.m_nVal = 0;\r
224         m_type = cJSONValueTypeNull;\r
225     }\r
226 \r
227     inline void json_value::set_value(bool val)\r
228     {\r
229         free_data();\r
230         m_data.m_nVal = val;\r
231         m_type = cJSONValueTypeBool;\r
232     }\r
233 \r
234     inline void json_value::set_value(int8 nVal)\r
235     {\r
236         free_data();\r
237         m_data.m_nVal = nVal;\r
238         m_type = cJSONValueTypeInt;\r
239     }\r
240 \r
241     inline void json_value::set_value(int16 nVal)\r
242     {\r
243         free_data();\r
244         m_data.m_nVal = nVal;\r
245         m_type = cJSONValueTypeInt;\r
246     }\r
247 \r
248     inline void json_value::set_value(int32 nVal)\r
249     {\r
250         free_data();\r
251         m_data.m_nVal = nVal;\r
252         m_type = cJSONValueTypeInt;\r
253     }\r
254 \r
255     inline void json_value::set_value(int64_t nVal)\r
256     {\r
257         free_data();\r
258         m_data.m_nVal = nVal;\r
259         m_type = cJSONValueTypeInt;\r
260     }\r
261 \r
262     inline void json_value::set_value(uint8 nVal)\r
263     {\r
264         set_value(static_cast<int64_t>(nVal));\r
265     }\r
266 \r
267     inline void json_value::set_value(uint16 nVal)\r
268     {\r
269         set_value(static_cast<int64_t>(nVal));\r
270     }\r
271 \r
272     inline void json_value::set_value(uint32 nVal)\r
273     {\r
274         set_value(static_cast<int64_t>(nVal));\r
275     }\r
276 \r
277     inline void json_value::set_value(double flVal)\r
278     {\r
279         free_data();\r
280         m_data.m_flVal = flVal;\r
281         m_type = cJSONValueTypeDouble;\r
282     }\r
283 \r
284     inline void json_value::set_value(const char *pStr)\r
285     {\r
286         free_data();\r
287         m_data.m_pStr = vogl_strdup(pStr);\r
288         m_type = cJSONValueTypeString;\r
289     }\r
290 \r
291     inline void json_value::set_value(const dynamic_string &str)\r
292     {\r
293         free_data();\r
294         m_data.m_pStr = vogl_strdup(str.get_ptr());\r
295         m_type = cJSONValueTypeString;\r
296     }\r
297 \r
298     inline void json_value::set_value(const json_node *pNode)\r
299     {\r
300         free_data();\r
301         m_data.m_pNode = get_json_node_pool()->alloc(*pNode);\r
302         m_type = cJSONValueTypeNode;\r
303     }\r
304 \r
305     inline void json_value::set_value_assume_ownership(char *pStr)\r
306     {\r
307         free_data();\r
308         m_data.m_pStr = pStr;\r
309         m_type = cJSONValueTypeString;\r
310     }\r
311 \r
312     inline void json_value::set_value_assume_ownership(json_node *pNode)\r
313     {\r
314         free_data();\r
315         m_data.m_pNode = pNode;\r
316         m_type = cJSONValueTypeNode;\r
317     }\r
318 \r
319     inline json_value &json_value::operator=(bool val)\r
320     {\r
321         set_value(val);\r
322         return *this;\r
323     }\r
324 \r
325     inline json_value &json_value::operator=(int32 nVal)\r
326     {\r
327         set_value(nVal);\r
328         return *this;\r
329     }\r
330 \r
331     inline json_value &json_value::operator=(uint32 nVal)\r
332     {\r
333         set_value(nVal);\r
334         return *this;\r
335     }\r
336 \r
337     inline json_value &json_value::operator=(int64_t nVal)\r
338     {\r
339         set_value(nVal);\r
340         return *this;\r
341     }\r
342 \r
343     inline json_value &json_value::operator=(uint64_t nVal)\r
344     {\r
345         set_value(nVal);\r
346         return *this;\r
347     }\r
348 \r
349     inline json_value &json_value::operator=(double flVal)\r
350     {\r
351         set_value(flVal);\r
352         return *this;\r
353     }\r
354 \r
355     inline json_value &json_value::operator=(const char *pStr)\r
356     {\r
357         set_value(pStr);\r
358         return *this;\r
359     }\r
360 \r
361     inline bool json_value::is_object() const\r
362     {\r
363         return (m_type == cJSONValueTypeNode) ? get_node_ptr()->is_object() : false;\r
364     }\r
365 \r
366     inline bool json_value::is_array() const\r
367     {\r
368         return (m_type == cJSONValueTypeNode) ? get_node_ptr()->is_array() : false;\r
369     }\r
370 \r
371     inline bool json_value::operator==(const json_value &other) const\r
372     {\r
373         if (m_type != other.m_type)\r
374             return false;\r
375 \r
376         switch (m_type)\r
377         {\r
378             case cJSONValueTypeNull:\r
379                 return true;\r
380             case cJSONValueTypeBool:\r
381             case cJSONValueTypeInt:\r
382             case cJSONValueTypeDouble:\r
383                 return m_data.m_nVal == other.m_data.m_nVal;\r
384             case cJSONValueTypeString:\r
385                 return vogl_strcmp(as_string_ptr(), other.as_string_ptr()) == 0;\r
386             case cJSONValueTypeNode:\r
387                 return *get_node_ptr() == *other.get_node_ptr();\r
388         }\r
389         return false;\r
390     }\r
391 \r
392     // Attempts to convert a JSON value to each type.\r
393     // Returns false and sets val to def if the value cannot be converted (out of range, or type is obviously incompatible).\r
394     // Note that if trying to convert a negative value to an unsigned type, or a value which is too large will fail and you'll get the default.\r
395     inline bool json_value::get_bool(bool &val, bool def) const\r
396     {\r
397         if (is_bool())\r
398         {\r
399             val = (m_data.m_nVal != 0);\r
400             return true;\r
401         }\r
402         else\r
403             return convert_to_bool(val, def);\r
404     }\r
405 \r
406     inline bool json_value::get_numeric(int32 &val, int32 def) const\r
407     {\r
408         if ((is_int()) && (m_data.m_nVal == static_cast<int32>(m_data.m_nVal)))\r
409         {\r
410             val = static_cast<int32>(m_data.m_nVal);\r
411             return true;\r
412         }\r
413         else\r
414             return convert_to_int32(val, def);\r
415     }\r
416 \r
417     inline bool json_value::get_numeric(int64_t &val, int64_t def) const\r
418     {\r
419         if (is_int())\r
420         {\r
421             val = m_data.m_nVal;\r
422             return true;\r
423         }\r
424         else\r
425             return convert_to_int64(val, def);\r
426     }\r
427 \r
428     inline bool json_value::get_numeric(uint64_t &val, uint64_t def) const\r
429     {\r
430         return convert_to_uint64(val, def);\r
431     }\r
432 \r
433     inline bool json_value::get_numeric(float &val, float def) const\r
434     {\r
435         if (is_double())\r
436         {\r
437             val = static_cast<float>(m_data.m_flVal);\r
438             return true;\r
439         }\r
440         else\r
441             return convert_to_float(val, def);\r
442     }\r
443 \r
444     inline bool json_value::get_numeric(double &val, double def) const\r
445     {\r
446         if (is_double())\r
447         {\r
448             val = m_data.m_flVal;\r
449             return true;\r
450         }\r
451         else\r
452             return convert_to_double(val, def);\r
453     }\r
454 \r
455     inline bool json_value::get_string(dynamic_string &val, const char *pDef) const\r
456     {\r
457         if (is_string())\r
458         {\r
459             val = m_data.m_pStr;\r
460             return true;\r
461         }\r
462         else\r
463             return convert_to_string(val, pDef);\r
464     }\r
465 \r
466     inline bool json_value::as_bool(bool def) const\r
467     {\r
468         bool result;\r
469         get_bool(result, def);\r
470         return result;\r
471     }\r
472 \r
473     inline int json_value::as_int(int def) const\r
474     {\r
475         int32 result;\r
476         get_numeric(result, def);\r
477         return result;\r
478     }\r
479 \r
480     inline int json_value::as_int32(int32 def) const\r
481     {\r
482         int32 result;\r
483         get_numeric(result, def);\r
484         return result;\r
485     }\r
486 \r
487     inline uint32 json_value::as_uint32(uint32 def) const\r
488     {\r
489         uint32 result;\r
490         get_numeric(result, def);\r
491         return result;\r
492     }\r
493 \r
494     inline int64_t json_value::as_int64(int64_t def) const\r
495     {\r
496         int64_t result;\r
497         get_numeric(result, def);\r
498         return result;\r
499     }\r
500 \r
501     inline uint64_t json_value::as_uint64(uint64_t def) const\r
502     {\r
503         uint64_t result;\r
504         get_numeric(result, def);\r
505         return result;\r
506     }\r
507 \r
508     inline float json_value::as_float(float def) const\r
509     {\r
510         float result;\r
511         get_numeric(result, def);\r
512         return result;\r
513     }\r
514 \r
515     inline double json_value::as_double(double def) const\r
516     {\r
517         double result;\r
518         get_numeric(result, def);\r
519         return result;\r
520     }\r
521 \r
522     // Returns value as a string, or the default string if the value cannot be converted.\r
523     inline dynamic_string json_value::as_string(const char *pDef) const\r
524     {\r
525         dynamic_string result;\r
526         get_string(result, pDef);\r
527         return result;\r
528     }\r
529 \r
530     // Returns pointer to null terminated string or NULL if the value is not a string.\r
531     inline const char *json_value::as_string_ptr(const char *pDef) const\r
532     {\r
533         return is_string() ? m_data.m_pStr : pDef;\r
534     }\r
535 \r
536     inline bool json_value::operator!=(const json_value &other) const\r
537     {\r
538         return !(*this == other);\r
539     }\r
540 \r
541     inline void json_value::swap(json_value &other)\r
542     {\r
543         std::swap(m_type, other.m_type);\r
544         VOGL_ASSUME(sizeof(m_data.m_nVal) == sizeof(m_data));\r
545         std::swap(m_data.m_nVal, other.m_data.m_nVal);\r
546     }\r
547 \r
548     inline void json_value::set_line(uint line)\r
549     {\r
550         m_line = line;\r
551     }\r
552 \r
553     inline uint json_value::get_line() const\r
554     {\r
555         return m_line;\r
556     }\r
557 \r
558     template <typename T>\r
559     bool json_node::get_value_as_int(const char *pKey, T &val, T def) const\r
560     {\r
561         val = def;\r
562 \r
563         int index = find_key(pKey);\r
564         if (index < 0)\r
565             return false;\r
566 \r
567         int64_t v;\r
568         if (!get_value(index).get_numeric(v, 0))\r
569             return false;\r
570 \r
571         if ((v < int_traits<T>::cMin) || (v > int_traits<T>::cMax))\r
572             return false;\r
573         val = static_cast<T>(v);\r
574         return true;\r
575     }\r
576 \r
577     inline bool json_node::operator==(const json_node &other) const\r
578     {\r
579         if (m_is_object != other.m_is_object)\r
580             return false;\r
581         if (m_keys.size() != other.m_keys.size())\r
582             return false;\r
583         if (m_values.size() != other.m_values.size())\r
584             return false;\r
585         if (m_is_object)\r
586         {\r
587             for (uint i = 0; i < m_values.size(); i++)\r
588             {\r
589                 int j = other.find_key(m_keys[i].get_ptr());\r
590                 if (j == cInvalidIndex)\r
591                     return false;\r
592 \r
593                 if (m_values[i] != other.m_values[j])\r
594                     return false;\r
595             }\r
596         }\r
597         else\r
598         {\r
599             for (uint i = 0; i < m_values.size(); i++)\r
600             {\r
601                 if (m_values[i] != other.m_values[i])\r
602                     return false;\r
603             }\r
604         }\r
605         return true;\r
606     }\r
607 \r
608     // Parent/child retrieval\r
609     inline const json_node *json_node::get_parent() const\r
610     {\r
611         return m_pParent;\r
612     }\r
613 \r
614     // true if the value at the specified index is an object or array.\r
615     inline bool json_node::is_child(uint index) const\r
616     {\r
617         return get_value_type(index) == cJSONValueTypeNode;\r
618     }\r
619 \r
620     // true if the value at the specified index is an object.\r
621     inline bool json_node::is_child_object(uint index) const\r
622     {\r
623         const json_node *pChild = get_child(index);\r
624         if (!pChild)\r
625             return false;\r
626         return pChild->is_object();\r
627     }\r
628 \r
629     // true if the value at the specified index is an array.\r
630     inline bool json_node::is_child_array(uint index) const\r
631     {\r
632         const json_node *pChild = get_child(index);\r
633         if (!pChild)\r
634             return false;\r
635         return pChild->is_array();\r
636     }\r
637 \r
638     // Returns pointer to the child array or object at the specified index, or NULL if the value is not an array or object.\r
639     inline const json_node *json_node::get_child(uint index) const\r
640     {\r
641         return m_values[index].get_node_ptr();\r
642     }\r
643 \r
644     inline json_node *json_node::get_child(uint index)\r
645     {\r
646         return m_values[index].get_node_ptr();\r
647     }\r
648 \r
649     // Object/array info\r
650     inline bool json_node::is_object() const\r
651     {\r
652         return m_is_object;\r
653     }\r
654 \r
655     inline bool json_node::is_array() const\r
656     {\r
657         return !m_is_object;\r
658     }\r
659 \r
660     inline uint json_node::size() const\r
661     {\r
662         return m_values.size();\r
663     }\r
664 \r
665     inline bool json_node::has_key(const char *pKey) const\r
666     {\r
667         return find_key(pKey) >= 0;\r
668     }\r
669 \r
670     // true if the value associated with the specified key is an object\r
671     inline bool json_node::has_object(const char *pKey) const\r
672     {\r
673         int index = find_key(pKey);\r
674         if (index < 0)\r
675             return false;\r
676         return is_child_object(index);\r
677     }\r
678 \r
679     // true if the value associated with the specified key is an array\r
680     inline bool json_node::has_array(const char *pKey) const\r
681     {\r
682         int index = find_key(pKey);\r
683         if (index < 0)\r
684             return false;\r
685         return is_child_array(index);\r
686     }\r
687 \r
688     inline const dynamic_string &json_node::get_key(uint index) const\r
689     {\r
690         return m_keys[index];\r
691     }\r
692 \r
693     // returns g_null_json_value if the key does not exist\r
694     inline const json_value &json_node::operator[](const char *pKey) const\r
695     {\r
696         return find_value(pKey);\r
697     }\r
698 \r
699     // Value retrieval/finding\r
700     inline json_value_type_t json_node::get_value_type(uint index) const\r
701     {\r
702         return m_values[index].get_type();\r
703     }\r
704 \r
705     inline const json_value &json_node::get_value(uint index) const\r
706     {\r
707         return m_values[index];\r
708     }\r
709 \r
710     inline const json_value &json_node::operator[](uint index) const\r
711     {\r
712         return m_values[index];\r
713     }\r
714 \r
715     // Returns NULL if the value is not an object or array.\r
716     inline const json_node *json_node::get_value_as_object_or_array(uint index) const\r
717     {\r
718         return get_child(index);\r
719     }\r
720 \r
721     inline const json_node *json_node::get_value_as_object(uint index) const\r
722     {\r
723         if (!is_child_object(index))\r
724             return NULL;\r
725         else\r
726             return get_child(index);\r
727     }\r
728 \r
729     inline const json_node *json_node::get_value_as_array(uint index) const\r
730     {\r
731         if (!is_child_array(index))\r
732             return NULL;\r
733         else\r
734             return get_child(index);\r
735     }\r
736 \r
737     inline bool json_node::operator!=(const json_node &other) const\r
738     {\r
739         return !(*this == other);\r
740     }\r
741 \r
742     // Retrieves the json_value at the specified index.\r
743     inline json_value &json_node::get_value(uint index)\r
744     {\r
745         return m_values[index];\r
746     }\r
747 \r
748     inline json_value &json_node::operator[](uint index)\r
749     {\r
750         return m_values[index];\r
751     }\r
752 \r
753     // Sets the parent node of this node.\r
754     inline void json_node::set_parent(const json_node *pParent)\r
755     {\r
756         m_pParent = pParent;\r
757     }\r
758 \r
759     inline void json_node::init_object()\r
760     {\r
761         set_is_object(true);\r
762     }\r
763 \r
764     inline void json_node::init_array()\r
765     {\r
766         set_is_object(false);\r
767     }\r
768 \r
769     // Changes the number of elements in this node. Enlarging will add empty keys (for objects), and values of type cJSONValueTypeNull.\r
770     inline uint json_node::enlarge(uint n)\r
771     {\r
772         uint cur_size = size();\r
773         resize(cur_size + n);\r
774         return cur_size;\r
775     }\r
776 \r
777     // Retrieves the json_value associated with a key, or adds a new named key/value to the node, which must be an object. The newly added json_value will have type cJSONValueTypeNull.\r
778     inline json_value &json_node::get_or_add(const dynamic_string &key)\r
779     {\r
780         return get_or_add(key.get_ptr());\r
781     }\r
782 \r
783     // Adds a named key/value to the node. The json_value will have type cJSONValueTypeNull. If the node is not an object it will be upgraded to an object.\r
784     inline json_value &json_node::add(const dynamic_string &key)\r
785     {\r
786         return add(key.get_ptr());\r
787     }\r
788 \r
789     // Adds a named child object to the node. If the node is not an object it will be upgraded to an object.\r
790     inline json_node &json_node::add_object(const dynamic_string &key)\r
791     {\r
792         return add_object(key.get_ptr());\r
793     }\r
794 \r
795     // Adds a named child array to the node. If the node is not an object it will be upgraded to an object.\r
796     inline json_node &json_node::add_array(const dynamic_string &key)\r
797     {\r
798         return add_array(key.get_ptr());\r
799     }\r
800 \r
801     // Adds a key/value to a node. If the node is not an object it will be upgraded to an object.\r
802     inline json_value &json_node::add_key_value(const dynamic_string &key, const json_value &val)\r
803     {\r
804         return add_key_value(key.get_ptr(), val);\r
805     }\r
806 \r
807     // Adds a new key/value to a node. pValueToParse must be JSON text.\r
808     inline bool add_key_and_parsed_value(const dynamic_string &key, const char *pValueToParse)\r
809     {\r
810         return add_key_and_parsed_value(key.get_ptr(), pValueToParse);\r
811     }\r
812 \r
813     inline bool json_node::erase(const dynamic_string &key)\r
814     {\r
815         return erase(key.get_ptr());\r
816     }\r
817 \r
818     // Set the light number associated with this node.\r
819     inline void json_node::set_line(uint line)\r
820     {\r
821         m_line = line;\r
822     }\r
823 \r
824     // Gets the light number associated with this node.\r
825     inline uint json_node::get_line() const\r
826     {\r
827         return m_line;\r
828     }\r
829 \r
830     template <typename T>\r
831     bool json_node::add_object(const char *pKey, const T &obj)\r
832     {\r
833         json_value &val = pKey ? add(pKey) : add_value();\r
834         return json_serialize(obj, val);\r
835     }\r
836 \r
837     template <typename T>\r
838     bool json_node::get_object(const char *pKey, T &obj) const\r
839     {\r
840         if (!pKey)\r
841         {\r
842             VOGL_ASSERT_ALWAYS;\r
843             return false;\r
844         }\r
845 \r
846         const json_value &val = find_value(pKey);\r
847         if (val == g_null_json_value)\r
848             return false;\r
849 \r
850         return json_deserialize(obj, val);\r
851     }\r
852 \r
853     template <typename T>\r
854     bool json_node::get_object(uint index, T &obj) const\r
855     {\r
856         return json_deserialize(obj, get_value(index));\r
857     }\r
858 \r
859     template <typename T>\r
860     inline bool json_node::add_vector(const char *pKey, const T &vec)\r
861     {\r
862         json_node &obj = pKey ? add_object(pKey) : *this;\r
863 \r
864         obj.add_key_value("type", "vector");\r
865 \r
866         uint size = vec.size();\r
867         obj.add_key_value("size", size);\r
868 \r
869         if (size)\r
870         {\r
871             json_node &elements = obj.add_array("elements");\r
872             elements.reserve(size);\r
873 \r
874             for (uint i = 0; i < size; i++)\r
875             {\r
876                 json_value &new_val = elements.add_value();\r
877                 if (!json_serialize(vec[i], new_val))\r
878                     return false;\r
879 \r
880                 if (new_val.is_node())\r
881                     new_val.get_node_ptr()->set_parent(&elements);\r
882             }\r
883         }\r
884 \r
885         return true;\r
886     }\r
887 \r
888     template <typename T>\r
889     inline bool json_node::get_vector(const char *pKey, T &vec) const\r
890     {\r
891         const json_node *pObj = pKey ? find_child_object(pKey) : this;\r
892         if (!pObj)\r
893             return false;\r
894 \r
895         if (!pObj->is_object())\r
896             return false;\r
897 \r
898         if (pObj->value_as_string("type") != "vector")\r
899             return false;\r
900 \r
901         uint64_t size64 = pObj->value_as_uint64("size");\r
902         if (size64 > cUINT32_MAX)\r
903             return false;\r
904 \r
905         uint size = static_cast<uint>(size64);\r
906 \r
907         vec.resize(size);\r
908 \r
909         if (size)\r
910         {\r
911             const json_node *pElements = pObj->find_child_array("elements");\r
912 \r
913             if ((!pElements) || (pElements->size() != size))\r
914                 return false;\r
915 \r
916             for (uint i = 0; i < size; i++)\r
917                 if (!json_deserialize(vec[i], pElements->get_value(i)))\r
918                     return false;\r
919         }\r
920 \r
921         return true;\r
922     }\r
923 \r
924     template <typename T>\r
925     inline bool json_node::add_map(const char *pKey, const T &map)\r
926     {\r
927         json_node &obj = pKey ? add_object(pKey) : *this;\r
928 \r
929         obj.add_key_value("type", "map");\r
930         obj.add_key_value("size", map.size());\r
931 \r
932         if (map.size())\r
933         {\r
934             json_node &arr_node = obj.add_array("objects");\r
935             arr_node.reserve(map.size());\r
936 \r
937             typename T::const_iterator end_it(map.end());\r
938             for (typename T::const_iterator it = map.begin(); it != end_it; ++it)\r
939             {\r
940                 json_node &element = arr_node.add_object();\r
941 \r
942                 json_value &val = element.add("key");\r
943                 json_serialize(it->first, val);\r
944                 if (val.is_node())\r
945                     val.get_node_ptr()->set_parent(&arr_node);\r
946 \r
947                 if (!is_empty_type<typename T::referent_type>::cValue)\r
948                 {\r
949                     json_value &val = element.add("value");\r
950                     json_serialize(it->second, val);\r
951                     if (val.is_node())\r
952                         val.get_node_ptr()->set_parent(&arr_node);\r
953                 }\r
954             }\r
955         }\r
956 \r
957         return true;\r
958     }\r
959 \r
960     template <typename T>\r
961     inline bool json_node::get_map(const char *pKey, T &map) const\r
962     {\r
963         const json_node *pObj = pKey ? find_child_object(pKey) : this;\r
964         if (!pObj)\r
965             return false;\r
966 \r
967         if (!pObj->is_object())\r
968             return false;\r
969 \r
970         if (pObj->value_as_string("type") != "map")\r
971             return false;\r
972 \r
973         if (!pObj->has_key("size"))\r
974             return false;\r
975 \r
976         uint64_t size64 = pObj->value_as_uint32("size");\r
977         if ((size64) && (!pObj->has_key("objects")))\r
978             return false;\r
979 \r
980         // TODO: fix this once vogl::vector supports 64-bit arrays\r
981         if (size64 > cUINT32_MAX)\r
982             return false;\r
983 \r
984         map.reset();\r
985 \r
986         if (!size64)\r
987             return true;\r
988 \r
989         uint size = static_cast<uint>(size64);\r
990 \r
991         map.reserve(size);\r
992 \r
993         const json_node *pObjects_arr = pObj->find_child_array("objects");\r
994         if (!pObjects_arr)\r
995             return false;\r
996 \r
997         if (pObjects_arr->size() != size)\r
998             return false;\r
999 \r
1000         for (uint i = 0; i < pObjects_arr->size(); i++)\r
1001         {\r
1002             const json_node *pArr_node = pObjects_arr->get_child(i);\r
1003             if (!pArr_node)\r
1004                 return false;\r
1005 \r
1006             const json_value &key_val = pArr_node->find_value("key");\r
1007             if (key_val == g_null_json_value)\r
1008                 return false;\r
1009 \r
1010             typename T::key_type key;\r
1011             if (!json_deserialize(key, key_val))\r
1012                 return false;\r
1013 \r
1014             typename T::referent_type val;\r
1015 \r
1016             if (!is_empty_type<typename T::referent_type>::cValue)\r
1017             {\r
1018                 const json_value &value_val = pArr_node->find_value("value");\r
1019                 if (value_val == g_null_json_value)\r
1020                     return false;\r
1021 \r
1022                 if (!json_deserialize(val, value_val))\r
1023                     return false;\r
1024             }\r
1025 \r
1026             if (!map.insert(key, val).second)\r
1027                 return false;\r
1028         }\r
1029 \r
1030         return true;\r
1031     }\r
1032 \r
1033     template <typename T>\r
1034     inline bool json_serialize(const T &v, json_value &val)\r
1035     {\r
1036         return v.json_serialize(val);\r
1037     }\r
1038 \r
1039     template <typename T>\r
1040     inline bool json_deserialize(T &v, const json_value &val)\r
1041     {\r
1042         return v.json_deserialize(val);\r
1043     }\r
1044 \r
1045     inline bool json_serialize(const int8 &v, json_value &val)\r
1046     {\r
1047         val = v;\r
1048         return true;\r
1049     }\r
1050 \r
1051     inline bool json_deserialize(int8 &v, const json_value &val)\r
1052     {\r
1053         return val.get_numeric(v);\r
1054     }\r
1055 \r
1056     inline bool json_serialize(const int16 &v, json_value &val)\r
1057     {\r
1058         val = v;\r
1059         return true;\r
1060     }\r
1061 \r
1062     inline bool json_deserialize(int16 &v, const json_value &val)\r
1063     {\r
1064         return val.get_numeric(v);\r
1065     }\r
1066 \r
1067     inline bool json_serialize(const int32 &v, json_value &val)\r
1068     {\r
1069         val = v;\r
1070         return true;\r
1071     }\r
1072 \r
1073     inline bool json_deserialize(int32 &v, const json_value &val)\r
1074     {\r
1075         return val.get_numeric(v);\r
1076     }\r
1077 \r
1078     inline bool json_serialize(const int64_t &v, json_value &val)\r
1079     {\r
1080         val = v;\r
1081         return true;\r
1082     }\r
1083 \r
1084     inline bool json_deserialize(int64_t &v, const json_value &val)\r
1085     {\r
1086         return val.get_numeric(v);\r
1087     }\r
1088 \r
1089     inline bool json_serialize(const uint8 &v, json_value &val)\r
1090     {\r
1091         val = v;\r
1092         return true;\r
1093     }\r
1094 \r
1095     inline bool json_deserialize(uint8 &v, const json_value &val)\r
1096     {\r
1097         return val.get_numeric(v);\r
1098     }\r
1099 \r
1100     inline bool json_serialize(const uint16 &v, json_value &val)\r
1101     {\r
1102         val = v;\r
1103         return true;\r
1104     }\r
1105 \r
1106     inline bool json_deserialize(uint16 &v, const json_value &val)\r
1107     {\r
1108         return val.get_numeric(v);\r
1109     }\r
1110 \r
1111     inline bool json_serialize(const uint32 &v, json_value &val)\r
1112     {\r
1113         val = v;\r
1114         return true;\r
1115     }\r
1116 \r
1117     inline bool json_deserialize(uint32 &v, const json_value &val)\r
1118     {\r
1119         return val.get_numeric(v);\r
1120     }\r
1121 \r
1122     inline bool json_serialize(const uint64_t &v, json_value &val)\r
1123     {\r
1124         val = v;\r
1125         return true;\r
1126     }\r
1127 \r
1128     inline bool json_deserialize(uint64_t &v, const json_value &val)\r
1129     {\r
1130         return val.get_numeric(v);\r
1131     }\r
1132 \r
1133     inline bool json_serialize(const float &v, json_value &val)\r
1134     {\r
1135         val = v;\r
1136         return true;\r
1137     }\r
1138 \r
1139     inline bool json_deserialize(float &v, const json_value &val)\r
1140     {\r
1141         return val.get_numeric(v);\r
1142     }\r
1143 \r
1144     inline bool json_serialize(const double &v, json_value &val)\r
1145     {\r
1146         val = v;\r
1147         return true;\r
1148     }\r
1149 \r
1150     inline bool json_deserialize(double &v, const json_value &val)\r
1151     {\r
1152         return val.get_numeric(v);\r
1153     }\r
1154 \r
1155     inline bool json_serialize(const json_node &v, json_value &val)\r
1156     {\r
1157         val.set_value(&v);\r
1158         return true;\r
1159     }\r
1160 \r
1161     inline bool json_deserialize(json_node &v, const json_value &val)\r
1162     {\r
1163         if (!val.is_object_or_array())\r
1164             return false;\r
1165         v = *val.get_node_ptr();\r
1166         return true;\r
1167     }\r
1168 \r
1169     template <typename Key, typename Value, typename Hasher, typename Equals>\r
1170     inline bool json_serialize(const hash_map<Key, Value, Hasher, Equals> &hash_map, json_value &val)\r
1171     {\r
1172         json_node *pObj = val.init_object();\r
1173         return pObj->add_map(NULL, hash_map);\r
1174     }\r
1175 \r
1176     template <typename Key, typename Value, typename Hasher, typename Equals>\r
1177     inline bool json_deserialize(hash_map<Key, Value, Hasher, Equals> &hash_map, const json_value &val)\r
1178     {\r
1179         if (!val.is_object())\r
1180             return false;\r
1181         const json_node *pNode = val.get_node_ptr();\r
1182         return pNode->get_map(NULL, hash_map);\r
1183     }\r
1184 \r
1185     template <typename Key, typename Value, typename Hasher, typename Equals, typename Allocator>\r
1186     inline bool json_serialize(const rh_hash_map<Key, Value, Hasher, Equals, Allocator> &rh_hash_map, json_value &val)\r
1187     {\r
1188         json_node *pObj = val.init_object();\r
1189         return pObj->add_map(NULL, rh_hash_map);\r
1190     }\r
1191 \r
1192     template <typename Key, typename Value, typename Hasher, typename Equals, typename Allocator>\r
1193     inline bool json_deserialize(rh_hash_map<Key, Value, Hasher, Equals, Allocator> &rh_hash_map, const json_value &val)\r
1194     {\r
1195         if (!val.is_object())\r
1196             return false;\r
1197         const json_node *pNode = val.get_node_ptr();\r
1198         return pNode->get_map(NULL, rh_hash_map);\r
1199     }\r
1200 \r
1201     template <typename Key, typename Value, typename LessComp, typename EqualComp, uint MaxLevels>\r
1202     inline bool json_serialize(const vogl::map<Key, Value, LessComp, EqualComp, MaxLevels> &map, json_value &val)\r
1203     {\r
1204         json_node *pObj = val.init_object();\r
1205         return pObj->add_map(NULL, map);\r
1206     }\r
1207 \r
1208     template <typename Key, typename Value, typename LessComp, typename EqualComp, uint MaxLevels>\r
1209     inline bool json_deserialize(vogl::map<Key, Value, LessComp, EqualComp, MaxLevels> &map, const json_value &val)\r
1210     {\r
1211         if (!val.is_object())\r
1212             return false;\r
1213         const json_node *pNode = val.get_node_ptr();\r
1214         return pNode->get_map(NULL, map);\r
1215     }\r
1216 \r
1217     template <typename T>\r
1218     inline bool json_serialize(const vogl::vector<T> &vec, json_value &val)\r
1219     {\r
1220         json_node *pObj = val.init_object();\r
1221         return pObj->add_vector(NULL, vec);\r
1222     }\r
1223 \r
1224     template <typename T>\r
1225     inline bool json_deserialize(vogl::vector<T> &vec, const json_value &val)\r
1226     {\r
1227         if (!val.is_object())\r
1228             return false;\r
1229         const json_node *pNode = val.get_node_ptr();\r
1230         return pNode->get_vector(NULL, vec);\r
1231     }\r
1232 \r
1233     template <typename T, uint N>\r
1234     inline bool json_serialize(const vogl::growable_array<T, N> &vec, json_value &val)\r
1235     {\r
1236         json_node *pObj = val.init_object();\r
1237         return pObj->add_vector(NULL, vec);\r
1238     }\r
1239 \r
1240     template <typename T, uint N>\r
1241     inline bool json_deserialize(vogl::growable_array<T, N> &vec, const json_value &val)\r
1242     {\r
1243         if (!val.is_object())\r
1244             return false;\r
1245         const json_node *pNode = val.get_node_ptr();\r
1246         return pNode->get_vector(NULL, vec);\r
1247     }\r
1248 \r
1249     // root value manipulation\r
1250     inline const json_value &json_document::get_value() const\r
1251     {\r
1252         return *this;\r
1253     }\r
1254 \r
1255     inline json_value &json_document::get_value()\r
1256     {\r
1257         return *this;\r
1258     }\r
1259 \r
1260     // This returns a pointer because a valid JSON document can be a single value (in which case the document's value is not a node pointer).\r
1261     inline const json_node *json_document::get_root() const\r
1262     {\r
1263         return get_node_ptr();\r
1264     }\r
1265 \r
1266     inline json_node *json_document::get_root()\r
1267     {\r
1268         return get_node_ptr();\r
1269     }\r
1270 \r
1271     inline void json_document::clear(bool reinitialize_to_object)\r
1272     {\r
1273         json_value::clear();\r
1274         if (reinitialize_to_object)\r
1275             init_object();\r
1276     }\r
1277 \r
1278     // document's filename\r
1279     inline const dynamic_string &json_document::get_filename() const\r
1280     {\r
1281         return m_filename;\r
1282     }\r
1283 \r
1284     inline void json_document::set_filename(const char *pFilename)\r
1285     {\r
1286         m_filename.set(pFilename ? pFilename : "");\r
1287     }\r
1288 \r
1289     // error messages due to failed parses\r
1290     inline const dynamic_string &json_document::get_error_msg() const\r
1291     {\r
1292         return m_error_msg;\r
1293     }\r
1294 \r
1295     inline uint json_document::get_error_line() const\r
1296     {\r
1297         return m_error_line;\r
1298     }\r
1299 \r
1300     inline void json_document::clear_error()\r
1301     {\r
1302         m_error_msg.clear();\r
1303         m_error_line = 0;\r
1304     }\r
1305 \r
1306 } // namespace vogl\r