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_SymbolTable.h"
16 #include "UT_VectorTypes.h"
17 #include "UT_StringArray.h"
18 #include "UT_StringHolder.h"
19 #include "UT_Compression.h"
20 #include <SYS/SYS_Compiler.h>
21 #include <SYS/SYS_Inline.h>
22 #include <SYS/SYS_Hash.h>
23 
24 class UT_JSONValue;
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 /// Ideally, this should be an inner class to UT_JSONValue, but it needs to be
34 /// forward declared
36 {
37  explicit UT_JSONFindResult(UT_JSONValue *v = nullptr, int64 idx=-1)
38  : myValue(v)
39  , myIndex(idx)
40  {
41  }
42 
43  SYS_SAFE_BOOL operator bool() const { return myValue != nullptr; }
44  const UT_JSONValue *operator->() const { return get(); }
45  UT_JSONValue *operator->() { return get(); }
46  const UT_JSONValue &operator*() const { return *get(); }
47  UT_JSONValueMap *getMap() const;
48  UT_JSONValueArray *getArray() const;
49 
50  UT_JSONValue *get() const { return myValue; }
51  int64 index() const { return myIndex; }
52 
55 };
56 
57 /// @brief Class to store JSON objects as C++ objects
58 ///
59 /// This class is able to represent a JSON object in its entirety. Arrays and
60 /// Maps store arrays and maps of JSON values.
61 ///
62 /// There are methods to load a JSONValue from a UT_JSONParser and to save to a
63 /// UT_JSONWriter object.
64 ///
65 /// To load an entire JSON file into memory, you can do something like
66 /// @code
67 /// UT_JSONIStream *is(utistream);
68 /// UT_JSONParser parser;
69 /// UT_JSONValue value;
70 /// if (!value.load(parser, *is))
71 /// reportFailure(parser.getErrors());
72 /// @endcode
73 ///
74 /// To save a value:
75 /// @code
76 /// UT_JSONWriterSubclass &os;
77 /// value.save(os);
78 /// @endcode
79 ///
80 /// Alternatively, it's possible to use the UT_JSONValue class from within
81 /// other UT_JSONHandle classes. For example, when loading key/value pairs for
82 /// an arbitrary map:
83 /// @code
84 /// bool
85 /// my_handle::jsonKey(UT_JSONParser &parser, const char *token, int64)
86 /// {
87 /// UT_String keyword;
88 /// UT_JSONValue value;
89 /// keyword.harden(token);
90 /// if (!value.load(parser))
91 /// return false;
92 /// process(keyword, value);
93 /// return true;
94 /// }
95 /// @endcode
96 /// @see UT_JSONParser, UT_JSONWriter, UT_JSONHandle, UT_JSONValueArray,
97 /// UT_JSONValueMap
98 
100 {
101 public:
102  /// Types held in the UT_JSONValue. The number type has been broken out
103  /// into an integer and a real.
104  enum Type {
105  JSON_NULL, // Null
106  JSON_BOOL, // Bool
107  JSON_INT, // Integer
108  JSON_REAL, // Real
109  JSON_STRING, // String value
110  JSON_KEY, // Key value
111  JSON_ARRAY, // An array of UT_JSON_VALUE
112  JSON_MAP, // A map of keyword, UT_JSONValue object
113  };
114 
115  UT_JSONValue();
116  explicit UT_JSONValue(Type type);
117  explicit UT_JSONValue(bool value);
118  explicit UT_JSONValue(int64 value);
119  explicit UT_JSONValue(fpreal64 value);
120  explicit UT_JSONValue(const char *string, int64 length=-1);
121  explicit UT_JSONValue(const UT_StringHolder &s);
122  UT_JSONValue(const UT_JSONValue &v);
123  ~UT_JSONValue();
124 
126  {
127  copyFrom(v);
128  return *this;
129  }
131  {
132  setString(s);
133  return *this;
134  }
136  {
137  setBool(v);
138  return *this;
139  }
141  {
142  setInt(v);
143  return *this;
144  }
146  {
147  setReal(v);
148  return *this;
149  }
150 
151  /// Normally JSON values store shared pointers to the array and map
152  /// objects. This method will make a deep copy of the JSON Value.
153  UT_JSONValue deepCopy() const;
154 
155  /// Read the next value from the parser and store it in this object
156  /// @param parser The parser
157  /// @param is If specified, data will be read from this stream.
158  /// @param record_source_offsets Track offsets in stream for later seeking
159  /// Otherwise, the stream associated with the parser will be used.
160  bool parseValue(UT_JSONParser &parser,
161  UT_IStream *is = 0,
162  bool record_source_offsets = false);
163 
164  bool parseValue(const UT_StringRef &json_source);
165  bool parseValue(std::istream& is);
166  bool parseValue(UT_IStream& stream);
167 
168  /// Loads an entire JSON file into this value.
169  bool loadFromFile(const char* file_name,
170  bool record_source_offsets = false);
171 
172  /// Saves an entire JSON value to the specified file.
173  bool saveToFile(const char* file_name,
174  bool binary = false,
175  UT_CompressionType compressionType =
177 
178  /// Save the object the output stream
179  bool save(UT_JSONWriter &os) const;
180 
181  /// Dump the value to stdout (same as save to cout)
182  void dump() const;
183  UT_StringHolder toString() const;
184 
185  /// Get the type of data stored in the object
186  SYS_NO_DISCARD_RESULT Type getType() const { return myType; }
187  SYS_NO_DISCARD_RESULT bool isMap() const { return myType == JSON_MAP; }
188  SYS_NO_DISCARD_RESULT bool isArray() const { return myType == JSON_ARRAY; }
189  SYS_NO_DISCARD_RESULT bool isNull() const { return myType == JSON_NULL; }
191  {
192  return !isMap() && !isArray();
193  }
194 
195  /// Get the bool value. Interprets integer/float as bool
196  SYS_NO_DISCARD_RESULT bool getB() const;
197  /// Get the integer value. Intereprets bool/real as integer
198  /// @note Real values are cast to integer.
199  SYS_NO_DISCARD_RESULT int64 getI() const;
200  /// Get the real value. Interprets bool/int as reals.
201  SYS_NO_DISCARD_RESULT fpreal64 getF() const;
202  /// Get the string value. If the value is not a string it returns the empty
203  /// string. Either check the type prior to calling this function or use
204  /// import<>() if you need to tell if there was an error.
206  {
207  const UT_StringHolder* v = getStringHolder();
208  if (v != nullptr)
209  return *v;
211  }
212 
213  /// Get the string value (may return a NULL pointer)
214  SYS_NO_DISCARD_RESULT const char *getS() const;
215  /// Return the string length (returns -1 if not a string)
216  SYS_NO_DISCARD_RESULT int64 getSLength() const;
217  /// Return the string value.
218  SYS_NO_DISCARD_RESULT const UT_StringHolder *getStringHolder() const;
219 
220  SYS_NO_DISCARD_RESULT int32 get(const UT_StringRef& key, int32 def_value) const;
221  SYS_NO_DISCARD_RESULT int64 get(const UT_StringRef& key, int64 def_value) const;
222  SYS_NO_DISCARD_RESULT UT_StringHolder get(const UT_StringRef& key, const UT_StringRef& def_value) const;
223  SYS_NO_DISCARD_RESULT UT_StringArray get(const UT_StringRef& key, const UT_StringArray& def_value) const;
224 
225  /// Get a key value
226  SYS_NO_DISCARD_RESULT const char *getKey() const;
227  /// Get the length of the key
228  SYS_NO_DISCARD_RESULT int64 getKeyLength() const;
229  /// Return a string holder for the key.
230  SYS_NO_DISCARD_RESULT const UT_StringHolder *getKeyHolder() const;
231 
232  /// Get the array value (may return a NULL pointer)
233  SYS_NO_DISCARD_RESULT UT_JSONValueArray *getArray() const;
234  /// Get the map value (may return a NULL pointer)
235  SYS_NO_DISCARD_RESULT UT_JSONValueMap *getMap() const;
236 
237  /// Get the "uniform" type of an array. This will return:
238  /// - JSON_NULL: The array is heterogeneous (or not an array)
239  /// - JSON_BOOL: The array is only bool values
240  /// - JSON_INT: The array is all bool or int values
241  /// - JSON_REAL: The array is bool, int or real values
242  /// - JSON_STRING: The array is all strings
243  SYS_NO_DISCARD_RESULT Type getUniformArrayType() const;
244 
245  /// Extract a bool (returns false if type is invalid)
246  SYS_FORCE_INLINE bool import(bool &result) const
247  {
248  switch (myType)
249  {
250  case JSON_BOOL:
251  result = myData.myBool;
252  return true;
253  case JSON_INT:
254  result = myData.myInt != 0;
255  return true;
256  case JSON_REAL:
257  result = myData.myReal != 0;
258  return true;
259  default:
260  break;
261  }
262  return false;
263  }
264  /// Extract an integer (returns false if type is invalid)
265  SYS_FORCE_INLINE bool import(int64 &result) const
266  {
267  switch (myType)
268  {
269  case JSON_BOOL:
270  result = myData.myBool ? 1 : 0;
271  return true;
272  case JSON_INT:
273  result = myData.myInt;
274  return true;
275  case JSON_REAL:
276  result = (int64)myData.myReal;
277  return true;
278  default:
279  break;
280  }
281  return false;
282  }
283  /// Extract an float (returns false if type is invalid)
284  SYS_FORCE_INLINE bool import(fpreal64 &result) const
285  {
286  switch (myType)
287  {
288  case JSON_BOOL:
289  result = myData.myBool ? 1. : 0.;
290  return true;
291  case JSON_INT:
292  result = myData.myInt;
293  return true;
294  case JSON_REAL:
295  result = myData.myReal;
296  return true;
297  default:
298  break;
299  }
300  return false;
301  }
302  /// Extract a string @b or key (returns false if type is invalid)
303  bool import(UT_WorkBuffer &result) const;
304  bool import(UT_StringHolder &result) const;
305  /// Extract a tuple of integers from an JSON_Array. If there aren't enough
306  /// elements in the array, this method fails
307  bool import(int64 *result, int size) const;
308  /// Extract a tuple of floats from an JSON_Array. If there aren't enough
309  /// elements in the array, this method fails
310  bool import(fpreal64 *result, int size) const;
311  /// Extract a vector of integers from a JSON_Array
312  bool import(UT_Array<int64> &array) const;
313  /// Extract a vector of reals from a JSON_Array
314  bool import(UT_Array<fpreal64> &array) const;
315  /// Extract a vector of strings from a JSON_Array
316  bool import(UT_StringArray &array) const;
317  /// Extract a value from the object. Only applies to json objects.
318  template <typename T>
319  bool import(const UT_StringRef &key, T &reuslt) const;
320 
321  /// Returns whether the value can be interpreted as a number
322  bool isNumber() const
323  {
324  return myType == JSON_REAL || myType == JSON_INT ||
325  myType == JSON_BOOL;
326  }
327 
328  /// Set value to a null
329  void setNull() { clearValue(); }
330  /// Set value to an bool
331  void setBool(bool v);
332  /// Set value to an int
333  void setInt(int64 v);
334  /// Set value to an int
335  void setReal(fpreal64 v);
336  /// Set string. If the length is not specified, the length of the string
337  /// will be used.
338  void setString(const char *s, int64 length=-1)
339  { setStringType(s, length, JSON_STRING); }
341  { setStringType(s, JSON_STRING); }
342  /// Set string. If the length is not specified, the length of the string
343  /// will be used.
344  void setKey(const char *s, int64 length=-1)
345  { setStringType(s, length, JSON_KEY); }
346  void setKey(const UT_StringHolder &s)
347  { setStringType(s, JSON_KEY); }
348  /// Set value to the array
349  void setArray(UT_JSONValueArray *array);
350  /// Set value to the map
351  void setMap(UT_JSONValueMap *map);
352 
353  /// Start building an array from scratch. @see appendArray
354  UT_JSONValueArray *startArray();
355  /// Add an element to an array (returns false if operation fails)
356  /// The current value must be an array object
357  bool appendArray(const UT_JSONValue &v);
358 
359  /// Start building a map from scratch. @see appendMap
360  UT_JSONValueMap *startMap();
361  /// Add an element to a map (returns false if operation fails)
362  /// The current value must be a map object
363  bool appendMap(const UT_StringHolder &key, const UT_JSONValue &v);
364 
365  /// Adds a new map child to this value. The current value must
366  /// be either an array or a map. If this value is an array,
367  /// the map_key parameter is ignored. This is due to overly
368  /// convoluted JSON syntax design.
369  UT_JSONValueMap* addMapChild(const UT_StringHolder &map_key);
370 
371  /// Adds a new array child to this value. The current value must
372  /// be either an array or a map. If this value is an array,
373  /// the map_key parameter is ignored. This is due to overly
374  /// convoluted JSON syntax design.
375  UT_JSONValueArray* addArrayChild(const UT_StringHolder &map_key);
376 
377  /// Set json value as a json map.
378  bool setAsMap();
379  /// Set json value as a json array.
380  bool setAsArray();
381 
382  /// @{
383  /// Build a uniform array of values
384  bool setUniformArray(int nvalues, const int32 *data);
385  bool setUniformArray(int nvalues, const int64 *data);
386  bool setUniformArray(int nvalues, const fpreal16 *data);
387  bool setUniformArray(int nvalues, const fpreal32 *data);
388  bool setUniformArray(int nvalues, const fpreal64 *data);
389  bool setUniformArray(int nvalues, const UT_StringHolder *data);
390  /// @}
391 
392  /// Used internally by UT_JSONValueMap
394  { return myMapIndex; }
395  /// Used internally by UT_JSONValueMap
396  void setMapIndex(int i)
397  { myMapIndex = i; }
398 
399  /// Used by UT_JSONValue parsing from a stream
401  { return mySourceLine; }
403  { return mySourceOffset; }
404  void setSourceOffset(int line, int offset)
405  { mySourceLine = line; mySourceOffset = offset; }
406 
407  /// {@
408  /// Helper access operators.
409  /// - operator() allow for the value to not exist.
410  /// - operator[] does not allow for the value to not exist.
412  {
413  return get(i);
414  }
416  {
417  return get(i);
418  }
420  {
421  return get(k);
422  }
424  {
425  return get(k);
426  }
428  {
429  // Matching std::vector where accessing out of bounds is undefined
430  // behaviour. If bounds checking is necessary use operator().
431  const UT_JSONValue* v = get(i);
432  UT_ASSERT_P(v != nullptr);
433  return *v;
434  }
436  {
437  // Matching std::vector where accessing out of bounds is undefined
438  // behaviour. If bounds checking is necessary use operator().
439  UT_JSONValue* v = get(i);
440  UT_ASSERT_P(v != nullptr);
441  return *v;
442  }
444  {
445  if (UT_JSONValue* v = get(k); v != nullptr)
446  return *v;
447  auto it = emplace(k, UT_JSONValue::JSON_NULL);
448  return *it.first;
449  }
450  /// @}
451 
452  /// @brief Traverse the children of the current value.
453  ///
454  /// This class will iterate over all items in this value, whether they
455  /// are in the form of an array or a map. For values with neither,
456  /// it will return the current value itself.
457  /// Note that the getKey() function is only available when this
458  /// value is a map.
459  ///
460  /// Example:
461  /// @code
462  /// UT_JSONValue::traverser it;
463  /// for (it = value.beginTraversal(); !it.atEnd(); ++it)
464  /// @endcode
466  {
467  public:
470  using pointer = value_type*;
472  using iterator_category = std::forward_iterator_tag;
473 
475  : myValue(NULL),
476  myIsValid(false)
477  {
478  myCurrArrayPos = myNumArrayEntries = 0;
479  }
481  {
482  *this = src;
483  }
485 
487  {
488  myValue = src.myValue;
489  myIsValid = src.myIsValid;
490  myCurrArrayPos = src.myCurrArrayPos;
491  myNumArrayEntries = src.myNumArrayEntries;
492  myValueType = src.myValueType;
493  myMapKeys = src.myMapKeys;
494  return *this;
495  }
496 
497  /// ++iterator
498  traverser &operator++() { advance(); return *this; }
499  /// No post increment as it is harmful.
500 
501  bool operator==(const traverser &rhs) const
502  {
503  return myCurrArrayPos == rhs.myCurrArrayPos
504  && myIsValid == rhs.myIsValid;
505  }
506  bool operator!=(const traverser& rhs) const
507  {
508  return !(*this == rhs);
509  }
510  const UT_JSONValue& operator*() const
511  {
512  return *this->getValue();
513  }
515  {
516  return *this->getValue();
517  }
518  const UT_JSONValue* operator->() const
519  {
520  return getValue();
521  }
523  {
524  return getValue();
525  }
526  bool atEnd() const { return !myIsValid; }
527  void advance()
528  {
529  if(myValue && myIsValid)
530  {
531  if(myValueType == JSON_MAP)
532  {
533  myCurrArrayPos++;
534  if(myCurrArrayPos >= myMapKeys.entries())
535  myIsValid = false;
536  }
537  else if(myValueType == JSON_ARRAY)
538  {
539  myCurrArrayPos++;
540  if(myCurrArrayPos >= myNumArrayEntries)
541  myIsValid = false;
542  }
543  else
544  // Any non-array, non-map values only
545  // have one item.
546  myIsValid = false;
547 
548  }
549  }
550 
551  /// Returns the child value which corresponds to the current
552  /// traversal position.
554  {
555  if (myValue && myIsValid)
556  return iteratorValue();
557  return nullptr;
558  }
559  const UT_JSONValue* getValue() const
560  {
561  if (myValue && myIsValid)
562  return SYSconst_cast(this)->iteratorValue();
563  return nullptr;
564  }
566  {
567  if (myValue && myIsValid
568  && (myValueType == JSON_ARRAY || myValueType == JSON_MAP))
569  {
570  return myCurrArrayPos;
571  }
572  return -1;
573  }
574 
575  /// Deprecated in favour of UT_StringHolder method
576  SYS_DEPRECATED(14.0) bool getKey(UT_String &key)
577  {
578  UT_StringHolder tmp;
579  if (!getKey(tmp))
580  return false;
581  key = tmp;
582  return true;
583  }
584  /// Deprecated in favour of UT_StringHolder method
585  SYS_DEPRECATED(14.0) bool getLowerCaseKey(UT_String &key)
586  {
587  UT_StringHolder tmp;
588  if (!getLowerCaseKey(tmp))
589  return false;
590  key = tmp;
591  return true;
592  }
593 
594  bool getKey(UT_StringHolder &key) const
595  {
596  if(myValue && myIsValid)
597  {
598  if(myValueType == JSON_MAP)
599  {
600  key = myMapKeys(myCurrArrayPos);
601  return true;
602  }
603  else
604  {
605  key.clear();
606  }
607  }
608  else
609  {
610  key.clear();
611  }
612  return false;
613  }
614 
615  /// Get a lower case map key (for case insensitive maps)
617  {
618  if (getKey(key))
619  {
620  key = key.toLower();
621  return true;
622  }
623  return false;
624  }
625  private:
626  traverser(UT_JSONValue *value_in)
627  : myValue(value_in),
628  myIsValid(false)
629  {
630  myCurrArrayPos = 0;
631  myNumArrayEntries = 0;
632  initData(value_in);
633  }
634  traverser(UT_JSONValue *value_in, exint start_idx)
635  : myValue(value_in), myIsValid(false), myCurrArrayPos(start_idx)
636  {
637  myNumArrayEntries = 0;
638  initData(value_in);
639  }
640  // Outline these to fix dependencies on UT_JSONValueArray/Map
641  void initData(const UT_JSONValue *value_in);
642  UT_JSONValue *iteratorValue();
643 
644  UT_JSONValue *myValue;
645  UT_JSONValue::Type myValueType;
646  UT_StringArray myMapKeys;
647  int64 myCurrArrayPos;
648  int64 myNumArrayEntries;
649  bool myIsValid;
650 
651  friend class UT_JSONValue;
652  };
653 
655  {
656  public:
658  using iterator_category = std::forward_iterator_tag;
659  using reference = std::pair<exint, UT_JSONValue&>;
660  using pointer = std::pair<exint, UT_JSONValue*>;
661 
662  explicit indexed_traverser(UT_JSONValue *v, exint end_len)
663  : traverser(v, end_len)
664  {
665  }
667 
668  using traverser::operator++;
669  using traverser::operator==;
670  using traverser::operator!=;
671 
673  {
674  return std::make_pair(
675  this->getArrayIndex(), std::ref(*this->getValue()));
676  }
678  {
679  return std::make_pair(this->getArrayIndex(), this->getValue());
680  }
681 
682  const UT_JSONValue& value() const
683  {
684  return *getValue();
685  }
686  };
687 
689  {
690  public:
692  using iterator_category = std::forward_iterator_tag;
693  using reference = std::tuple<exint, UT_StringHolder, UT_JSONValue&>;
694  using pointer = std::tuple<exint, UT_StringHolder, UT_JSONValue*>;
695 
697  : traverser(v, end_len)
698  {
699  }
701 
702  using traverser::operator++;
703  using traverser::operator==;
704  using traverser::operator!=;
705 
707  {
708  UT_StringHolder key;
709  getKey(key);
710  return std::make_tuple(
711  this->getArrayIndex(), key, std::ref(*this->getValue()));
712  }
714  {
715  UT_StringHolder key;
716  getKey(key);
717  return std::make_tuple(
718  this->getArrayIndex(), key, this->getValue());
719  }
720 
721  const UT_StringHolder &key() const
722  {
723  if (myValue && myIsValid)
724  {
725  if (myValueType == JSON_MAP)
726  {
727  return myMapKeys(myCurrArrayPos);
728  }
729  }
731  }
732 
733  const UT_JSONValue& value() const
734  {
735  return *getValue();
736  }
737  };
738 
739  /// Helper traverser to retrieve the key/value on the contained map.
740  /// Structured bindings are also offered with this type.
742  {
743  public:
746  using pointer = value_type *;
748  using iterator_category = std::forward_iterator_tag;
749 
750  explicit map_traverser(UT_JSONValue* v, exint end_len) :
751  traverser(v, end_len)
752  {}
754  traverser(v)
755  {
756  }
757 
758  using traverser::operator++;
759  using traverser::operator==;
760  using traverser::operator!=;
761 
762  reference operator*() { return *this; }
763  pointer operator->() { return this; }
764 
765  const UT_StringHolder &key() const
766  {
767  if (myValue && myIsValid)
768  {
769  if (myValueType == JSON_MAP)
770  {
771  return myMapKeys(myCurrArrayPos);
772  }
773  }
775  }
776 
777  const UT_JSONValue& value() const { return *getValue(); }
778  };
779 
780  /// Used to iterate over a map from a json value.
781  template <typename IteratorT>
783  {
784  public:
785  IteratorT begin()
786  {
787  return IteratorT(myValue);
788  }
789  IteratorT end()
790  {
791  return IteratorT(myValue, myValue->count());
792  }
793  const IteratorT begin() const
794  {
796  return IteratorT(me->myValue);
797  }
798  const IteratorT end() const
799  {
801  return IteratorT(me->myValue, me->myValue->count());
802  }
803  private:
804  explicit json_proxy(UT_JSONValue* v) :
805  myValue(v)
806  {}
807 
808  friend class UT_JSONValue;
809  UT_JSONValue* myValue;
810  };
811 
815 
816  using const_iterator = const traverser;
817  /// {@
818  /// Iterate over contained values.
819  /// Map: iterate over the json values of the map (excludes keys).
820  /// Array: iterate over the json values in the array.
821  /// Value: iterate over the single element contained in the json value.
825  {
826  return traverser(SYSconst_cast(this));
827  }
829  {
830  return traverser(SYSconst_cast(this), count());
831  }
833  {
834  return traverser(SYSconst_cast(this));
835  }
837  {
838  return traverser(SYSconst_cast(this), count());
839  }
840  /// @}
841  /// {@
842  /// Return a proxy map object to iterate over [key,value] on the contained
843  /// map.
845  {
846  UT_ASSERT(isMap());
847  return map_proxy(this);
848  }
850  {
851  UT_ASSERT(isMap());
852  return map_proxy(SYSconst_cast(this));
853  }
854  /// @}
855  /// {@
856  /// Return a proxy indexed object to iterate over [index, value] on the
857  /// contained object.
859  {
860  UT_ASSERT(isMap() || isArray());
861  return indexed_proxy(this);
862  }
864  {
865  UT_ASSERT(isMap() || isArray());
866  return indexed_proxy(SYSconst_cast(this));
867  }
869  {
870  UT_ASSERT(isMap());
871  return indexed_map_proxy(this);
872  }
874  {
875  UT_ASSERT(isMap());
876  return indexed_map_proxy(SYSconst_cast(this));
877  }
878  /// @}
880 
881  /// Number of elements contained inside the json value.
883 
884  /// Add a key/value pair to the contained map.
885  std::pair<traverser, bool> insert(
886  const UT_StringHolder &key,
887  const UT_JSONValue &value);
888 
889  /// Add an entry to the contained map
890  template <typename... ARGS>
891  std::pair<traverser, bool> emplace(
892  const UT_StringHolder &key,
893  ARGS &&... args)
894  {
895  return insert(key, UT_JSONValue(std::forward<ARGS>(args)...));
896  }
897 
898  /// Insert a json value to the back of the contained array.
899  traverser append(const UT_JSONValue& v);
900  /// Insert a json value to the back of the contained array.
901  template <typename... ARGS>
903  {
904  return append(UT_JSONValue(std::forward<ARGS>(args)...));
905  }
906 
907  /// {@
908  /// Find the value contained in the json object by key. The json value must
909  /// be a map object.
910  traverser find(const UT_StringRef& key);
911  const_iterator find(const UT_StringRef& key) const;
912  /// @}
913 
914  /// {@
915  /// Access a value by index. nullptr is returned if the element does not
916  /// exist.
917  UT_JSONValue* get(int64 idx);
918  const UT_JSONValue* get(int64 idx) const;
919  /// @}
920 
921  /// {@
922  /// Lookup a value by key. The key is allowed to not exist.
923  UT_JSONValue* get(const UT_StringRef& k);
924  const UT_JSONValue* get(const UT_StringRef& k) const;
925  /// @}
926 
927  /// {@
928  /// Check if a key exists on the map.
929  bool contains(const UT_StringRef& key) const;
930  /// @}
931 
932  /// {@
933  /// Remove a value by index.
934  void remove(int64 index);
935  /// @}
936 
937  /// {@
938  /// Erase an element by map key.
939  void erase(const UT_StringRef& k);
940  /// @}
941 
942  /// Searches all children of this value recursively for another value
943  /// with a child that contains the given map key set to the given value.
945  const UT_StringHolder &map_key,
946  const char *key_value);
948  const UT_StringHolder &map_key,
949  const char *key_value);
950 
951  /// Removes NULL values from all arrays recursively.
952  /// Note that maps are currently unsupported, and null values will
953  /// not be removed from them.
955 
956  /// Compute a hash
958  /// @{
959  /// Test equality
962  { return !(*this == src); }
963  /// @}
964 
965 private:
966  void clearValue();
967  void copyFrom(const UT_JSONValue &s);
968  void setStringType(const char *s, int64 l, Type t);
969  void setStringType(const UT_StringHolder &s, Type t);
970  union {
971  bool myBool;
974  } myData;
975  union {
976  // NOTE: Keep the pointers and scalars separate. The string is stored
977  // as a pointer and a length so that null characters may be contained.
980  } myPointers;
981  UT_StringHolder myString;
982  int myMapIndex; // Location in a map
983  int mySourceLine; // Line in source stream
984  int mySourceOffset; // Offset in source line
985  Type myType;
986 };
987 
988 UT_API size_t format(char *buffer, size_t buffer_size, const UT_JSONValue &v);
989 
990 // Structured Bindings Support
991 template <std::size_t N, std::enable_if_t<N == 0, int> = 0>
992 auto
994  -> decltype(m.key())
995 {
996  return m.key();
997 }
998 // Structured Bindings Support
999 template <std::size_t N, std::enable_if_t<N == 1, int> = 0>
1000 auto
1001 get(const UT_JSONValue::map_traverser &m) -> decltype(m.value())
1002 {
1003  return m.value();
1004 }
1005 
1006 template <std::size_t N, std::enable_if_t<N==0, int> = 0>
1007 auto
1008 get(const UT_JSONValue::indexed_traverser& it) -> decltype(it.getArrayIndex())
1009 {
1010  return it.getArrayIndex();
1011 }
1012 
1013 template <std::size_t N, std::enable_if_t<N == 1, int> = 0>
1014 auto
1015 get(const UT_JSONValue::indexed_traverser& it) -> decltype(it.value())
1016 {
1017  return it.value();
1018 }
1019 
1020 template <std::size_t N, std::enable_if_t<N==0, int> = 0>
1021 auto
1022 get(const UT_JSONValue::indexed_map_traverser& it) -> decltype(it.getArrayIndex())
1023 {
1024  return it.getArrayIndex();
1025 }
1026 
1027 template <std::size_t N, std::enable_if_t<N == 1, int> = 0>
1028 auto
1029 get(const UT_JSONValue::indexed_map_traverser& it) -> decltype(it.key())
1030 {
1031  return it.key();
1032 }
1033 
1034 template <std::size_t N, std::enable_if_t<N == 2, int> = 0>
1035 auto
1036 get(const UT_JSONValue::indexed_map_traverser& it) -> decltype(it.value())
1037 {
1038  return it.value();
1039 }
1040 
1041 namespace std
1042 {
1043 template <>
1044 struct tuple_size<UT_JSONValue::map_traverser>
1045  : public std::integral_constant<std::size_t, 2>
1046 {
1047 };
1048 template <std::size_t N>
1049 struct tuple_element<N, UT_JSONValue::map_traverser>
1050 {
1051  using type = decltype(get<N>(std::declval<UT_JSONValue::map_traverser>()));
1052 };
1053 
1054 template <>
1055 struct tuple_size<UT_JSONValue::indexed_traverser>
1056  : public std::integral_constant<std::size_t, 2>
1057 {
1058 };
1059 template <std::size_t N>
1060 struct tuple_element<N, UT_JSONValue::indexed_traverser>
1061 {
1062  using type = decltype(get<N>(std::declval<UT_JSONValue::indexed_traverser>()));
1063 };
1064 
1065 template <>
1066 struct tuple_size<UT_JSONValue::indexed_map_traverser>
1067  : public std::integral_constant<std::size_t, 3>
1068 {
1069 };
1070 template <std::size_t N>
1071 struct tuple_element<N, UT_JSONValue::indexed_map_traverser>
1072 {
1073  using type = decltype(get<N>(
1074  std::declval<UT_JSONValue::indexed_map_traverser>()));
1075 };
1076 } // namespace std
1077 
1078 #endif
GLuint GLuint stream
Definition: glcorearb.h:1832
Used to iterate over a map from a json value.
Definition: UT_JSONValue.h:782
const traverser const_iterator
Definition: UT_JSONValue.h:816
traverser find(const UT_StringRef &key)
UT_JSONValueMap stores a map/dictionary of UT_JSONValue objects.
int int32
Definition: SYS_Types.h:39
SYS_NO_DISCARD_RESULT const_iterator begin() const
Definition: UT_JSONValue.h:824
#define SYS_DEPRECATED(__V__)
const UT_JSONValue & value() const
Definition: UT_JSONValue.h:733
SYS_NO_DISCARD_RESULT UT_JSONValue * operator()(const UT_StringRef &k)
Definition: UT_JSONValue.h:423
SYS_NO_DISCARD_RESULT traverser begin()
Definition: UT_JSONValue.h:822
bool isNumber() const
Returns whether the value can be interpreted as a number.
Definition: UT_JSONValue.h:322
const GLdouble * v
Definition: glcorearb.h:837
SYS_FORCE_INLINE void clear()
void setNull()
Set value to a null.
Definition: UT_JSONValue.h:329
void setKey(const UT_StringHolder &s)
Definition: UT_JSONValue.h:346
const GLuint GLenum const void * binary
Definition: glcorearb.h:1924
UT_JSONValueArray stores a list of UT_JSONValue objects.
SYS_NO_DISCARD_RESULT const UT_JSONValue * operator()(const UT_StringRef &k) const
Definition: UT_JSONValue.h:419
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
Definition: SYS_Types.h:136
int64 exint
Definition: SYS_Types.h:125
SYS_NO_DISCARD_RESULT UT_JSONValue & operator[](const UT_StringRef &k)
Definition: UT_JSONValue.h:443
GLdouble s
Definition: glad.h:3009
std::size_t SYS_HashType
Define the type for hash values.
Definition: SYS_Hash.h:19
UT_JSONValueArray * myArray
Definition: UT_JSONValue.h:978
void erase(const UT_StringRef &k)
SYS_NO_DISCARD_RESULT int getSourceOffset() const
Definition: UT_JSONValue.h:402
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
map_traverser(UT_JSONValue *v)
Definition: UT_JSONValue.h:753
const UT_StringHolder & key() const
Definition: UT_JSONValue.h:721
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:87
#define UT_API
Definition: UT_API.h:14
SYS_NO_DISCARD_RESULT bool isMap() const
Definition: UT_JSONValue.h:187
UT_JSONValue & operator=(const UT_StringHolder &s)
Definition: UT_JSONValue.h:130
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:37
void removeNullValuesRecursive()
**But if you need a result
Definition: thread.h:613
bool getLowerCaseKey(UT_StringHolder &key)
Get a lower case map key (for case insensitive maps)
Definition: UT_JSONValue.h:616
UT_JSONValue * myValue
Definition: UT_JSONValue.h:53
const UT_JSONValue * operator->() const
Definition: UT_JSONValue.h:518
float fpreal32
Definition: SYS_Types.h:200
fpreal64 myReal
Definition: UT_JSONValue.h:973
decltype(get< N >(std::declval< UT_JSONValue::map_traverser >())) type
SYS_NO_DISCARD_RESULT traverser beginTraversal()
Definition: UT_JSONValue.h:879
const UT_JSONValue * getValue() const
Definition: UT_JSONValue.h:559
const UT_JSONValue * operator->() const
Definition: UT_JSONValue.h:44
indexed_traverser(UT_JSONValue *v, exint end_len)
Definition: UT_JSONValue.h:662
__hostdev__ float getValue(uint32_t i) const
Definition: NanoVDB.h:5578
SYS_NO_DISCARD_RESULT UT_JSONValue * operator()(int64 i)
Definition: UT_JSONValue.h:415
bool contains(const UT_StringRef &key) const
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:400
SYS_NO_DISCARD_RESULT bool isValueType() const
Definition: UT_JSONValue.h:190
void setSourceOffset(int line, int offset)
Definition: UT_JSONValue.h:404
SYS_NO_DISCARD_RESULT const_iterator end() const
Definition: UT_JSONValue.h:828
decltype(get< N >(std::declval< UT_JSONValue::indexed_traverser >())) type
void setKey(const char *s, int64 length=-1)
Definition: UT_JSONValue.h:344
GLintptr offset
Definition: glcorearb.h:665
Definition: core.h:760
json_proxy< indexed_traverser > indexed_proxy
Definition: UT_JSONValue.h:813
traverser emplace_back(ARGS &&...args)
Insert a json value to the back of the contained array.
Definition: UT_JSONValue.h:902
const UT_JSONValue & value() const
Definition: UT_JSONValue.h:777
const traverser & operator=(const traverser &src)
Definition: UT_JSONValue.h:486
decltype(get< N >(std::declval< UT_JSONValue::indexed_map_traverser >())) type
std::pair< traverser, bool > insert(const UT_StringHolder &key, const UT_JSONValue &value)
Add a key/value pair to the contained map.
GLint ref
Definition: glcorearb.h:124
SYS_NO_DISCARD_RESULT indexed_map_proxy enumerateMap()
Definition: UT_JSONValue.h:868
#define SYS_SAFE_BOOL
Definition: SYS_Compiler.h:55
SYS_NO_DISCARD_RESULT UT_JSONFindResult findParentValueRecursive(const UT_StringHolder &map_key, const char *key_value)
UT_JSONValueMap * myMap
Definition: UT_JSONValue.h:979
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
static const UT_StringHolder theEmptyString
json_proxy< indexed_map_traverser > indexed_map_proxy
Definition: UT_JSONValue.h:814
UT_JSONValue & operator=(fpreal64 v)
Definition: UT_JSONValue.h:145
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
Traverse the children of the current value.
Definition: UT_JSONValue.h:465
SYS_NO_DISCARD_RESULT const indexed_proxy enumerate() const
Definition: UT_JSONValue.h:863
const UT_JSONValue & operator*() const
Definition: UT_JSONValue.h:46
int64 getArrayIndex() const
Definition: UT_JSONValue.h:565
indexed_map_traverser(UT_JSONValue *v, exint end_len)
Definition: UT_JSONValue.h:696
traverser(const traverser &src)
Definition: UT_JSONValue.h:480
SYS_NO_DISCARD_RESULT indexed_proxy enumerate()
Definition: UT_JSONValue.h:858
friend class UT_JSONValue
Definition: UT_JSONValue.h:651
long long int64
Definition: SYS_Types.h:116
#define SYS_NO_DISCARD_RESULT
Definition: SYS_Compiler.h:93
SYS_NO_DISCARD_RESULT bool isArray() const
Definition: UT_JSONValue.h:188
UT_JSONValue & operator=(const UT_JSONValue &v)
Definition: UT_JSONValue.h:125
std::forward_iterator_tag iterator_category
Definition: UT_JSONValue.h:472
SYS_NO_DISCARD_RESULT SYS_HashType hash() const
Compute a hash.
UT_JSONValue * operator->()
Definition: UT_JSONValue.h:45
indexed_traverser(UT_JSONValue *v)
Definition: UT_JSONValue.h:666
UT_JSONValue & operator=(int64 v)
Definition: UT_JSONValue.h:140
SYS_NO_DISCARD_RESULT const UT_JSONValue & operator[](int64 i) const
Definition: UT_JSONValue.h:427
SYS_NO_DISCARD_RESULT const UT_JSONValue * operator()(int64 i) const
Definition: UT_JSONValue.h:411
GLdouble t
Definition: glad.h:2397
bool getKey(UT_StringHolder &key) const
Definition: UT_JSONValue.h:594
traverser & operator++()
++iterator
Definition: UT_JSONValue.h:498
GLsizeiptr size
Definition: glcorearb.h:664
void setString(const UT_StringHolder &s)
Definition: UT_JSONValue.h:340
SYS_NO_DISCARD_RESULT UT_JSONValue & operator[](int64 i)
Definition: UT_JSONValue.h:435
const UT_JSONValue & value() const
Definition: UT_JSONValue.h:682
const UT_StringHolder & key() const
Definition: UT_JSONValue.h:765
SYS_NO_DISCARD_RESULT const map_proxy items() const
Definition: UT_JSONValue.h:849
const UT_JSONValue & operator*() const
Definition: UT_JSONValue.h:510
bool operator==(const traverser &rhs) const
No post increment as it is harmful.
Definition: UT_JSONValue.h:501
void setString(const char *s, int64 length=-1)
Definition: UT_JSONValue.h:338
UT_CompressionType
UT_JSONFindResult(UT_JSONValue *v=nullptr, int64 idx=-1)
Definition: UT_JSONValue.h:37
SYS_NO_DISCARD_RESULT int getMapIndex() const
Used internally by UT_JSONValueMap.
Definition: UT_JSONValue.h:393
SYS_NO_DISCARD_RESULT exint count() const
Number of elements contained inside the json value.
SYS_NO_DISCARD_RESULT UT_StringRef toLower() const
SYS_NO_DISCARD_RESULT map_proxy items()
Definition: UT_JSONValue.h:844
GA_API const UT_StringHolder N
SYS_NO_DISCARD_RESULT const_iterator cend() const
Definition: UT_JSONValue.h:836
SYS_NO_DISCARD_RESULT Type getType() const
Get the type of data stored in the object.
Definition: UT_JSONValue.h:186
json_proxy< map_traverser > map_proxy
Definition: UT_JSONValue.h:812
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:99
**If you just want to fire and args
Definition: thread.h:609
int64 index() const
Definition: UT_JSONValue.h:51
UT_JSONValue * getValue()
Definition: UT_JSONValue.h:553
SYS_NO_DISCARD_RESULT bool isNull() const
Definition: UT_JSONValue.h:189
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
Definition: core.h:1131
SYS_NO_DISCARD_RESULT bool operator!=(const UT_JSONValue &src) const
Definition: UT_JSONValue.h:961
const IteratorT end() const
Definition: UT_JSONValue.h:798
UT_JSONValue * operator->()
Definition: UT_JSONValue.h:522
bool getKey(UT_String &key)
Deprecated in favour of UT_StringHolder method.
Definition: UT_JSONValue.h:576
map_traverser(UT_JSONValue *v, exint end_len)
Definition: UT_JSONValue.h:750
UT_JSONValue & operator=(bool v)
Definition: UT_JSONValue.h:135
UT_API size_t format(char *buffer, size_t buffer_size, const UT_JSONValue &v)
SYS_NO_DISCARD_RESULT UT_JSONFindResult findValueRecursive(const UT_StringHolder &map_key, const char *key_value)
UT_JSONValue & operator*()
Definition: UT_JSONValue.h:514
traverser append(const UT_JSONValue &v)
Insert a json value to the back of the contained array.
type
Definition: core.h:1059
SYS_NO_DISCARD_RESULT const UT_StringHolder & getString() const
Definition: UT_JSONValue.h:205
const IteratorT begin() const
Definition: UT_JSONValue.h:793
SYS_NO_DISCARD_RESULT const indexed_map_proxy enumerateMap() const
Definition: UT_JSONValue.h:873
std::pair< traverser, bool > emplace(const UT_StringHolder &key, ARGS &&...args)
Add an entry to the contained map.
Definition: UT_JSONValue.h:891
Definition: format.h:895
void setMapIndex(int i)
Used internally by UT_JSONValueMap.
Definition: UT_JSONValue.h:396
bool operator!=(const traverser &rhs) const
Definition: UT_JSONValue.h:506
SYS_NO_DISCARD_RESULT traverser end()
Definition: UT_JSONValue.h:823
GLenum src
Definition: glcorearb.h:1793
SYS_NO_DISCARD_RESULT const_iterator cbegin() const
Definition: UT_JSONValue.h:832