HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_JSONParser.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_JSONParser.h ( UT Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __UT_JSONParser__
12 #define __UT_JSONParser__
13 
14 #include "UT_API.h"
15 #include "UT_IntArray.h"
16 #include "UT_JSONDefines.h"
17 #include "UT_Map.h"
18 #include "UT_StackBuffer.h"
19 #include "UT_StringHolder.h"
20 #include "UT_StringArray.h"
21 #include "UT_ValArray.h"
22 #include "UT_WorkBuffer.h"
23 
24 #include <SYS/fpreal16Limits.h>
25 #include <SYS/SYS_Math.h>
26 #include <SYS/SYS_Types.h>
27 
28 #include <istream>
29 #include <limits>
30 #include <streambuf>
31 
32 
33 class UT_BitArray;
34 class UT_IStream;
35 class UT_JSONHandle;
36 class UT_JSONValue;
37 
38 class ut_JValue;
39 class ut_SimpleJSONObjectHandle;
40 
41 
42 /// @brief JSON reader class which handles parsing of JSON or bJSON files
43 ///
44 /// The JSON format (http://www.json.org) is a generic way to store data.
45 /// Houdini extends JSON to a byte-stream binary encoding. This class is used
46 /// to parse JSON (binary or ASCII) and provides callbacks to handle the data.
47 ///
48 /// For binary JSON files, Houdini has extended JSON slightly to support
49 /// compact versions for specific data representations. The @c ua methods
50 /// callback methods on the JSONHandle are used to process a uniform array of
51 /// simple types. Data for the uniform array can be read directly from the
52 /// stream. Care must be taken for uaBool() and uaString() which encode the
53 /// array data. uaReadString() can be used to read a string from the data
54 /// stream. The uniform array of uaBool encodes the bits into 32-bit words.
55 ///
56 /// The standard implementation of the uaInt16() method is:
57 /// @code
58 /// bool
59 /// UT_JSONParser::uaInt16(int64 length) {
60 /// int16 value;
61 /// if (!jsonBeginArray())
62 /// return false;
63 /// for (int64 i=0; i < length; i++) {
64 /// if (!read(&value, sizeof(int16)))
65 /// return false;
66 /// if (getSwapFlag())
67 /// UTswapBytes(&value, 1);
68 /// if (!jsonInt(value))
69 /// return false;
70 /// }
71 /// return jsonEndArray();
72 /// }
73 /// @endcode
74 ///
75 /// @see UT_JID, UT_JSONHandle
77 {
78 public:
80 
81  UT_JSONParser();
82  ~UT_JSONParser();
83 
84  /// Seek the parser to a specific location in stream (see streams
85  /// seekg)
86  /// If the reset flag is true then the parser will be reset so it
87  /// expects to see the beginning of a JSON stream.
88  bool seekg(exint pos, int dir, bool reset = true);
89 
90  /// Retrieves the stream that is being used internally to read
91  /// This is used for seekable geometry files to read the footer
92  /// without parsing it as JSON.
93  /// Normally using this should be avoided.
94  UT_IStream* getInternalStream();
95 
96  /// Set's binary to given value. This is used to read BJSON without
97  /// having the magic infront of it (for embedded geometry)
98  void setBinary(bool isBinary) { myBinary = isBinary; }
99 
100  /// Parse a single object.
101  /// @param handle @n
102  /// The UT_JSONHandle to perform interpretation of the JSON tokens
103  /// @param is @n
104  /// If specified, data will be read from this stream. The initial
105  /// parseObject() call must have a stream.
106  bool parseObject(UT_JSONHandle &handle, UT_IStream*is=0);
107 
108  /// @{
109  /// Simple convenience method to parse a single string (keys not valid)
110  /// This is done by reading the next object using UT_JSONValue.
111  /// The method fails if the next object in the stream is not a string.
112  bool parseString(UT_WorkBuffer &v);
113  bool parseString(UT_StringHolder &v);
114  /// @}
115 
116  /// @{
117  /// Simple convenience method to parse a single map key (strings not valid)
118  /// This is done by reading the next object using UT_JSONValue
119  /// The method fails if the next object in the stream is not a key.
120  bool parseKey(UT_WorkBuffer &v);
121  bool parseKey(UT_StringHolder &v);
122  /// @}
123  /// Simple convenience method to parse a single string (keys not valid)
124  /// This is done by reading the next object using UT_JSONValue.
125  /// The method fails if the next object in the stream is not a string.
126  bool parseBool(bool &v);
127  /// Simple convenience method to parse a single integer
128  /// This is done by reading the next object using UT_JSONValue
129  /// The method fails if the next object in the stream is not a number or
130  /// bool. Real values are cast to integers.
131  bool parseInteger(int64 &v);
132  /// Alternate short-form
133  bool parseInt(int64 &v) { return parseInteger(v); }
134  /// Simple convenience method to parse a single real
135  /// This is done by reading the next object using UT_JSONValue
136  /// The method fails if the next object in the stream is not a number
137  bool parseReal(fpreal64 &v);
138  /// Generic parsing of a number (int)
139  bool parseNumber(int8 &v);
140  bool parseNumber(int16 &v);
141  bool parseNumber(int32 &v);
142  bool parseNumber(int64 &v) { return parseInteger(v); }
143  bool parseNumber(uint8 &v);
144  bool parseNumber(uint16 &v);
145  /// Generic parsing of a number (real)
146  bool parseNumber(fpreal16 &v);
147  bool parseNumber(fpreal32 &v);
148  bool parseNumber(fpreal64 &v) { return parseReal(v); }
149 
150  bool parseValue(UT_WorkBuffer &v){ return parseString(v); }
151  bool parseValue(UT_StringHolder &v){ return parseString(v); }
152  bool parseValue(bool &v) { return parseBool(v); }
153  bool parseValue(int8 &v) { return parseNumber(v); }
154  bool parseValue(int16 &v) { return parseNumber(v); }
155  bool parseValue(int32 &v) { return parseNumber(v); }
156  bool parseValue(int64 &v) { return parseNumber(v); }
157  bool parseValue(uint8 &v) { return parseNumber(v); }
158  bool parseValue(uint16 &v) { return parseNumber(v); }
159  bool parseValue(fpreal16 &v) { return parseNumber(v); }
160  bool parseValue(fpreal32 &v) { return parseNumber(v); }
161  bool parseValue(fpreal64 &v) { return parseNumber(v); }
162 
163  /// A utility method to load a uniform array of data (ie. those written
164  /// out by UT_JSONWriter::uniformArray()). Returns the number of elements
165  /// successfully extracted from the parser. A maximum of len elements will
166  /// be saved in data.
167  template <typename T>
169  {
170  iterator it = beginArray();
171  int64 array_size = getUniformArraySize();
172  int64 load_size = SYSmin(len, array_size);
173  int64 i;
174 
175  switch (getUniformArrayType())
176  {
177  case UT_JID_INT8:
178  i = UniformArrayHelper<int8, T>::load(it, data, load_size);
179  break;
180  case UT_JID_INT16:
181  i = UniformArrayHelper<int16, T>::load(it, data, load_size);
182  break;
183  case UT_JID_INT32:
184  i = UniformArrayHelper<int32, T>::load(it, data, load_size);
185  break;
186  case UT_JID_INT64:
187  i = UniformArrayHelper<int64, T>::load(it, data, load_size);
188  break;
189  case UT_JID_REAL16:
190  i = UniformArrayHelper<fpreal16, T>::load(it, data, load_size);
191  break;
192  case UT_JID_REAL32:
193  i = UniformArrayHelper<fpreal32, T>::load(it, data, load_size);
194  break;
195  case UT_JID_REAL64:
196  i = UniformArrayHelper<fpreal64, T>::load(it, data, load_size);
197  break;
198  default:
199  i = 0;
200  load_size = 0;
201  break;
202  }
203 
204  if (i < load_size) // error occurred during load
205  return i;
206 
207  // TODO: We eat any trailing array entries for the cases handled above
208  // here as well, and this could be done more efficiently.
209  for ( ; !it.atEnd(); ++it, ++i)
210  {
211  T val;
212  if (!parseValue(val))
213  break;
214  if (i < len)
215  data[i] = val;
216  }
217  return i;
218  }
219 
220  /// A utility method to load blocks of values from an array which can
221  /// load data from uniform arrays very efficiently. Returns the number
222  /// of elements successfully extracted from the parser. A maximum of len
223  /// elements will be saved in data.
224  template <typename T>
226  {
227  int64 unread_size = getUniformArrayUnreadSize();
228  int64 load_size = SYSmin(len, unread_size);
229  int64 i;
230 
231  switch (getUniformArrayType())
232  {
233  case UT_JID_INT8:
234  i = UniformArrayHelper<int8, T>::load(it, data, load_size);
235  break;
236  case UT_JID_INT16:
237  i = UniformArrayHelper<int16, T>::load(it, data, load_size);
238  break;
239  case UT_JID_INT32:
240  i = UniformArrayHelper<int32, T>::load(it, data, load_size);
241  break;
242  case UT_JID_INT64:
243  i = UniformArrayHelper<int64, T>::load(it, data, load_size);
244  break;
245  case UT_JID_REAL16:
246  i = UniformArrayHelper<fpreal16, T>::load(it, data, load_size);
247  break;
248  case UT_JID_REAL32:
249  i = UniformArrayHelper<fpreal32, T>::load(it, data, load_size);
250  break;
251  case UT_JID_REAL64:
252  i = UniformArrayHelper<fpreal64, T>::load(it, data, load_size);
253  break;
254  default:
255  for (i = 0; !it.atEnd() && i < len; ++it, ++i)
256  {
257  T val;
258  if (!parseValue(val))
259  break;
260  data[i] = val;
261  }
262  break;
263  }
264 
265  return i;
266  }
267 
268  /// A utility method to load a uniform array of data (ie. those written
269  /// out by UT_JSONWriter::uniformArray()). Returns the number of elements
270  /// successfully extracted from the parser. A maximum of len elements will
271  /// be saved in data.
272  int64 parseUniformBoolArray(UT_BitArray &data, int64 len);
273 
274 private:
275  /// @private - Used by loadPODArray
276  template <typename OP_TYPE, typename T> bool
277  loadPODUniformArray(OP_TYPE &op, iterator &it, int64 size)
278  {
279  UT_StackBuffer<T> b(size);
280  if (!it.readUniformArray(b.array(), size))
281  return false;
282  bool success = op.setArray((const T*)b, size);
283  return success;
284  }
285  /// @private - Used by parseUniformArray
286  template <typename INTERNAL_T, typename T>
287  class UniformArrayHelper
288  {
289  public:
290  /// size MUST be <= it.getUniformArraySize(), so a return value
291  /// less than size indicates an error occurred.
292  static int64 load(iterator &it, T *data, int64 size)
293  {
295  if (!it.readUniformArray(b.array(), size))
296  return 0;
297  if (std::numeric_limits<INTERNAL_T>::is_integer &&
298  std::numeric_limits<T>::is_integer &&
299  std::numeric_limits<INTERNAL_T>::digits >
300  std::numeric_limits<T>::digits)
301  {
302  for (int64 i = 0; i < size; ++i)
303  {
304  INTERNAL_T v = b[i];
305  // Ondrej says INTERNAL_T should always be the larger
306  // precision type right here.
307  if (v < INTERNAL_T(std::numeric_limits<T>::min()) ||
308  v > INTERNAL_T(std::numeric_limits<T>::max()))
309  return i;
310  data[i] = static_cast<T>(v);
311  }
312  return size;
313  }
314  else
315  {
316  for (int64 i = 0; i < size; ++i)
317  data[i] = static_cast<T>(b[i]);
318  return size;
319  }
320  }
321  };
322  /// @private - Used by parseUniformArray
323  template <typename T>
324  class UniformArrayHelper<T,T>
325  {
326  public:
327  /// size MUST be <= it.getUniformArraySize(), so a return value
328  /// less than size indicates an error occurred.
329  static int64 load(iterator &it, T *data, int64 size)
330  {
331  if (!it.readUniformArray(data, size))
332  return 0;
333  return size;
334  }
335  };
336 public:
337  /// @private Used by iterator to determine uniform array information
338  UT_JID getUniformArrayType() const;
339  /// @private Used by iterator to determine uniform array information
340  int64 getUniformArraySize() const;
341  /// @private Used by iterator to determine uniform array information
342  int64 getUniformArrayUnreadSize() const;
343  /// @{
344  /// @private Used by iterator
345  bool readUniformArray(int8 *buffer, int64 buffer_size);
346  bool readUniformArray(int16 *buffer, int64 buffer_size);
347  bool readUniformArray(int32 *buffer, int64 buffer_size);
348  bool readUniformArray(int64 *buffer, int64 buffer_size);
349  bool readUniformArray(uint8 *buffer, int64 buffer_size);
350  bool readUniformArray(uint16 *buffer, int64 buffer_size);
351  bool readUniformArray(fpreal16 *buffer, int64 buffer_size);
352  bool readUniformArray(fpreal32 *buffer, int64 buffer_size);
353  bool readUniformArray(fpreal64 *buffer, int64 buffer_size);
354  /// @}
355 
356  /// Load an entire array of POD data using the operator passed in.
357  /// This method may allocate a temporary buffer to load a uniform
358  /// array.
359  template <typename OP_TYPE, typename POD_TYPE>
360  bool loadPODArray(OP_TYPE &op)
361  {
362  iterator it = beginArray();
363  int64 n = getUniformArraySize();
364  switch (getUniformArrayType())
365  {
366  case UT_JID_INT8:
367  return loadPODUniformArray<OP_TYPE, int8>
368  (op, it, n);
369  case UT_JID_INT16:
370  return loadPODUniformArray<OP_TYPE, int16>
371  (op, it, n);
372  case UT_JID_INT32:
373  return loadPODUniformArray<OP_TYPE, int32>
374  (op, it, n);
375  case UT_JID_INT64:
376  return loadPODUniformArray<OP_TYPE, int64>
377  (op, it, n);
378  case UT_JID_REAL16:
379  return loadPODUniformArray<OP_TYPE, fpreal16>
380  (op, it, n);
381  case UT_JID_REAL32:
382  return loadPODUniformArray<OP_TYPE, fpreal32>
383  (op, it, n);
384  case UT_JID_REAL64:
385  return loadPODUniformArray<OP_TYPE, fpreal64>
386  (op, it, n);
387  default:
388  break;
389  }
390  POD_TYPE val;
391  for (int64 i = 0; !it.atEnd(); ++it, ++i)
392  {
393  if (!parseNumber(val))
394  return false;
395  if (!op.set(i, val))
396  return false;
397  }
398  return true;
399  }
400 
401  /// Returns true if the next token was the start of a map. If there was an
402  /// error parsing the stream, then error will be set, otherwise the error
403  /// parameter will remain unchanged.
404  bool parseBeginMap(bool &error);
405  /// Returns true if the next token was the start of an array. If there was
406  /// an error parsing the stream, then error will be set, otherwise the
407  /// error parameter will remain unchanged.
408  bool parseBeginArray(bool &error);
409  /// Returns true if the next token was an end map. If there was an error
410  /// parsing the stream, then error will be set, otherwise the error
411  /// parameter will remain unchanged.
412  inline bool parseEndMap(bool &error)
413  {
414  UT_JSONHandle *push = myHandle;
415  myHandle = nullptr;
416  bool ok = parseBeginEnd(UT_JID_MAP_END, error);
417  myHandle = push;
418  return ok;
419  }
420  /// Returns true if the next token was an end of an array. If there was an
421  /// error parsing the stream, then error will be set, otherwise the error
422  /// parameter will remain unchanged.
423  inline bool parseEndArray(bool &error)
424  {
425  UT_JSONHandle *push = myHandle;
426  myHandle = nullptr;
427  bool ok = parseBeginEnd(UT_JID_ARRAY_END, error);
428  myHandle = push;
429  return ok;
430  }
431  /// Simple convenience method to skip the next object in the stream
432  bool skipNextObject();
433 
434  /// Get resulting warnings/errors
435  const UT_StringArray &getErrors() const { return myErrors; }
436 
437  /// The read method should be called whenever data needs to be read from
438  /// the stream. It keeps line counts & character offsets.
439  bool readBytes(void *data, exint bytes);
440 
441  /// Returns whether we're reading a binary or ASCII file
442  bool getBinary() const { return myBinary; }
443 
444  /// Returns the current position in the input stream
445  int64 getStreamLineCount() const;
446  int64 getStreamLineStartPosition() const;
447  int64 getStreamPosition() const;
448 
449  /// Returns the true and sets the filename if the stream supports random
450  /// seeks.
451  bool isRandomAccessFile(UT_WorkBuffer &filename) const;
452 
453  /// When reading raw binary data, this returns whether the endianness of
454  /// the file is different than the endianness of the processor (requiring
455  /// byte swapping). There are convenience methods to read integer/real
456  /// data which automatically swap. However, when reading uniform arrays in
457  /// batch mode, it is more efficient to swap the entire array rather than
458  /// piecemeal.
459  bool getSwapFlag() const { return mySwap; }
460 
461  /// Convenience method to a int8 values
462  bool readValue(int8 *v, exint n) { return readBytes(v, n); }
463  /// Convenience method to read int16 values (possibly byte-swapped)
464  bool readValue(int16 *v, exint n);
465  /// Convenience method to read int32 values (possibly byte-swapped)
466  bool readValue(int32 *v, exint n);
467  /// Convenience method to read int64 values (possibly byte-swapped)
468  bool readValue(int64 *v, exint n);
469 
470  /// Convenience method to read uint8 values
471  bool readValue(uint8 *v, exint n) { return readBytes(v, n); }
472  /// Convenience method to read uint16 values (possibly byte-swapped)
473  bool readValue(uint16 *v, exint n);
474  /// Convenience method to read uint32 values (possibly byte-swapped)
475  bool readValue(uint32 *v, exint n);
476  /// Convenience method to read uint64 values (possibly byte-swapped)
477  bool readValue(uint64 *v, exint n);
478 
479  /// Convenience method to read fpreal16 values (possibly byte-swapped)
480  bool readValue(fpreal16 *v, exint n);
481  /// Convenience method to read fpreal32 values (possibly byte-swapped)
482  bool readValue(fpreal32 *v, exint n);
483  /// Convenience method to read fpreal64 values (possibly byte-swapped)
484  bool readValue(fpreal64 *v, exint n);
485 
486  /// @{
487  /// Convenience method to read a binary encoded string.@n
488  /// @note This should be used when reading uniform arrays of UT_JID_STRING
489  /// type.
492  /// @}
493 
494  /// @{
495  /// Convenience method to read a binary encoded string token. Instead of
496  /// reading an encoded string (readString()), an integer token will be
497  /// read. This indexes the shared string table (see UT_JID_TOKENDEF,
498  /// UT_JID_TOKENREF).
499  /// @note This should be used when reading uniform arrays of
500  /// UT_JID_TOKENREF type.
501  bool readStringToken(UT_WorkBuffer &storage);
502  bool readStringToken(UT_StringHolder &str);
503  /// @}
504 
505  /// Add an error message. If the terminate flag is set, parsing will be
506  /// terminated.
507  void addFatal(const char *fmt, ...)
509  void addWarning(const char *fmt, ...)
511 
512  /// Steal errors from another parser (leaves the other parser intact)
513  void stealErrors(const UT_JSONParser &parser);
514 
515  /// @brief Traverse an array object in the parser
516  ///
517  /// This class will iterate over an array. There is no object associated
518  /// with the array, it's up to the caller to load the objects
519  ///
520  /// There is no rewind() operation available on this iterator
521  /// @code
522  /// UT_JSONParser::iterator it;
523  /// for (it = UT_JSONParser::beginMap(); !it.atEnd(); ++it)
524  /// or
525  /// for (it = UT_JSONParser::beginArray(); !it.atEnd(); ++it)
526  /// @endcode
528  {
529  public:
531  : myParser(nullptr)
532  , myMap(false)
533  , myValid(false)
534  , myError(false)
535  {
536  }
537  iterator(const iterator &src)
538  {
539  *this = src;
540  }
542 
543  const iterator &operator=(const iterator &src)
544  {
545  myParser = src.myParser;
546  myMap = src.myMap;
547  myValid = src.myValid;
548  myError = src.myError;
549  return *this;
550  }
551 
552  /// ++iterator
553  iterator &operator++() { advance(); return *this; }
554  /// Caution: The post-increment operator has side effects and is
555  /// equivalent to the iterator @b after the increment is performed.
556  iterator &operator++(int) { advance(); return *this; }
557 
558  bool atEnd() const { return !myValid || myError; }
559  void advance()
560  {
561  if (myParser && !myError)
562  {
563  bool hit;
564  hit = (myMap) ? myParser->parseEndMap(myError)
565  : myParser->parseEndArray(myError);
566  if (hit || myError)
567  myValid = false;
568  }
569  }
570  /// Get the key from the map.
571  /// If we're iterating over an array, this assumes that the next
572  /// array element will be a string token. This allows for
573  /// "ordered" maps to be stored in an array of tuples
574  /// (string,value)
575  ///
576  /// The T template can be either UT_WorkBuffer or UT_StringHolder
577  template <typename T>
578  bool getKey(T &key)
579  {
580  if (myParser && myValid)
581  {
582  return myMap ? myParser->parseKey(key)
583  : myParser->parseString(key);
584  }
585  if (myParser)
586  {
587  myParser->addWarning(
588  "Missing key while parsing map");
589  }
590  myValid = false;
591  myError = true;
592  return false;
593  }
594 
595  /// Get a lower case map key (for case insensitive maps)
596  template <typename T>
597  bool getLowerKey(T &key)
598  {
599  if (getKey(key))
600  {
601  toLower(key);
602  return true;
603  }
604  return false;
605  }
606 
607  /// The error state records whether any errors were encountered
608  /// during the iterator's parse operations.
609  bool getErrorState() const { return myError; }
610 
611  /// Return the uniform array type (UT_JID_NULL if not uniform array)
613  {
614  return myParser ? myParser->getUniformArrayType()
615  : UT_JID_NULL;
616  }
617  /// Return the number of elements in the uniform array (0 if empty)
619  {
620  return myParser ? myParser->getUniformArraySize()
621  : -1;
622  }
623  /// Return the remaining number of elements in the uniform array
624  /// (0 if empty)
626  {
627  return myParser ?
628  myParser->getUniformArrayUnreadSize() : -1;
629  }
630 
631  /// Read uniform array straight into a buffer. This template only
632  /// works for int8, int16, int32, int64, fpreal16, fpreal32,
633  /// fpreal64.
634  template <typename T>
636  {
637  if (!myParser)
638  return (myError = false);
639  if (!myParser->readUniformArray(buffer, size))
640  return (myError = false);
641  // Now, advance to check end condition of array
642  advance();
643  return !myError;
644  }
645 
646  private:
647  static inline void toLower(UT_WorkBuffer &w) { w.lower(); }
648  static void toLower(UT_StringHolder &w) { w = w.toLower(); }
649  iterator(UT_JSONParser *p, bool map)
650  : myParser(p)
651  , myMap(map)
652  , myValid(false)
653  , myError(false)
654  {
655  if (myParser)
656  {
657  if (myMap)
658  {
659  if ((myValid = myParser->parseBeginMap(myError)))
660  {
661  // Check for an empty map
662  if (!myError)
663  myValid = !myParser->parseEndMap(myError);
664  }
665  }
666  else
667  {
668  if ((myValid = myParser->parseBeginArray(myError)))
669  {
670  if (!myError)
671  myValid = !myParser->parseEndArray(myError);
672  }
673  }
674  if (myError)
675  myValid = false;
676  }
677  }
678 
679  UT_JSONParser *myParser;
680  bool myMap;
681  bool myValid;
682  bool myError;
683 
684  friend class UT_JSONParser;
685  };
686  typedef iterator traverser; // For backward compatibility
687 
688  iterator beginMap() { return iterator(this, true); }
689  iterator beginArray() { return iterator(this, false); }
690 
691  /// The TiledStream class reads data that was generated by a
692  /// UT_JSONWriter::TiledStream. The reader expects an array, followed by
693  /// multiple arrays of uint8. The multiple arrays appear as a single
694  /// stream to the user. To read a tiled stream from a JSON file, you would
695  /// do something like: @code
696  /// bool copyStream(UT_JSONParser &p, ostream &os)
697  /// {
698  /// UT_JSONParser::TiledStream is(p);
699  /// while (true)
700  /// {
701  /// char buffer[128];
702  /// exint nread = is.read(buffer, 128);
703  /// if (nread < 0)
704  /// return false; // See p.getErrors() for error message
705  /// if (nread == 0) // Read to end of stream
706  /// break;
707  /// os.write(buffer, nread);
708  /// }
709  /// return true;
710  /// }
711  /// @endcode
712  class UT_API TiledStreamBuf : public std::streambuf
713  {
714  public:
716  ~TiledStreamBuf() override;
717 
718  int_type underflow() override;
719 
720  private:
721  /// Returns the number of bytes read or less than 0 on error.
722  exint read(void *buffer, exint bufsize);
723  exint loadBuffer();
724  UT_JSONParser &myParser;
726  char *myBuffer;
727  exint mySize;
728  exint myCapacity;
729  };
730 
731  class UT_API TiledStream : public std::istream
732  {
733  public:
735  ~TiledStream() override;
736  private:
737  TiledStreamBuf myBuf;
738  };
739 
740 private:
741  // Different parsing states
742  enum ut_JParseState
743  {
744  JSON_START, // Prior to parsing JSON file
745  JSON_COMPLETE, // Successful parsing
746  JSON_ERROR, // Error thrown
747 
748  JSON_MAP_START, // Starting a map (almost same as JSON_MAP_NEED_KEY)
749  JSON_MAP_SEP, // Expecting a map separator
750  JSON_MAP_NEED_VAL, // Expecting a map value
751  JSON_MAP_GOT_VAL, // Expecting end of map or value separator
752  JSON_MAP_NEED_KEY, // Expecting a map key (string)
753 
754  JSON_ARRAY_START, // Starting an array
755  JSON_ARRAY_NEED_VAL, // Expecting a value for an array
756  JSON_ARRAY_GOT_VAL, // Expecting end of array or value separator
757  };
758 
759  /// @private Set a stream for the parser.
760  UT_IStream *setIStream(UT_IStream *is);
761 
762  /// @private Parse the stream
763  bool parseStream(exint nobjects);
764 
765  /// @private Parse a single token
766  bool parseToken(UT_JID &token);
767 
768  /// @private Parse a simple object
769  bool parseSimpleObject(ut_SimpleJSONObjectHandle &h);
770 
771  /// @private Test if next token is an end-object
772  bool parseBeginEnd(UT_JID type, bool &error);
773 
774  /// @private: Read an encoded length
775  /// @see UT_JID
776  bool readLength(int64 &l);
777  /// @private: Peek at the next token. The result will be in myPeek
778  bool peekToken();
779  /// @private: Process a token
780  bool readToken(ut_JValue &value);
781  /// @private: Push parse state
782  bool pushState(ut_JParseState state); // Push state
783  /// @private: Set parse state
784  void setState(ut_JParseState state); // Set top of stack
785  /// @private: Pop parse state
786  bool popState(); // Pop state
787  /// @private: Query parse state
788  ut_JParseState getState() const { return myState; }
789  /// @private: Read UTF-8 quoted string
790  bool readQuotedString(UT_StringHolder &buf);
791  /// @private: Read number/null/true/false
792  bool readNumber(ut_JValue &value);
793  /// @private: defineToken()
794  bool defineToken();
795  /// @private: undefineToken()
796  bool undefineToken();
797  /// @private: undefineToken()
798  void undefineToken(int64 id);
799  /// @private: lookupToken()
800  bool lookupToken(UT_StringHolder &value);
801  /// @private: clearTokens()
802  void clearTokens();
803 
804  typedef UT_Map<int64, UT_StringHolder> TokenMap;
805 
806  UT_JSONHandle *myHandle;
807  UT_IStream *myStream;
808  ut_JValue *myPeek;
809  ut_JValue *myPeekCache;
810  UT_StringArray myErrors;
811  UT_IntArray myStack; // State stack
812  TokenMap myTokens;
813  ut_JParseState myState;
814  int64 myLineCount;
815  int64 myLineStartPosition;
816  bool mySwap;
817  bool myBinary;
818 
819  friend class UT_AutoJSONParser;
820 };
821 
822 /// Convenience class to create a JSON parser from a simple input
823 ///
824 /// For example: @code
825 /// // Function to parse the JSON stream
826 /// bool load(UT_JSONParser &p) { ... }
827 ///
828 /// // Function to parse from a std::string
829 /// bool load(const std::string &str)
830 /// {
831 /// UT_JSONAutoParser p(str.c_str(), str.size());
832 /// return load(*p);
833 /// }
834 ///
835 /// // Function to parse from a UT_JSONValue
836 /// bool load(const UT_JSONValue &v)
837 /// {
838 /// UT_JSONAutoParser p(v);
839 /// return load(*p);
840 /// }
841 /// @endcode
842 ///
844 {
845 public:
847 
848  /// Load JSON from the given UT_IStream
850 
851  /// Load JSON from the given string
852  UT_AutoJSONParser(const char *buffer, int64 size);
853 
854  /// Load JSON from the UT_JSONValue
856 
858  {
859  close();
860  }
861 
862  void attach(UT_IStream &is);
863 
864  /// @{
865  /// Access to the parser
866  UT_JSONParser &parser() { return myParser; }
867  UT_JSONParser &operator*() { return myParser; }
868  UT_JSONParser *operator->() { return &myParser; }
869  /// @}
870 
871  // Implicit casting to a UT_JSONParser
872  operator UT_JSONParser &() { return myParser; }
873 
874  /// Close the parser
875  void close();
876 
877 private:
878 
879  UT_JSONParser myParser;
880  UT_WorkBuffer myBuffer;
881  UT_IStream* myIStream;
882  bool myAllocatedIStream;
883 };
884 
885 #endif
The following byte represents an 8 bit integer.
vint4 max(const vint4 &a, const vint4 &b)
Definition: simd.h:4703
*pool push(my_func, arg1,...)
unsigned short uint16
Definition: SYS_Types.h:38
No data follows the NULL token.
GT_API const UT_StringHolder filename
GLsizeiptr size
Definition: glew.h:1681
GLenum src
Definition: glew.h:2410
int int32
Definition: SYS_Types.h:39
The following 4 bytes represent an 32 bit real (float)
GLsizei bufsize
Definition: glew.h:2581
UT_JID
The UT_JID enums are used in byte-stream encoding of binary JSON.
void setBinary(bool isBinary)
Definition: UT_JSONParser.h:98
*get result *(waiting if necessary)*A common idiom is to fire a bunch of sub tasks at the and then *wait for them to all complete We provide a helper class
Definition: thread.h:643
Marks the end of an array object.
GLuint const GLfloat * val
Definition: glew.h:2794
0x23 and 0x24 are reserved for future use (32/64 bit unsigned)
int64 parseArrayValues(iterator &it, T *data, int64 len)
bool parseValue(fpreal64 &v)
UT_JSONHandle processes events from a UT_JSONParser parser.
Definition: UT_JSONHandle.h:36
int64 exint
Definition: SYS_Types.h:125
int64 getUniformArraySize() const
Return the number of elements in the uniform array (0 if empty)
UT_JID getUniformArrayType() const
Return the uniform array type (UT_JID_NULL if not uniform array)
iterator & operator++()
++iterator
iterator beginArray()
bool parseValue(fpreal16 &v)
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:76
#define UT_API
Definition: UT_API.h:13
GLdouble l
Definition: glew.h:9122
const GLdouble * v
Definition: glew.h:1391
void close() override
GLboolean reset
Definition: glew.h:4959
unsigned long long uint64
Definition: SYS_Types.h:117
float fpreal32
Definition: SYS_Types.h:200
void read(T &in, bool &v)
Definition: ImfXdr.h:611
const UT_StringArray & getErrors() const
Get resulting warnings/errors.
bool parseNumber(int64 &v)
double fpreal64
Definition: SYS_Types.h:201
unsigned char uint8
Definition: SYS_Types.h:36
The following 8 bytes represent an 64 bit real (float)
bool parseInt(int64 &v)
Alternate short-form.
The following 8 bytes represent an 64 bit integer.
bool parseValue(int8 &v)
bool readValue(int8 *v, exint n)
Convenience method to a int8 values.
const iterator & operator=(const iterator &src)
The following 2 bytes represent an 16 bit integer.
int64 getUniformArrayUnreadSize() const
UT_JSONParser & parser()
bool parseValue(fpreal32 &v)
GLuint buffer
Definition: glew.h:1680
GLint GLenum GLsizei GLint GLsizei const void * data
Definition: glew.h:1379
UT_JSONParser & operator*()
bool readValue(uint8 *v, exint n)
Convenience method to read uint8 values.
#define SYS_PRINTF_CHECK_ATTRIBUTE(string_index, first_to_check)
Definition: SYS_Types.h:433
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1890
Traverse an array object in the parser.
GLsizei n
Definition: glew.h:4040
long long int64
Definition: SYS_Types.h:116
bool parseValue(int64 &v)
bool getErrorState() const
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:8011
signed char int8
Definition: SYS_Types.h:35
The following 4 bytes represent an 32 bit integer.
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1253
iterator(const iterator &src)
bool getBinary() const
Returns whether we're reading a binary or ASCII file.
bool getSwapFlag() const
int64 parseUniformArray(T *data, int64 len)
GLdouble GLdouble GLdouble b
Definition: glew.h:9122
GLfloat GLfloat p
Definition: glew.h:16321
Marks the end of a map object.
bool parseValue(UT_WorkBuffer &v)
class UT_API iterator
Definition: UT_JSONParser.h:79
short int16
Definition: SYS_Types.h:37
bool parseEndArray(bool &error)
SYS_NO_DISCARD_RESULT UT_StringRef toLower() const
bool loadPODArray(OP_TYPE &op)
UT_JSONParser * operator->()
bool readUniformArray(T *buffer, int64 size)
iterator & operator++(int)
Name readString(std::istream &is)
Definition: Name.h:20
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:77
unsigned int uint32
Definition: SYS_Types.h:40
bool parseValue(uint16 &v)
bool parseValue(int16 &v)
bool parseValue(UT_StringHolder &v)
GLuint64EXT * result
Definition: glew.h:14007
getOption("OpenEXR.storage") storage
Definition: HDK_Image.dox:276
bool parseEndMap(bool &error)
#define const
Definition: zconf.h:214
vint4 min(const vint4 &a, const vint4 &b)
Definition: simd.h:4694
bool parseValue(int32 &v)
iterator beginMap()
GLenum GLuint GLsizei const GLchar * buf
Definition: glew.h:2580
#define SYSmin(a, b)
Definition: SYS_Math.h:1522
bool parseValue(bool &v)
bool parseValue(uint8 &v)
GLsizei const GLfloat * value
Definition: glew.h:1849
void lower()
Convert string to lower case.
bool getLowerKey(T &key)
Get a lower case map key (for case insensitive maps)
iterator traverser
bool parseNumber(fpreal64 &v)
GLenum GLsizei len
Definition: glew.h:7752