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