CoolProp  4.2.5
An open-source fluid property and humid air property database
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
reader.h
Go to the documentation of this file.
1 #ifndef RAPIDJSON_READER_H_
2 #define RAPIDJSON_READER_H_
3 
4 // Copyright (c) 2011 Milo Yip (miloyip@gmail.com)
5 // Version 0.1
6 
7 #include "rapidjson.h"
8 #include "internal/pow10.h"
9 #include "internal/stack.h"
10 #include <csetjmp>
11 
12 #ifdef RAPIDJSON_SSE42
13 #include <nmmintrin.h>
14 #elif defined(RAPIDJSON_SSE2)
15 #include <emmintrin.h>
16 #endif
17 
18 #ifdef _MSC_VER
19 #pragma warning(push)
20 #pragma warning(disable : 4127) // conditional expression is constant
21 #endif
22 
23 #ifndef RAPIDJSON_PARSE_ERROR
24 #define RAPIDJSON_PARSE_ERROR(msg, offset) \
25  RAPIDJSON_MULTILINEMACRO_BEGIN \
26  parseError_ = msg; \
27  errorOffset_ = offset; \
28  longjmp(jmpbuf_, 1); \
29  RAPIDJSON_MULTILINEMACRO_END
30 #endif
31 
32 namespace rapidjson {
33 
35 // ParseFlag
36 
38 enum ParseFlag {
41 };
42 
44 // Handler
45 
67 // BaseReaderHandler
69 
71 
74 template<typename Encoding = UTF8<> >
76  typedef typename Encoding::Ch Ch;
77 
78  void Default() {}
79  void Null() { Default(); }
80  void Bool(bool) { Default(); }
81  void Int(int) { Default(); }
82  void Uint(unsigned) { Default(); }
83  void Int64(int64_t) { Default(); }
84  void Uint64(uint64_t) { Default(); }
85  void Double(double) { Default(); }
86  void String(const Ch*, SizeType, bool) { Default(); }
87  void StartObject() { Default(); }
88  void EndObject(SizeType) { Default(); }
89  void StartArray() { Default(); }
90  void EndArray(SizeType) { Default(); }
91 };
92 
94 // SkipWhitespace
95 
97 
100 template<typename Stream>
101 void SkipWhitespace(Stream& stream) {
102  Stream s = stream; // Use a local copy for optimization
103  while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
104  s.Take();
105  stream = s;
106 }
107 
108 #ifdef RAPIDJSON_SSE42
109 inline const char *SkipWhitespace_SIMD(const char* p) {
111  static const char whitespace[16] = " \n\r\t";
112  __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]);
113 
114  for (;;) {
115  __m128i s = _mm_loadu_si128((const __m128i *)p);
116  unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
117  if (r == 0) // all 16 characters are whitespace
118  p += 16;
119  else { // some of characters may be non-whitespace
120 #ifdef _MSC_VER // Find the index of first non-whitespace
121  unsigned long offset;
122  if (_BitScanForward(&offset, r))
123  return p + offset;
124 #else
125  if (r != 0)
126  return p + __builtin_ffs(r) - 1;
127 #endif
128  }
129  }
130 }
131 
132 #elif defined(RAPIDJSON_SSE2)
133 
135 inline const char *SkipWhitespace_SIMD(const char* p) {
136  static const char whitespaces[4][17] = {
137  " ",
138  "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
139  "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
140  "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
141 
142  __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]);
143  __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]);
144  __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]);
145  __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]);
146 
147  for (;;) {
148  __m128i s = _mm_loadu_si128((const __m128i *)p);
149  __m128i x = _mm_cmpeq_epi8(s, w0);
150  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
151  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
152  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
153  unsigned short r = ~_mm_movemask_epi8(x);
154  if (r == 0) // all 16 characters are whitespace
155  p += 16;
156  else { // some of characters may be non-whitespace
157 #ifdef _MSC_VER // Find the index of first non-whitespace
158  unsigned long offset;
159  if (_BitScanForward(&offset, r))
160  return p + offset;
161 #else
162  if (r != 0)
163  return p + __builtin_ffs(r) - 1;
164 #endif
165  }
166  }
167 }
168 
169 #endif // RAPIDJSON_SSE2
170 
171 #ifdef RAPIDJSON_SIMD
172 template<> inline void SkipWhitespace(InsituStringStream& stream) {
174  stream.src_ = const_cast<char*>(SkipWhitespace_SIMD(stream.src_));
175 }
176 
178 template<> inline void SkipWhitespace(StringStream& stream) {
179  stream.src_ = SkipWhitespace_SIMD(stream.src_);
180 }
181 #endif // RAPIDJSON_SIMD
182 
184 // GenericReader
185 
187 
201 template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
203 public:
204  typedef typename Encoding::Ch Ch;
205 
207 
210  GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {}
211 
213 
220  template <unsigned parseFlags, typename Stream, typename Handler>
221  bool Parse(Stream& stream, Handler& handler) {
222  parseError_ = 0;
223  errorOffset_ = 0;
224 
225 #ifdef _MSC_VER
226 #pragma warning(push)
227 #pragma warning(disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
228 #endif
229  if (setjmp(jmpbuf_)) {
230 #ifdef _MSC_VER
231 #pragma warning(pop)
232 #endif
233  stack_.Clear();
234  return false;
235  }
236 
237  SkipWhitespace(stream);
238 
239  if (stream.Peek() == '\0')
240  RAPIDJSON_PARSE_ERROR("Text only contains white space(s)", stream.Tell());
241  else {
242  switch (stream.Peek()) {
243  case '{': ParseObject<parseFlags>(stream, handler); break;
244  case '[': ParseArray<parseFlags>(stream, handler); break;
245  default: RAPIDJSON_PARSE_ERROR("Expect either an object or array at root", stream.Tell());
246  }
247  SkipWhitespace(stream);
248 
249  if (stream.Peek() != '\0')
250  RAPIDJSON_PARSE_ERROR("Nothing should follow the root object or array.", stream.Tell());
251  }
252 
253  return true;
254  }
255 
256  bool HasParseError() const { return parseError_ != 0; }
257  const char* GetParseError() const { return parseError_; }
258  size_t GetErrorOffset() const { return errorOffset_; }
259 
260 private:
261  // Parse object: { string : value, ... }
262  template<unsigned parseFlags, typename Stream, typename Handler>
263  void ParseObject(Stream& stream, Handler& handler) {
264  RAPIDJSON_ASSERT(stream.Peek() == '{');
265  stream.Take(); // Skip '{'
266  handler.StartObject();
267  SkipWhitespace(stream);
268 
269  if (stream.Peek() == '}') {
270  stream.Take();
271  handler.EndObject(0); // empty object
272  return;
273  }
274 
275  for (SizeType memberCount = 0;;) {
276  if (stream.Peek() != '"') {
277  RAPIDJSON_PARSE_ERROR("Name of an object member must be a string", stream.Tell());
278  break;
279  }
280 
281  ParseString<parseFlags>(stream, handler);
282  SkipWhitespace(stream);
283 
284  if (stream.Take() != ':') {
285  RAPIDJSON_PARSE_ERROR("There must be a colon after the name of object member", stream.Tell());
286  break;
287  }
288  SkipWhitespace(stream);
289 
290  ParseValue<parseFlags>(stream, handler);
291  SkipWhitespace(stream);
292 
293  ++memberCount;
294 
295  switch(stream.Take()) {
296  case ',': SkipWhitespace(stream); break;
297  case '}': handler.EndObject(memberCount); return;
298  default: RAPIDJSON_PARSE_ERROR("Must be a comma or '}' after an object member", stream.Tell());
299  }
300  }
301  }
302 
303  // Parse array: [ value, ... ]
304  template<unsigned parseFlags, typename Stream, typename Handler>
305  void ParseArray(Stream& stream, Handler& handler) {
306  RAPIDJSON_ASSERT(stream.Peek() == '[');
307  stream.Take(); // Skip '['
308  handler.StartArray();
309  SkipWhitespace(stream);
310 
311  if (stream.Peek() == ']') {
312  stream.Take();
313  handler.EndArray(0); // empty array
314  return;
315  }
316 
317  for (SizeType elementCount = 0;;) {
318  ParseValue<parseFlags>(stream, handler);
319  ++elementCount;
320  SkipWhitespace(stream);
321 
322  switch (stream.Take()) {
323  case ',': SkipWhitespace(stream); break;
324  case ']': handler.EndArray(elementCount); return;
325  default: RAPIDJSON_PARSE_ERROR("Must be a comma or ']' after an array element.", stream.Tell());
326  }
327  }
328  }
329 
330  template<unsigned parseFlags, typename Stream, typename Handler>
331  void ParseNull(Stream& stream, Handler& handler) {
332  RAPIDJSON_ASSERT(stream.Peek() == 'n');
333  stream.Take();
334 
335  if (stream.Take() == 'u' && stream.Take() == 'l' && stream.Take() == 'l')
336  handler.Null();
337  else
338  RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1);
339  }
340 
341  template<unsigned parseFlags, typename Stream, typename Handler>
342  void ParseTrue(Stream& stream, Handler& handler) {
343  RAPIDJSON_ASSERT(stream.Peek() == 't');
344  stream.Take();
345 
346  if (stream.Take() == 'r' && stream.Take() == 'u' && stream.Take() == 'e')
347  handler.Bool(true);
348  else
349  RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell());
350  }
351 
352  template<unsigned parseFlags, typename Stream, typename Handler>
353  void ParseFalse(Stream& stream, Handler& handler) {
354  RAPIDJSON_ASSERT(stream.Peek() == 'f');
355  stream.Take();
356 
357  if (stream.Take() == 'a' && stream.Take() == 'l' && stream.Take() == 's' && stream.Take() == 'e')
358  handler.Bool(false);
359  else
360  RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1);
361  }
362 
363  // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
364  template<typename Stream>
365  unsigned ParseHex4(Stream& stream) {
366  Stream s = stream; // Use a local copy for optimization
367  unsigned codepoint = 0;
368  for (int i = 0; i < 4; i++) {
369  Ch c = s.Take();
370  codepoint <<= 4;
371  codepoint += c;
372  if (c >= '0' && c <= '9')
373  codepoint -= '0';
374  else if (c >= 'A' && c <= 'F')
375  codepoint -= 'A' - 10;
376  else if (c >= 'a' && c <= 'f')
377  codepoint -= 'a' - 10;
378  else
379  RAPIDJSON_PARSE_ERROR("Incorrect hex digit after \\u escape", s.Tell() - 1);
380  }
381  stream = s; // Restore stream
382  return codepoint;
383  }
384 
385  // Parse string, handling the prefix and suffix double quotes and escaping.
386  template<unsigned parseFlags, typename Stream, typename Handler>
387  void ParseString(Stream& stream, Handler& handler) {
388 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
389  static const Ch escape[256] = {
390  Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
391  Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
392  0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
393  0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
394  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
395  };
396 #undef Z16
397 
398  Stream s = stream; // Use a local copy for optimization
399  RAPIDJSON_ASSERT(s.Peek() == '\"');
400  s.Take(); // Skip '\"'
401  Ch *head;
402  SizeType len;
403  if (parseFlags & kParseInsituFlag)
404  head = s.PutBegin();
405  else
406  len = 0;
407 
408 #define RAPIDJSON_PUT(x) \
409  do { \
410  if (parseFlags & kParseInsituFlag) \
411  s.Put(x); \
412  else { \
413  *stack_.template Push<Ch>() = x; \
414  ++len; \
415  } \
416  } while(false)
417 
418  for (;;) {
419  Ch c = s.Take();
420  if (c == '\\') { // Escape
421  Ch e = s.Take();
422  if ((sizeof(Ch) == 1 || e < 256) && escape[(unsigned char)e])
423  RAPIDJSON_PUT(escape[(unsigned char)e]);
424  else if (e == 'u') { // Unicode
425  unsigned codepoint = ParseHex4(s);
426  if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { // Handle UTF-16 surrogate pair
427  if (s.Take() != '\\' || s.Take() != 'u') {
428  RAPIDJSON_PARSE_ERROR("Missing the second \\u in surrogate pair", s.Tell() - 2);
429  return;
430  }
431  unsigned codepoint2 = ParseHex4(s);
432  if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) {
433  RAPIDJSON_PARSE_ERROR("The second \\u in surrogate pair is invalid", s.Tell() - 2);
434  return;
435  }
436  codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
437  }
438 
439  Ch buffer[4];
440  SizeType count = SizeType(Encoding::Encode(buffer, codepoint) - &buffer[0]);
441 
442  if (parseFlags & kParseInsituFlag)
443  for (SizeType i = 0; i < count; i++)
444  s.Put(buffer[i]);
445  else {
446  memcpy(stack_.template Push<Ch>(count), buffer, count * sizeof(Ch));
447  len += count;
448  }
449  }
450  else {
451  RAPIDJSON_PARSE_ERROR("Unknown escape character", stream.Tell() - 1);
452  return;
453  }
454  }
455  else if (c == '"') { // Closing double quote
456  if (parseFlags & kParseInsituFlag) {
457  size_t length = s.PutEnd(head);
458  RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
459  RAPIDJSON_PUT('\0'); // null-terminate the string
460  handler.String(head, SizeType(length), false);
461  }
462  else {
463  RAPIDJSON_PUT('\0');
464  handler.String(stack_.template Pop<Ch>(len), len - 1, true);
465  }
466  stream = s; // restore stream
467  return;
468  }
469  else if (c == '\0') {
470  RAPIDJSON_PARSE_ERROR("lacks ending quotation before the end of string", stream.Tell() - 1);
471  return;
472  }
473  else if ((unsigned)c < 0x20) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
474  RAPIDJSON_PARSE_ERROR("Incorrect unescaped character in string", stream.Tell() - 1);
475  return;
476  }
477  else
478  RAPIDJSON_PUT(c); // Normal character, just copy
479  }
480 #undef RAPIDJSON_PUT
481  }
482 
483  template<unsigned parseFlags, typename Stream, typename Handler>
484  void ParseNumber(Stream& stream, Handler& handler) {
485  Stream s = stream; // Local copy for optimization
486  // Parse minus
487  bool minus = false;
488  if (s.Peek() == '-') {
489  minus = true;
490  s.Take();
491  }
492 
493  // Parse int: zero / ( digit1-9 *DIGIT )
494  unsigned i;
495  bool try64bit = false;
496  if (s.Peek() == '0') {
497  i = 0;
498  s.Take();
499  }
500  else if (s.Peek() >= '1' && s.Peek() <= '9') {
501  i = s.Take() - '0';
502 
503  if (minus)
504  while (s.Peek() >= '0' && s.Peek() <= '9') {
505  if (i >= 214748364) { // 2^31 = 2147483648
506  if (i != 214748364 || s.Peek() > '8') {
507  try64bit = true;
508  break;
509  }
510  }
511  i = i * 10 + (s.Take() - '0');
512  }
513  else
514  while (s.Peek() >= '0' && s.Peek() <= '9') {
515  if (i >= 429496729) { // 2^32 - 1 = 4294967295
516  if (i != 429496729 || s.Peek() > '5') {
517  try64bit = true;
518  break;
519  }
520  }
521  i = i * 10 + (s.Take() - '0');
522  }
523  }
524  else {
525  RAPIDJSON_PARSE_ERROR("Expect a value here.", stream.Tell());
526  return;
527  }
528 
529  // Parse 64bit int
530  uint64_t i64 = 0;
531  bool useDouble = false;
532  if (try64bit) {
533  i64 = i;
534  if (minus)
535  while (s.Peek() >= '0' && s.Peek() <= '9') {
536  if (i64 >= 922337203685477580uLL) // 2^63 = 9223372036854775808
537  if (i64 != 922337203685477580uLL || s.Peek() > '8') {
538  useDouble = true;
539  break;
540  }
541  i64 = i64 * 10 + (s.Take() - '0');
542  }
543  else
544  while (s.Peek() >= '0' && s.Peek() <= '9') {
545  if (i64 >= 1844674407370955161uLL) // 2^64 - 1 = 18446744073709551615
546  if (i64 != 1844674407370955161uLL || s.Peek() > '5') {
547  useDouble = true;
548  break;
549  }
550  i64 = i64 * 10 + (s.Take() - '0');
551  }
552  }
553 
554  // Force double for big integer
555  double d = 0.0;
556  if (useDouble) {
557  d = (double)i64;
558  while (s.Peek() >= '0' && s.Peek() <= '9') {
559  if (d >= 1E307) {
560  RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell());
561  return;
562  }
563  d = d * 10 + (s.Take() - '0');
564  }
565  }
566 
567  // Parse frac = decimal-point 1*DIGIT
568  int expFrac = 0;
569  if (s.Peek() == '.') {
570  if (!useDouble) {
571  d = try64bit ? (double)i64 : (double)i;
572  useDouble = true;
573  }
574  s.Take();
575 
576  if (s.Peek() >= '0' && s.Peek() <= '9') {
577  d = d * 10 + (s.Take() - '0');
578  --expFrac;
579  }
580  else {
581  RAPIDJSON_PARSE_ERROR("At least one digit in fraction part", stream.Tell());
582  return;
583  }
584 
585  while (s.Peek() >= '0' && s.Peek() <= '9') {
586  if (expFrac > -16) {
587  d = d * 10 + (s.Peek() - '0');
588  --expFrac;
589  }
590  s.Take();
591  }
592  }
593 
594  // Parse exp = e [ minus / plus ] 1*DIGIT
595  int exp = 0;
596  if (s.Peek() == 'e' || s.Peek() == 'E') {
597  if (!useDouble) {
598  d = try64bit ? (double)i64 : (double)i;
599  useDouble = true;
600  }
601  s.Take();
602 
603  bool expMinus = false;
604  if (s.Peek() == '+')
605  s.Take();
606  else if (s.Peek() == '-') {
607  s.Take();
608  expMinus = true;
609  }
610 
611  if (s.Peek() >= '0' && s.Peek() <= '9') {
612  exp = s.Take() - '0';
613  while (s.Peek() >= '0' && s.Peek() <= '9') {
614  exp = exp * 10 + (s.Take() - '0');
615  if (exp > 308) {
616  RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell());
617  return;
618  }
619  }
620  }
621  else {
622  RAPIDJSON_PARSE_ERROR("At least one digit in exponent", s.Tell());
623  return;
624  }
625 
626  if (expMinus)
627  exp = -exp;
628  }
629 
630  // Finish parsing, call event according to the type of number.
631  if (useDouble) {
632  d *= internal::Pow10(exp + expFrac);
633  handler.Double(minus ? -d : d);
634  }
635  else {
636  if (try64bit) {
637  if (minus)
638  handler.Int64(-(int64_t)i64);
639  else
640  handler.Uint64(i64);
641  }
642  else {
643  if (minus)
644  handler.Int(-(int)i);
645  else
646  handler.Uint(i);
647  }
648  }
649 
650  stream = s; // restore stream
651  }
652 
653  // Parse any JSON value
654  template<unsigned parseFlags, typename Stream, typename Handler>
655  void ParseValue(Stream& stream, Handler& handler) {
656  switch (stream.Peek()) {
657  case 'n': ParseNull <parseFlags>(stream, handler); break;
658  case 't': ParseTrue <parseFlags>(stream, handler); break;
659  case 'f': ParseFalse <parseFlags>(stream, handler); break;
660  case '"': ParseString<parseFlags>(stream, handler); break;
661  case '{': ParseObject<parseFlags>(stream, handler); break;
662  case '[': ParseArray <parseFlags>(stream, handler); break;
663  default : ParseNumber<parseFlags>(stream, handler);
664  }
665  }
666 
667  static const size_t kDefaultStackCapacity = 256;
668  internal::Stack<Allocator> stack_;
669  jmp_buf jmpbuf_;
670  const char* parseError_;
671  size_t errorOffset_;
672 }; // class GenericReader
673 
676 
677 } // namespace rapidjson
678 
679 #ifdef _MSC_VER
680 #pragma warning(pop)
681 #endif
682 
683 #endif // RAPIDJSON_READER_H_
void Uint(unsigned)
Definition: reader.h:82
Concept for receiving events from GenericReader upon parsing.
void Int64(int64_t)
Definition: reader.h:83
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
Definition: reader.h:202
unsigned SizeType
Use 32-bit array/string indices even for 64-bit platform, instead of using size_t.
Definition: rapidjson.h:67
void Uint64(uint64_t)
Definition: reader.h:84
#define Z16
GenericInsituStringStream< UTF8<> > InsituStringStream
Definition: rapidjson.h:507
GenericReader(Allocator *allocator=0, size_t stackCapacity=kDefaultStackCapacity)
Constructor.
Definition: reader.h:210
std::vector< double > x(ncmax, 0)
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:80
double Pow10(int n)
Computes integer powers of 10 in double (10.0^n).
Definition: pow10.h:12
#define RAPIDJSON_PARSE_ERROR(msg, offset)
Definition: reader.h:24
GenericStringStream< UTF8<> > StringStream
Definition: rapidjson.h:477
Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer...
Definition: reader.h:39
ParseFlag
Combination of parseFlags.
Definition: reader.h:38
Concept for reading and writing characters.
void SkipWhitespace(Stream &stream)
Skip the JSON white spaces in a stream.
Definition: reader.h:101
size_t GetErrorOffset() const
Definition: reader.h:258
GenericReader< UTF8<> > Reader
Reader with UTF8 encoding and default allocator.
Definition: reader.h:675
Encoding::Ch Ch
Definition: reader.h:204
Default implementation of Handler.
Definition: reader.h:75
const char * GetParseError() const
Definition: reader.h:257
In-situ(destructive) parsing.
Definition: reader.h:40
Concept for allocating, resizing and freeing memory block.
bool HasParseError() const
Definition: reader.h:256
bool Parse(Stream &stream, Handler &handler)
Parse JSON text.
Definition: reader.h:221
#define RAPIDJSON_PUT(x)
void EndObject(SizeType)
Definition: reader.h:88
void EndArray(SizeType)
Definition: reader.h:90
void String(const Ch *, SizeType, bool)
Definition: reader.h:86