]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_json.h
Initial vogl checkin
[vogl] / src / voglcore / vogl_json.h
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 // File: vogl_json.h
28 //
29 // TODO: Ensure UBJ format is compatible with the latest specification. I'm using the spec from late 2011.
30 //
31 #ifndef VOGL_JSON_H
32 #define VOGL_JSON_H
33
34 #ifdef WIN32
35 #pragma once
36 #endif
37
38 #include "vogl_core.h"
39 #include "vogl_strutils.h"
40 #include "vogl_vec.h"
41 #include "vogl_object_pool.h"
42
43 #define VOGL_TEXT_JSON_EXTENSION "json"
44 #define VOGL_BINARY_JSON_EXTENSION "ubj"
45
46 namespace vogl
47 {
48
49     class json_growable_char_buf;
50     class json_deserialize_buf_ptr;
51     class json_document;
52
53     template <typename T, uint N>
54     class growable_array;
55
56     template <typename Key, typename Value, typename Hasher, typename Equals>
57     class hash_map;
58
59     template <typename Key, typename Value, typename Hasher, typename Equals, typename Allocator>
60     class rh_hash_map;
61
62     template <typename Key, typename Value, typename LessComp, typename EqualComp, uint MaxLevels>
63     class map;
64
65     enum json_value_type_t
66     {
67         cJSONValueTypeNull = 0,
68         cJSONValueTypeBool,
69         cJSONValueTypeInt, // 64-bit signed integer
70         cJSONValueTypeDouble,
71         cJSONValueTypeString,
72         cJSONValueTypeNode // A node is a JSON object or array.
73     };
74
75     enum
76     {
77         CMaxLineLenDefault = 160
78     };
79
80     class json_node;
81
82     // A simple value variant.
83     union json_value_data_t
84     {
85         int64_t m_nVal;
86         double m_flVal;
87         json_node *m_pNode;
88         char *m_pStr;
89     };
90
91     // Parsing error coordinate.
92     struct json_error_info_t
93     {
94         int m_error_line;
95         dynamic_string m_error_msg;
96
97         void set_error(uint line, const char *pMsg, ...) VOGL_ATTRIBUTE_PRINTF(3, 4);
98     };
99
100     // Node pool
101     typedef object_pool<json_node, object_pool_spinlock_locking_policy> json_node_object_pool;
102     extern json_node_object_pool *g_pJSON_node_pool;
103
104     void json_node_pool_init();
105
106     inline json_node_object_pool *get_json_node_pool()
107     {
108         if (!g_pJSON_node_pool)
109             json_node_pool_init();
110         return g_pJSON_node_pool;
111     }
112
113     // A json_value is a null, bool, int64_t, double, a heap pointer to a null terminated string, or a heap pointer to a json_node (which is either a object or array).
114     // A json_value owns any string/node it points to, so the referenced strings/json_node is deleted upon destruction.
115     class json_value
116     {
117         friend class json_node;
118
119     public:
120         inline json_value();
121         inline json_value(bool val);
122         inline json_value(int32 nVal);
123         inline json_value(uint32 nVal);
124         inline json_value(int64_t nVal);
125         // Note uint64_t values may be encoded as hex strings or int64_t
126         inline json_value(uint64_t nVal);
127         inline json_value(double flVal);
128         inline json_value(char *pStr);
129         inline json_value(const char *pStr);
130         inline json_value(const dynamic_string &str);
131         inline json_value(const json_node *pNode);
132         inline json_value(json_value_type_t type);
133         inline ~json_value();
134
135         json_value(const json_value &other);
136         json_value &operator=(const json_value &rhs);
137
138         inline json_value_type_t get_type() const;
139
140         inline const json_value_data_t &get_raw_data() const;
141
142         json_value_data_t &get_raw_data();
143
144         inline bool is_null() const;
145         inline bool is_valid() const;
146         inline bool is_bool() const;
147         inline bool is_int() const;
148         inline bool is_double() const;
149         inline bool is_numeric() const;
150         inline bool is_string() const;
151         inline bool is_node() const;
152         inline bool is_object_or_array() const;
153         inline bool is_object() const;
154         inline bool is_array() const;
155
156         inline const json_node *get_node_ptr() const;
157
158         inline json_node *get_node_ptr();
159
160         inline void clear();
161
162         inline void assume_ownership(json_value &src_val);
163
164         inline void release_ownership(json_value &dst_value);
165
166         inline void init(json_value_type_t type);
167         inline json_node *init_object();
168         inline json_node *init_array();
169
170         inline json_node *set_value_to_object(json_node *pParent = NULL);
171         inline json_node *set_value_to_array(json_node *pParent = NULL);
172         inline json_node *set_value_to_node(bool is_object, json_node *pParent = NULL);
173
174         inline void set_value_to_null();
175         inline void set_value(bool val);
176         inline void set_value(int8 nVal);
177         inline void set_value(int16 nVal);
178         inline void set_value(int32 nVal);
179         inline void set_value(int64_t nVal);
180
181         inline void set_value(uint8 nVal);
182         inline void set_value(uint16 nVal);
183         inline void set_value(uint32 nVal);
184
185         // Note uint64_t values may be encoded as hex strings or int64_t
186         void set_value(uint64_t nVal);
187
188         inline void set_value(double flVal);
189         inline void set_value(const char *pStr);
190         inline void set_value(const dynamic_string &str);
191
192         // copies contents of *pNode into a new node, sets value to point to new node.
193         inline void set_value(const json_node *pNode);
194
195         inline void set_value_assume_ownership(char *pStr);
196         inline void set_value_assume_ownership(json_node *pNode);
197
198         inline json_value &operator=(bool val);
199         inline json_value &operator=(int32 nVal);
200         inline json_value &operator=(uint32 nVal);
201         inline json_value &operator=(int64_t nVal);
202         inline json_value &operator=(uint64_t nVal);
203         inline json_value &operator=(double flVal);
204         inline json_value &operator=(const char *pStr);
205
206         // Attempts to convert a JSON value to each type.
207         // Returns false and sets val to def if the value cannot be converted (out of range, or type is obviously incompatible).
208         // 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.
209         inline bool get_bool(bool &val, bool def = false) const;
210         bool get_numeric(int8 &val, int8 def = 0) const;
211         bool get_numeric(int16 &val, int16 def = 0) const;
212         inline bool get_numeric(int32 &val, int32 def = 0) const;
213         inline bool get_numeric(int64_t &val, int64_t def = 0) const;
214
215         bool get_numeric(uint8 &val, uint8 def = 0) const;
216         bool get_numeric(uint16 &val, uint16 def = 0) const;
217         bool get_numeric(uint32 &val, uint32 def = 0) const;
218         inline bool get_numeric(uint64_t &val, uint64_t def = 0) const;
219
220         inline bool get_numeric(float &val, float def = 0.0f) const;
221         inline bool get_numeric(double &val, double def = 0.0f) const;
222
223         inline bool get_string(dynamic_string &val, const char *pDef = "") const;
224         bool get_enum(const char **pStringList, int &val, int def) const;
225
226         inline bool as_bool(bool def = false) const;
227         inline int as_int(int def = 0) const;
228         inline int as_int32(int32 def = 0) const;
229         inline uint32 as_uint32(uint32 def = 0) const;
230         inline int64_t as_int64(int64_t def = 0) const;
231         inline uint64_t as_uint64(uint64_t def = 0) const;
232         inline float as_float(float def = 0.0f) const;
233         inline double as_double(double def = 0.0f) const;
234
235         // Returns value as a string, or the default string if the value cannot be converted.
236         inline dynamic_string as_string(const char *pDef = "") const;
237
238         // Returns pointer to null terminated string or NULL if the value is not a string.
239         inline const char *as_string_ptr(const char *pDef = NULL) const;
240
241         inline bool operator==(const json_value &other) const;
242         inline bool operator!=(const json_value &other) const;
243
244         inline void swap(json_value &other);
245
246         // Deserialize value from a UTF8 file, null terminated string or buffer.
247         bool deserialize_file(const char *pFilename, json_error_info_t *pError_info = NULL);
248         bool deserialize(FILE *pFile, json_error_info_t *pError_info = NULL);
249         bool deserialize(const vogl::vector<char> &buf, json_error_info_t *pError_info = NULL);
250         bool deserialize(const char *pStr, json_error_info_t *pError_info = NULL);
251         bool deserialize(const dynamic_string &str, json_error_info_t *pError_info = NULL);
252         bool deserialize(const char *pBuf, size_t buf_size, json_error_info_t *pError_info = NULL);
253
254         // Serialize to a UTF8 file, a growable buffer, or a string
255         bool serialize_to_file(const char *pFilename, bool formatted = true, uint max_line_len = CMaxLineLenDefault) const;
256         bool serialize(FILE *pFile, bool formatted = true, uint max_line_len = CMaxLineLenDefault) const;
257         void serialize(vogl::vector<char> &buf, bool formatted = true, uint cur_indent = 0, bool null_terminate = true, uint max_line_len = CMaxLineLenDefault) const;
258         // Serializes to a dynamic_string
259         dynamic_string &serialize(dynamic_string &str, bool formatted = true, uint cur_indent = 0, uint max_line_len = CMaxLineLenDefault) const;
260         // Serialize to stdout.
261         void print(bool formatted = true, uint cur_indent = 0, uint max_line_len = CMaxLineLenDefault) const;
262
263         // Deserialize from Universal Binary JSON (UBJ).
264         bool binary_deserialize(const uint8 *pBuf, size_t buf_size);
265         bool binary_deserialize_file(const char *pFilename);
266         bool binary_deserialize(FILE *pFile);
267         bool binary_deserialize(const vogl::vector<uint8> &buf);
268
269         // Serialize from UBJ.
270         void binary_serialize(vogl::vector<uint8> &buf) const;
271         bool binary_serialize_to_file(const char *pFilename);
272         bool binary_serialize(FILE *pFile);
273
274         bool is_equal(const json_value &other, double tol = 1e-8) const;
275
276         // Returns true if all parent pointers are correct.
277         bool validate(const json_node *pParent = NULL) const;
278
279         void set_line(uint line);
280
281         uint get_line() const;
282
283     protected:
284         json_value_data_t m_data;
285         json_value_type_t m_type;
286         uint m_line;
287
288         bool convert_to_bool(bool &val, bool def) const;
289         bool convert_to_int32(int32 &val, int32 def) const;
290         bool convert_to_int64(int64_t &val, int64_t def) const;
291         bool convert_to_uint64(uint64_t &val, uint64_t def) const;
292         bool convert_to_float(float &val, float def) const;
293         bool convert_to_double(double &val, double def) const;
294         bool convert_to_string(dynamic_string &val, const char *pDef) const;
295
296         inline void free_data()
297         {
298             if (m_type == cJSONValueTypeString)
299                 vogl_free(m_data.m_pStr);
300             else if (m_type == cJSONValueTypeNode)
301                 get_json_node_pool()->destroy(m_data.m_pNode);
302         }
303
304         bool deserialize_node(json_deserialize_buf_ptr &pStr, json_node *pParent, uint level, json_error_info_t &error_info);
305         bool estimate_deserialized_string_size(json_deserialize_buf_ptr &pStr, json_error_info_t &error_info, uint &size);
306         bool deserialize_quoted_string_to_buf(char *&pBuf, uint buf_size, json_deserialize_buf_ptr &pStr, json_error_info_t &error_info);
307         bool deserialize_string(json_deserialize_buf_ptr &pStr, json_error_info_t &error_info);
308         bool deserialize_number(json_deserialize_buf_ptr &pStr, json_error_info_t &error_info);
309         bool deserialize(json_deserialize_buf_ptr &pStr, json_node *pParent, uint level, json_error_info_t &error_info);
310
311         void binary_serialize_value(vogl::vector<uint8> &buf) const;
312         bool binary_deserialize(const uint8 *&pBuf, const uint8 *pBuf_end, json_node *pParent, uint depth);
313
314     private:
315         // Optional: Forbid (the super annoying) implicit conversions of all pointers/const pointers to bool, except for the specializations below.
316         // Purposely unimplemented. Constructor will be caught at compile time, and operator= at link time.
317         // TODO: Is this confusing crap needed anymore?
318         template <typename T>
319         json_value(T *);
320         template <typename T>
321         json_value(const T *);
322         template <typename T>
323         json_value &operator=(T *);
324         template <typename T>
325         json_value &operator=(const T *);
326     };
327
328     VOGL_DEFINE_BITWISE_MOVABLE(json_value);
329
330     extern json_value g_null_json_value;
331
332     typedef vogl::vector<dynamic_string> dynamic_string_array;
333     typedef vogl::vector<json_value> json_value_array;
334
335     // A json_node can be either a JSON object (key/values) or array (values only).
336     // It contains one or two separate unsorted arrays: one for keys (JSON objects only), and another for values (JSON objects or arrays).
337     // json_node's are multisets, not sets, so duplicate keys do not cause errors, although the find() helpers will only find the first key.
338     // The order of the key/value arrays is preserved in this design, but find()'s in large objects/array can be slow.
339     // json_value's may point to other child json_nodes, which are allocated and freed from the heap.
340     // The keys are simple zero terminated strings, and the values are instances of the json_value class above.
341     // This design allows all keys/values at each object/array level to be stored in simple contiguous arrays.
342     // Each json_node has a pointer to its parent, or NULL for the root.
343     // Note that json_values which are not json_node's don't have pointers to their owners nodes, which can be annoying.
344     class json_node
345     {
346         friend class json_value;
347
348     public:
349         json_node();
350         json_node(const json_node &other);
351         json_node(const json_node *pParent, bool is_object);
352         ~json_node();
353
354         json_node &operator=(const json_node &rhs);
355
356         // Serialize to buffer.
357         void serialize(vogl::vector<char> &buf, bool formatted = true, uint cur_index = 0, bool null_terminate = true, uint max_line_len = CMaxLineLenDefault) const;
358
359         void serialize(dynamic_string &str, bool formatted = true, uint cur_index = 0, uint max_line_len = CMaxLineLenDefault) const;
360
361         void binary_serialize(vogl::vector<uint8> &buf) const;
362
363         // Parent/child retrieval
364         inline const json_node *get_parent() const;
365
366         // true if the value at the specified index is an object or array.
367         inline bool is_child(uint index) const;
368
369         // true if the value at the specified index is an object.
370         inline bool is_child_object(uint index) const;
371
372         // true if the value at the specified index is an array.
373         inline bool is_child_array(uint index) const;
374
375         // Finds the specified child (case insensitive), or NULL if the child cannot be found.
376         const json_node *find_child(const char *pKey) const;
377         json_node *find_child(const char *pKey);
378
379         // Finds the specified child object (case insensitive), or NULL if the child cannot be found or if the child is not an object.
380         const json_node *find_child_object(const char *pKey) const;
381         json_node *find_child_object(const char *pKey);
382
383         // Finds the specified child object (case insensitive), or NULL if the child cannot be found or if the child is not an array.
384         const json_node *find_child_array(const char *pKey) const;
385         json_node *find_child_array(const char *pKey);
386
387         // true if all children are plain values (i.e. not arrays or objects)
388         bool are_all_children_values() const;
389
390         // true if all children are objects
391         bool are_all_children_objects() const;
392
393         // true if all children are arrays
394         bool are_all_children_arrays() const;
395
396         // true if all children are objects or arrays
397         bool are_all_children_objects_or_arrays() const;
398
399         // Returns pointer to the child array or object at the specified index, or NULL if the value is not an array or object.
400         inline const json_node *get_child(uint index) const;
401         inline json_node *get_child(uint index);
402
403         // true if any of the values in this node are objects or arrays.
404         bool has_children() const;
405
406         // Object/array info
407         inline bool is_object() const;
408         inline bool is_array() const;
409         inline uint size() const;
410
411         // Key retrieval/finding
412
413         // Returns cInvalidIndex (-1) if key was not found. Search is case insensitive.
414         int find_key(const char *pKey) const;
415
416         int find_child(const json_node *pNode) const;
417
418         inline bool has_key(const char *pKey) const;
419
420         // true if the value associated with the specified key is an object
421         inline bool has_object(const char *pKey) const;
422
423         // true if the value associated with the specified key is an array
424         inline bool has_array(const char *pKey) const;
425
426         inline const dynamic_string &get_key(uint index) const;
427
428         // returns g_null_json_value if the key does not exist
429         const json_value &find_value(const char *pKey) const;
430         inline const json_value &operator[](const char *pKey) const;
431
432         json_value_type_t find_value_type(const char *pKey) const;
433
434         // Value retrieval/finding
435         inline json_value_type_t get_value_type(uint index) const;
436         inline const json_value &get_value(uint index) const;
437         inline const json_value &operator[](uint index) const;
438
439         // Returns NULL if the value is not an object or array.
440         inline const json_node *get_value_as_object_or_array(uint index) const;
441         inline const json_node *get_value_as_object(uint index) const;
442         inline const json_node *get_value_as_array(uint index) const;
443
444         // get() variants returns true if key was found and the JSON value could be losslessly converted to the destination type.
445         bool get_value_as_string(const char *pKey, dynamic_string &val, const char *pDef = "") const;
446         bool get_value_as_enum(const char *pKey, const char **pStringList, int &val, int def = 0) const;
447
448         // T may be int8, int16, int32 or uint8, uint16, uint32
449         // Internally this fetches the value as int64_t and attempts to convert. Returns false and sets val to def if out of range.
450         template <typename T>
451         bool get_value_as_int(const char *pKey, T &val, T def = 0) const;
452
453         bool get_value_as_int64(const char *pKey, int64_t &val, int64_t def = 0) const;
454         bool get_value_as_uint32(const char *pKey, uint32 &val, uint32 def = 0) const;
455         bool get_value_as_uint64(const char *pKey, uint64_t &val, uint64_t def = 0) const;
456         bool get_value_as_float(const char *pKey, float &val, float def = 0) const;
457         bool get_value_as_double(const char *pKey, double &val, double def = 0) const;
458         bool get_value_as_bool(const char *pKey, bool &val, bool def = false) const;
459
460         // The value_as() variants find the first key matching pKey and return its value, or the default if key was not found.
461         // 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.
462         dynamic_string value_as_string(const char *pKey, const char *pDef = "") const;
463         const char *value_as_string_ptr(const char *pKey, const char *pDef = "") const;
464         int value_as_int(const char *pKey, int def = 0) const;
465         int32 value_as_int32(const char *pKey, int32 def = 0) const;
466         int64_t value_as_int64(const char *pKey, int64_t def = 0) const;
467         uint32 value_as_uint32(const char *pKey, uint32 def = 0) const;
468         uint64_t value_as_uint64(const char *pKey, uint64_t def = 0) const;
469         float value_as_float(const char *pKey, float def = 0) const;
470         double value_as_double(const char *pKey, double def = 0) const;
471         bool value_as_bool(const char *pKey, bool def = false) const;
472
473         // The value_as() variants return the value, or the default if key can't be converted to the desired type.
474         // 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.
475         dynamic_string value_as_string(uint index, const char *pDef = "") const;
476         // Returns NULL if value is not a string.
477         const char *value_as_string_ptr(uint index, const char *pDef = "") const;
478         int value_as_int(uint index, int def = 0) const;
479         int32 value_as_int32(uint index, int32 def = 0) const;
480         int64_t value_as_int64(uint index, int64_t def = 0) const;
481         uint32 value_as_uint32(uint index, uint32 def = 0) const;
482         uint64_t value_as_uint64(uint index, uint64_t def = 0) const;
483         float value_as_float(uint index, float def = 0) const;
484         double value_as_double(uint index, double def = 0) const;
485         bool value_as_bool(uint index, bool def = false) const;
486
487         inline bool operator==(const json_node &other) const;
488         inline bool operator!=(const json_node &other) const;
489
490         // Modification
491         // TODO: Add splicing, insert
492
493         // Retrieves the json_value at the specified index.
494         inline json_value &get_value(uint index);
495         inline json_value &operator[](uint index);
496
497         // Sets the parent node of this node.
498         void set_parent(const json_node *pParent);
499
500         // Completely clears the node.
501         void clear();
502
503         // Sets this node to an object. If the node is an array it will be upgraded to an object with an array of empty keys.
504         void set_is_object(bool is_object);
505         void init_object();
506         void init_array();
507
508         // Changes the number of elements in this node. Enlarging will add empty keys (for objects), and values of type cJSONValueTypeNull.
509         void resize(uint new_size);
510         inline uint enlarge(uint n);
511
512         void reserve(uint new_capacity);
513
514         // 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.
515         json_value &get_or_add(const char *pKey);
516         json_value &get_or_add(const dynamic_string &key);
517
518         // 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.
519         json_value &add(const char *pKey);
520         json_value &add(const dynamic_string &key);
521
522         // Adds a named child object to the node. If the node is not an object it will be upgraded to an object.
523         json_node &add_object(const char *pKey);
524         json_node &add_object(const dynamic_string &key);
525
526         // Adds an unnamed object to the node.
527         json_node &add_object();
528
529         // Adds a named child array to the node. If the node is not an object it will be upgraded to an object.
530         json_node &add_array(const char *pKey);
531         json_node &add_array(const dynamic_string &key);
532
533         // Adds an unnamed array to the node.
534         json_node &add_array();
535
536         // Adds a key/value to a node. If the node is not an object it will be upgraded to an object.
537         json_value &add_key_value(const char *pKey, const json_value &val);
538         json_value &add_key_value(const dynamic_string &key, const json_value &val);
539
540         // Adds a new value to a node. If the node is an object then an empty key will be associated with the newly added value.
541         json_value &add_value();
542         json_value &add_value(const json_value &val);
543
544         // Adds a new key/value to a node. pValueToParse must be JSON text.
545         bool add_key_and_parsed_value(const char *pKey, const char *pValueToParse);
546         bool add_key_and_parsed_value(const dynamic_string &key, const char *pValueToParse);
547
548         // Adds a new value to a node. pValueToParse must be JSON text.
549         bool add_parsed_value(const char *pValueToParse);
550
551         // Retrieves a node's key. Asserts and returns a ref to g_empty_dynamic_string if the node is an array.
552         dynamic_string &get_key(uint index);
553
554         // Sets the key/value at the specified index. If the node is not an object it will be upgraded to one.
555         void set_key_value(uint index, const char *pKey, const json_value &val);
556         void set_key(uint index, const char *pKey);
557         void set_value(uint index, const json_value &val);
558
559         // Sets the value at the specified index. Takes ownership of any node pointed to by val. val will be cleared.
560         void set_value_assume_ownership(uint index, json_value &val);
561         void add_value_assume_ownership(json_value &val);
562         void add_key_value_assume_ownership(const char *pKey, json_value &val);
563
564         // Removes the specified key (case insensitive), returns true if the key is found.
565         bool erase(const char *pKey);
566         bool erase(const dynamic_string &key);
567
568         // Removes the specified key at index.
569         void erase(uint index);
570
571         // true if the node passes some basic tests for validity.
572         bool basic_validation(const json_node *pParent) const;
573
574         // true if the node, and its children, pass some basic tests for validity.
575         bool validate(const json_node *pParent) const;
576
577         // Returns a path string to this node, i.e. [root]/blah/[5]/cool, where cool is the current node, [5] is cool's parent (array item 5), etc.
578         dynamic_string get_path_to_node() const;
579
580         // pKey is not validated.
581         dynamic_string get_path_to_key(const char *pKey) const;
582
583         // index is not range checked.
584         dynamic_string get_path_to_item(uint index) const;
585
586         // Returns true if one or more keys has the same name, which is not valid JSON to many readers (although this seems to be a grey area of the spec).
587         // Recursively checks children nodes.
588         bool check_for_duplicate_keys() const;
589
590         // Set the line number associated with this node.
591         void set_line(uint line);
592
593         // Gets the line number associated with this node.
594         uint get_line() const;
595
596         // High-level container serialization/deserialization to/from JSON nodes.
597         // These methods add or retrieve entire containers (vectors, growable_array's, hash_map's, or map's) or user objects to/from JSON nodes.
598         // They assume the object, element or key/value types have overloaded "json_serialize" and "json_deserialize" functions defined, or you've defined overloaded json_serialize/json_deserialize members in the voglcore namespace.
599
600         // Adds a named or unnamed object to this node.
601         template <typename T>
602         bool add_object(const char *pKey, const T &obj);
603
604         // Retrieves a named object from this node.
605         template <typename T>
606         bool get_object(const char *pKey, T &obj) const;
607
608         // Retrieves the object at the specified index from this node.
609         template <typename T>
610         bool get_object(uint index, T &obj) const;
611
612         // add_vector() and get_vector() are compatible with vogl::vector or vogl::growable_array.
613         // If pKey is NULL, the hash map is read from the current node, otherwise it's read from the child object named pKey.
614         template <typename T>
615         bool add_vector(const char *pKey, const T &vec);
616
617         // If pKey is NULL, the hash mode is added to the current node, otherwise it's added to a child named pKey.
618         template <typename T>
619         bool get_vector(const char *pKey, T &vec) const;
620
621         // add_map() and get_map() are compatible with vogl::map and vogl::hash_map.
622         // If pKey is NULL, the hash mode is added to the current node, otherwise it's added to a child named pKey.
623         template <typename T>
624         bool add_map(const char *pKey, const T &hash_map);
625
626         // If pKey is NULL, the hash map is read from the current node, otherwise it's read from the child object named pKey.
627         template <typename T>
628         bool get_map(const char *pKey, T &hash_map) const;
629
630     private:
631         const json_node *m_pParent;
632
633         dynamic_string_array m_keys;
634         json_value_array m_values;
635
636         uint m_line;
637
638         bool m_is_object;
639
640         void ensure_is_object();
641         void serialize(json_growable_char_buf &buf, bool formatted, uint cur_index, uint max_line_len = CMaxLineLenDefault) const;
642     };
643
644     // json_document is an optional helper class that derives from json_value.
645     // It may optionally have been parsed from a file, string, or buffer and contains filename/error/line information.
646     // It's not derived from json_node because a valid JSON document may be a single value and not necessarily an object or array, although in practice it will be an object or maybe an array (and NOT a plain value) 99.999% of the time.
647     class json_document : public json_value
648     {
649         typedef json_value base;
650
651     public:
652         json_document();
653         explicit json_document(const json_value &other);
654         json_document(const json_document &other);
655         json_document(const char *pStr, const char *pFilename = "<string>");
656         json_document(const char *pBuf, uint n, const char *pFilename = "<buffer>");
657         json_document(json_value_type_t value_type);
658         ~json_document();
659
660         json_document &operator=(const json_document &rhs);
661         json_document &operator=(const json_value &rhs);
662
663         // root value manipulation
664         inline const json_value &get_value() const;
665         inline json_value &get_value();
666
667         // 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).
668         inline const json_node *get_root() const;
669         inline json_node *get_root();
670
671         inline void clear(bool reinitialize_to_object = true);
672
673         // Swaps two documents.
674         void swap(json_document &other);
675
676         // Deserialize UTF8 text from files, buffer, or a string.
677         bool deserialize_file(const char *pFilename);
678         bool deserialize(FILE *pFile, const char *pFilename = "<FILE>");
679         bool deserialize(const vogl::vector<char> &buf, const char *pFilename = "<buffer>");
680         bool deserialize(const char *pBuf, size_t n, const char *pFilename = "<buffer>");
681         bool deserialize(const char *pStr, const char *pFilename = "<string>");
682         bool deserialize(const dynamic_string &str, const char *pFilename = "<string>");
683
684         // document's filename
685         inline const dynamic_string &get_filename() const;
686         inline void set_filename(const char *pFilename);
687
688         // error messages due to failed parses
689         const dynamic_string &get_error_msg() const;
690         uint get_error_line() const;
691         void clear_error();
692
693     private:
694         dynamic_string m_filename;
695
696         dynamic_string m_error_msg;
697         uint m_error_line;
698     };
699
700     bool json_test();
701
702 } // namespace vogl
703
704 #include "vogl_json.inl"
705
706 #endif // VOGL_JSON_DOC_H