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