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