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