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