HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_JSONValue.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_JSONValue.h ( UT Library, C++)
7  *
8  * COMMENTS: This class represents a JSON object.
9  */
10 
11 #ifndef __UT_JSONValue__
12 #define __UT_JSONValue__
13 
14 #include "UT_API.h"
15 #include "UT_ValArray.h"
16 #include "UT_SymbolTable.h"
17 #include "UT_VectorTypes.h"
18 #include "UT_JSONValueMap.h"
19 #include "UT_JSONValueArray.h"
20 #include "UT_StringArray.h"
21 #include "UT_StringHolder.h"
22 #include "UT_Compression.h"
23 #include <SYS/SYS_Inline.h>
24 
25 class UT_JSONValueArray;
26 class UT_JSONValueMap;
27 class UT_JSONParser;
28 class UT_JSONWriter;
29 class UT_IStream;
30 class UT_IStream;
31 class UT_WorkBuffer;
32 
33 /// @brief Class to store JSON objects as C++ objects
34 ///
35 /// This class is able to represent a JSON object in its entirety. Arrays and
36 /// Maps store arrays and maps of JSON values.
37 ///
38 /// There are methods to load a JSONValue from a UT_JSONParser and to save to a
39 /// UT_JSONWriter object.
40 ///
41 /// To load an entire JSON file into memory, you can do something like
42 /// @code
43 /// UT_JSONIStream *is(utistream);
44 /// UT_JSONParser parser;
45 /// UT_JSONValue value;
46 /// if (!value.load(parser, *is))
47 /// reportFailure(parser.getErrors());
48 /// @endcode
49 ///
50 /// To save a value:
51 /// @code
52 /// UT_JSONWriterSubclass &os;
53 /// value.save(os);
54 /// @endcode
55 ///
56 /// Alternatively, it's possible to use the UT_JSONValue class from within
57 /// other UT_JSONHandle classes. For example, when loading key/value pairs for
58 /// an arbitrary map:
59 /// @code
60 /// bool
61 /// my_handle::jsonKey(UT_JSONParser &parser, const char *token, int64)
62 /// {
63 /// UT_String keyword;
64 /// UT_JSONValue value;
65 /// keyword.harden(token);
66 /// if (!value.load(parser))
67 /// return false;
68 /// process(keyword, value);
69 /// return true;
70 /// }
71 /// @endcode
72 /// @see UT_JSONParser, UT_JSONWriter, UT_JSONHandle, UT_JSONValueArray,
73 /// UT_JSONValueMap
74 
76 public:
77  /// Types held in the UT_JSONValue. The number type has been broken out
78  /// into an integer and a real.
79  enum Type {
80  JSON_NULL, // Null
81  JSON_BOOL, // Bool
82  JSON_INT, // Integer
83  JSON_REAL, // Real
84  JSON_STRING, // String value
85  JSON_KEY, // Key value
86  JSON_ARRAY, // An array of UT_JSON_VALUE
87  JSON_MAP, // A map of keyword, UT_JSONValue object
88  };
89 
90  UT_JSONValue();
91  explicit UT_JSONValue(bool value);
92  explicit UT_JSONValue(int64 value);
93  explicit UT_JSONValue(fpreal64 value);
94  UT_JSONValue(const char *string, int64 length=-1);
95  UT_JSONValue(const UT_StringHolder &s);
96  UT_JSONValue(const UT_JSONValue &v);
97  ~UT_JSONValue();
98 
100  {
101  copyFrom(v);
102  return *this;
103  }
104 
105  /// Read the next value from the parser and store it in this object
106  /// @param parser The parser
107  /// @param is If specified, data will be read from this stream.
108  /// Otherwise, the stream associated with the parser will be used.
109  bool parseValue(UT_JSONParser &parser,
110  UT_IStream *is = 0,
111  bool record_source_offsets = false);
112 
113  /// Loads an entire JSON file into this value.
114  bool loadFromFile(const char* file_name,
115  bool record_source_offsets = false);
116 
117  /// Saves an entire JSON value to the specified file.
118  bool saveToFile(const char* file_name,
119  bool binary = false,
120  UT_CompressionType compressionType =
122 
123  /// Save the object the output stream
124  bool save(UT_JSONWriter &os) const;
125 
126  /// Dump the value to stdout (same as save to cout)
127  void dump() const;
128 
129  /// Get the type of data stored in the object
130  Type getType() const { return myType; }
131 
132  /// Get the bool value. Interprets integer/float as bool
133  bool getB() const;
134  /// Get the integer value. Intereprets bool/real as integer
135  /// @note Real values are cast to integer.
136  int64 getI() const;
137  /// Get the real value. Interprets bool/int as reals.
138  fpreal64 getF() const;
139 
140  /// Get the string value (may return a NULL pointer)
141  const char *getS() const;
142  /// Return the string length (returns -1 if not a string)
143  int64 getSLength() const;
144  /// Return the string value.
145  const UT_StringHolder *getStringHolder() const;
146 
147  /// Get a key value
148  const char *getKey() const;
149  /// Get the length of the key
150  int64 getKeyLength() const;
151  /// Return a string holder for the key.
152  const UT_StringHolder *getKeyHolder() const;
153 
154  /// Get the array value (may return a NULL pointer)
155  UT_JSONValueArray *getArray() const;
156  /// Get the map value (may return a NULL pointer)
157  UT_JSONValueMap *getMap() const;
158 
159  /// Get the "uniform" type of an array. This will return:
160  /// - JSON_NULL: The array is heterogeneous (or not an array)
161  /// - JSON_BOOL: The array is only bool values
162  /// - JSON_INT: The array is all bool or int values
163  /// - JSON_REAL: The array is bool, int or real values
164  /// - JSON_STRING: The array is all strings
165  Type getUniformArrayType() const;
166 
167  /// Extract a bool (returns false if type is invalid)
168  SYS_FORCE_INLINE bool import(bool &result) const
169  {
170  switch (myType)
171  {
172  case JSON_BOOL:
173  result = myData.myBool;
174  return true;
175  case JSON_INT:
176  result = myData.myInt != 0;
177  return true;
178  case JSON_REAL:
179  result = myData.myReal != 0;
180  return true;
181  default:
182  break;
183  }
184  return false;
185  }
186  /// Extract an integer (returns false if type is invalid)
187  SYS_FORCE_INLINE bool import(int64 &result) const
188  {
189  switch (myType)
190  {
191  case JSON_BOOL:
192  result = myData.myBool ? 1 : 0;
193  return true;
194  case JSON_INT:
195  result = myData.myInt;
196  return true;
197  case JSON_REAL:
198  result = (int64)myData.myReal;
199  return true;
200  default:
201  break;
202  }
203  return false;
204  }
205  /// Extract an float (returns false if type is invalid)
206  SYS_FORCE_INLINE bool import(fpreal64 &result) const
207  {
208  switch (myType)
209  {
210  case JSON_BOOL:
211  result = myData.myBool ? 1. : 0.;
212  return true;
213  case JSON_INT:
214  result = myData.myInt;
215  return true;
216  case JSON_REAL:
217  result = myData.myReal;
218  return true;
219  default:
220  break;
221  }
222  return false;
223  }
224  /// Extract a string @b or key (returns false if type is invalid)
225  bool import(UT_WorkBuffer &result) const;
226  bool import(UT_StringHolder &result) const;
227  /// Extract a tuple of integers from an JSON_Array. If there aren't enough
228  /// elements in the array, this method fails
229  bool import(int64 *result, int size) const;
230  /// Extract a tuple of floats from an JSON_Array. If there aren't enough
231  /// elements in the array, this method fails
232  bool import(fpreal64 *result, int size) const;
233  /// Extract a vector of integers from a JSON_Array
234  bool import(UT_Array<int64> &array) const;
235  /// Extract a vector of reals from a JSON_Array
236  bool import(UT_Array<fpreal64> &array) const;
237  /// Extract a vector of strings from a JSON_Array
238  bool import(UT_StringArray &array) const;
239 
240  /// Returns whether the value can be interpreted as a number
241  bool isNumber() const
242  {
243  return myType == JSON_REAL || myType == JSON_INT ||
244  myType == JSON_BOOL;
245  }
246 
247  /// Set value to a null
248  void setNull() { clearValue(); }
249  /// Set value to an bool
250  void setBool(bool v);
251  /// Set value to an int
252  void setInt(int64 v);
253  /// Set value to an int
254  void setReal(fpreal64 v);
255  /// Set string. If the length is not specified, the length of the string
256  /// will be used.
257  void setString(const char *s, int64 length=-1)
258  { setStringType(s, length, JSON_STRING); }
259  void setString(const UT_StringHolder &s)
260  { setStringType(s, JSON_STRING); }
261  /// Set string. If the length is not specified, the length of the string
262  /// will be used.
263  void setKey(const char *s, int64 length=-1)
264  { setStringType(s, length, JSON_KEY); }
265  void setKey(const UT_StringHolder &s)
266  { setStringType(s, JSON_KEY); }
267  /// Set value to the array
268  void setArray(UT_JSONValueArray *array);
269  /// Set value to the map
270  void setMap(UT_JSONValueMap *map);
271 
272  /// Start building an array from scratch. @see appendArray
273  void startArray();
274  /// Add an element to an array (returns false if operation fails)
275  bool appendArray(const UT_JSONValue &v);
276 
277  /// Start building a map from scratch . @see appendMap
278  void startMap();
279  /// Add an element to a map (returns false if operation fails)
280  bool appendMap(const UT_StringHolder &key, const UT_JSONValue &v);
281 
282  /// Adds a new map child to this value. The current value must
283  /// be either an array or a map. If this value is an array,
284  /// the map_key parameter is ignored. This is due to overly
285  /// convoluted JSON syntax design.
286  UT_JSONValueMap* addMapChild(const UT_StringHolder &map_key);
287 
288  /// Adds a new array child to this value. The current value must
289  /// be either an array or a map. If this value is an array,
290  /// the map_key parameter is ignored. This is due to overly
291  /// convoluted JSON syntax design.
292  UT_JSONValueArray* addArrayChild(const UT_StringHolder &map_key);
293 
294  /// @{
295  /// Build a uniform array of values
296  bool setUniformArray(int nvalues, const int32 *data);
297  bool setUniformArray(int nvalues, const int64 *data);
298  bool setUniformArray(int nvalues, const fpreal16 *data);
299  bool setUniformArray(int nvalues, const fpreal32 *data);
300  bool setUniformArray(int nvalues, const fpreal64 *data);
301  bool setUniformArray(int nvalues, const UT_StringHolder *data);
302  /// @}
303 
304  /// Used internally by UT_JSONValueMap
305  int getMapIndex() const
306  { return myMapIndex; }
307  /// Used internally by UT_JSONValueMap
308  void setMapIndex(int i)
309  { myMapIndex = i; }
310 
311  /// Used by UT_JSONValue parsing from a stream
312  int getSourceLine() const
313  { return mySourceLine; }
314  int getSourceOffset() const
315  { return mySourceOffset; }
316  void setSourceOffset(int line, int offset)
317  { mySourceLine = line; mySourceOffset = offset; }
318 
319  /// @brief Traverse the children of the current value.
320  ///
321  /// This class will iterate over all items in this value, whether they
322  /// are in the form of an array or a map. For values with neither,
323  /// it will return the current value itself.
324  /// Note that the getKey() function is only available when this
325  /// value is a map.
326  ///
327  /// Example:
328  /// @code
329  /// UT_JSONValue::traverser it;
330  /// for (it = value.beginTraversal(); !it.atEnd(); ++it)
331  /// @endcode
333  {
334  public:
336  : myValue(NULL),
337  myIsValid(false)
338  {
339  myCurrArrayPos = myNumArrayEntries = 0;
340  }
342  {
343  *this = src;
344  }
346 
348  {
349  myValue = src.myValue;
350  myIsValid = src.myIsValid;
351  myCurrArrayPos = src.myCurrArrayPos;
352  myNumArrayEntries = src.myNumArrayEntries;
353  myValueType = src.myValueType;
354  myMapKeys = src.myMapKeys;
355  return *this;
356  }
357 
358  /// ++iterator
359  traverser &operator++() { advance(); return *this; }
360  /// No post increment as it is harmful.
361 
362  bool atEnd() const { return !myIsValid; }
363  void advance()
364  {
365  if(myValue && myIsValid)
366  {
367  if(myValueType == JSON_MAP)
368  {
369  myCurrArrayPos++;
370  if(myCurrArrayPos >= myMapKeys.entries())
371  myIsValid = false;
372  }
373  else if(myValueType == JSON_ARRAY)
374  {
375  myCurrArrayPos++;
376  if(myCurrArrayPos >= myNumArrayEntries)
377  myIsValid = false;
378  }
379  else
380  // Any non-array, non-map values only
381  // have one item.
382  myIsValid = false;
383 
384  }
385  }
386 
387  /// Returns the child value which corresponds to the current
388  /// traversal position.
390  {
391  if(myValue && myIsValid)
392  {
393  if(myValueType == JSON_MAP)
394  return myValue->getMap()->get(myMapKeys(myCurrArrayPos).buffer());
395  else if(myValueType == JSON_ARRAY)
396  return myValue->getArray()->get(myCurrArrayPos);
397  else
398  return NULL;
399  }
400  return NULL;
401  }
402 
403  /// Deprecated in favour of UT_StringHolder method
404  SYS_DEPRECATED(14.0) bool getKey(UT_String &key)
405  {
406  UT_StringHolder tmp;
407  if (!getKey(tmp))
408  return false;
409  key = tmp;
410  return true;
411  }
412  /// Deprecated in favour of UT_StringHolder method
413  SYS_DEPRECATED(14.0) bool getLowerCaseKey(UT_String &key)
414  {
415  UT_StringHolder tmp;
416  if (!getLowerCaseKey(tmp))
417  return false;
418  key = tmp;
419  return true;
420  }
421 
423  {
424  if(myValue && myIsValid)
425  {
426  if(myValueType == JSON_MAP)
427  {
428  key = myMapKeys(myCurrArrayPos);
429  return true;
430  }
431  else
432  {
433  key.clear();
434  }
435  }
436  else
437  {
438  key.clear();
439  }
440  return false;
441  }
442 
443  /// Get a lower case map key (for case insensitive maps)
445  {
446  if (getKey(key))
447  {
448  key = key.toLower();
449  return true;
450  }
451  return false;
452  }
453 
454  private:
455  traverser(UT_JSONValue *value_in)
456  : myValue(value_in),
457  myIsValid(false)
458  {
459  myCurrArrayPos = 0;
460  myNumArrayEntries = 0;
461  if (value_in)
462  {
463  // See whether this map is a map or an array:
464  myValueType = myValue->getType();
465 
466  // Check for an empty array or map.
467  myIsValid = true;
468  if(myValueType == JSON_MAP)
469  {
470  if(myValue->getMap()->entries() == 0)
471  myIsValid = false;
472  else
473  myValue->getMap()->getKeys(myMapKeys);
474  }
475  else if(myValueType == JSON_ARRAY)
476  {
477  if(myValue->getArray()->entries() == 0)
478  myIsValid = false;
479  else
480  myNumArrayEntries = myValue->getArray()->entries();
481  }
482  else
483  myIsValid = false;
484  }
485  }
486 
487  UT_JSONValue *myValue;
488  UT_JSONValue::Type myValueType;
489  UT_StringArray myMapKeys;
490  int64 myCurrArrayPos, myNumArrayEntries;
491  bool myIsValid;
492 
493  friend class UT_JSONValue;
494  };
495 
496  traverser beginTraversal() { return traverser(this); }
497 
498  /// Searches all children of this value recursively for another value
499  /// with a child that contains the given map key set to the given value.
501  const char *key_value);
503  const char *key_value);
504 
505  /// Removes NULL values from all arrays recursively.
506  /// Note that maps are currently unsupported, and null values will
507  /// not be removed from them.
509 
510 private:
511  void clearValue();
512  void copyFrom(const UT_JSONValue &s);
513  void setStringType(const char *s, int64 l, Type t);
514  void setStringType(const UT_StringHolder &s, Type t);
515  union {
516  bool myBool;
519  } myData;
520  union {
521  // NOTE: Keep the pointers and scalars separate. The string is stored
522  // as a pointer and a length so that null characters may be contained.
525  } myPointers;
526  UT_StringHolder myString;
527  int myMapIndex; // Location in a map
528  int mySourceLine; // Line in source stream
529  int mySourceOffset; // Offset in source line
530  Type myType;
531 };
532 
533 #endif
534 
UT_JSONValue * findValueRecursive(const UT_StringHolder &map_key, const char *key_value)
UT_JSONValueMap stores a map/dictionary of UT_JSONValue objects.
#define SYS_DEPRECATED(__V__)
bool isNumber() const
Returns whether the value can be interpreted as a number.
Definition: UT_JSONValue.h:241
const GLdouble * v
Definition: glcorearb.h:836
SYS_FORCE_INLINE void clear()
void setNull()
Set value to a null.
Definition: UT_JSONValue.h:248
void setKey(const UT_StringHolder &s)
Definition: UT_JSONValue.h:265
const GLuint GLenum const void * binary
Definition: glcorearb.h:1923
UT_JSONValueArray stores a list of UT_JSONValue objects.
int getSourceLine() const
Used by UT_JSONValue parsing from a stream.
Definition: UT_JSONValue.h:312
UT_JSONValueArray * myArray
Definition: UT_JSONValue.h:523
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:75
#define UT_API
Definition: UT_API.h:13
UT_JSONValueMap * getMap() const
Get the map value (may return a NULL pointer)
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:32
void removeNullValuesRecursive()
bool getLowerCaseKey(UT_StringHolder &key)
Get a lower case map key (for case insensitive maps)
Definition: UT_JSONValue.h:444
fpreal64 myReal
Definition: UT_JSONValue.h:518
GLuint buffer
Definition: glcorearb.h:659
png_uint_32 i
Definition: png.h:2877
GLsizeiptr size
Definition: glcorearb.h:663
bool atEnd() const
No post increment as it is harmful.
Definition: UT_JSONValue.h:362
UT_StringRef toLower() const
int getSourceOffset() const
Definition: UT_JSONValue.h:314
long long int64
Definition: SYS_Types.h:107
void setSourceOffset(int line, int offset)
Definition: UT_JSONValue.h:316
void setKey(const char *s, int64 length=-1)
Definition: UT_JSONValue.h:263
const traverser & operator=(const traverser &src)
Definition: UT_JSONValue.h:347
UT_JSONValueMap * myMap
Definition: UT_JSONValue.h:524
double fpreal64
Definition: SYS_Types.h:192
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
Traverse the children of the current value.
Definition: UT_JSONValue.h:332
GLintptr offset
Definition: glcorearb.h:664
traverser(const traverser &src)
Definition: UT_JSONValue.h:341
int getMapIndex() const
Used internally by UT_JSONValueMap.
Definition: UT_JSONValue.h:305
traverser beginTraversal()
Definition: UT_JSONValue.h:496
UT_JSONValue & operator=(const UT_JSONValue &v)
Definition: UT_JSONValue.h:99
GLboolean * data
Definition: glcorearb.h:130
int int32
Definition: SYS_Types.h:35
UT_JSONValue * findParentValueRecursive(const UT_StringHolder &map_key, const char *key_value)
traverser & operator++()
++iterator
Definition: UT_JSONValue.h:359
void setString(const UT_StringHolder &s)
Definition: UT_JSONValue.h:259
GLsizei const GLfloat * value
Definition: glcorearb.h:823
void setString(const char *s, int64 length=-1)
Definition: UT_JSONValue.h:257
UT_CompressionType
Type getType() const
Get the type of data stored in the object.
Definition: UT_JSONValue.h:130
bool getKey(UT_StringHolder &key)
Definition: UT_JSONValue.h:422
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:75
UT_JSONValue * getValue()
Definition: UT_JSONValue.h:389
const UT_JSONValue * get(int64 i) const
Access a const entry by index.
float fpreal32
Definition: SYS_Types.h:191
SYS_FORCE_INLINE const UT_JSONValue * get(int64 i) const
Access a const entry by index.
void setMapIndex(int i)
Used internally by UT_JSONValueMap.
Definition: UT_JSONValue.h:308
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:794
GLenum src
Definition: glcorearb.h:1792
UT_JSONValueArray * getArray() const
Get the array value (may return a NULL pointer)