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