reader.h
Go to the documentation of this file.
1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // http://opensource.org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #ifndef RAPIDJSON_READER_H_
16 #define RAPIDJSON_READER_H_
17 
20 #include "allocators.h"
21 #include "stream.h"
22 #include "encodedstream.h"
23 #include "internal/meta.h"
24 #include "internal/stack.h"
25 #include "internal/strtod.h"
26 #include <limits>
27 
28 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
29 #include <intrin.h>
30 #pragma intrinsic(_BitScanForward)
31 #endif
32 #ifdef RAPIDJSON_SSE42
33 #include <nmmintrin.h>
34 #elif defined(RAPIDJSON_SSE2)
35 #include <emmintrin.h>
36 #elif defined(RAPIDJSON_NEON)
37 #include <arm_neon.h>
38 #endif
39 
40 #ifdef _MSC_VER
41 RAPIDJSON_DIAG_PUSH
42 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
43 RAPIDJSON_DIAG_OFF(4702) // unreachable code
44 #endif
45 
46 #ifdef __clang__
47 RAPIDJSON_DIAG_PUSH
48 RAPIDJSON_DIAG_OFF(old-style-cast)
49 RAPIDJSON_DIAG_OFF(padded)
50 RAPIDJSON_DIAG_OFF(switch-enum)
51 #endif
52 
53 #ifdef __GNUC__
54 RAPIDJSON_DIAG_PUSH
55 RAPIDJSON_DIAG_OFF(effc++)
56 #endif
57 
59 #define RAPIDJSON_NOTHING /* deliberately empty */
60 #ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
61 #define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
62  RAPIDJSON_MULTILINEMACRO_BEGIN \
63  if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
64  RAPIDJSON_MULTILINEMACRO_END
65 #endif
66 #define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
67  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
68 
100 #ifndef RAPIDJSON_PARSE_ERROR_NORETURN
101 #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \
102  RAPIDJSON_MULTILINEMACRO_BEGIN \
103  RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
104  SetParseError(parseErrorCode, offset); \
105  RAPIDJSON_MULTILINEMACRO_END
106 #endif
107 
119 #ifndef RAPIDJSON_PARSE_ERROR
120 #define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \
121  RAPIDJSON_MULTILINEMACRO_BEGIN \
122  RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
123  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
124  RAPIDJSON_MULTILINEMACRO_END
125 #endif
126 
127 #include "error/error.h" // ParseErrorCode, ParseResult
128 
130 
132 // ParseFlag
133 
140 #ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS
141 #define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
142 #endif
143 
145 
147 enum ParseFlag {
159 };
160 
162 // Handler
163 
180 
190 // BaseReaderHandler
192 
194 
197 template<typename Encoding = UTF8<>, typename Derived = void>
198 struct BaseReaderHandler {
199  typedef typename Encoding::Ch Ch;
200 
201  typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;
202 
203  bool Default() { return true; }
204  bool Null() { return static_cast<Override&>(*this).Default(); }
205  bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
206  bool Int(int) { return static_cast<Override&>(*this).Default(); }
207  bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }
208  bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); }
209  bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); }
210  bool Double(double) { return static_cast<Override&>(*this).Default(); }
212  bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
213  bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); }
214  bool StartObject() { return static_cast<Override&>(*this).Default(); }
215  bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
216  bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }
217  bool StartArray() { return static_cast<Override&>(*this).Default(); }
218  bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
219 };
220 
222 // StreamLocalCopy
223 
224 namespace internal {
225 
226 template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
228 
230 template<typename Stream>
231 class StreamLocalCopy<Stream, 1> {
232 public:
233  StreamLocalCopy(Stream& original) : s(original), original_(original) {}
234  ~StreamLocalCopy() { original_ = s; }
235 
236  Stream s;
237 
238 private:
239  StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
240 
241  Stream& original_;
242 };
243 
245 template<typename Stream>
246 class StreamLocalCopy<Stream, 0> {
247 public:
248  StreamLocalCopy(Stream& original) : s(original) {}
249 
250  Stream& s;
251 
252 private:
253  StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
254 };
255 
256 } // namespace internal
257 
259 // SkipWhitespace
260 
262 
265 template<typename InputStream>
266 void SkipWhitespace(InputStream& is) {
268  InputStream& s(copy.s);
269 
270  typename InputStream::Ch c;
271  while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t')
272  s.Take();
273 }
274 
275 inline const char* SkipWhitespace(const char* p, const char* end) {
276  while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
277  ++p;
278  return p;
279 }
280 
281 #ifdef RAPIDJSON_SSE42
282 inline const char *SkipWhitespace_SIMD(const char* p) {
284  // Fast return for single non-whitespace
285  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
286  ++p;
287  else
288  return p;
289 
290  // 16-byte align to the next boundary
291  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
292  while (p != nextAligned)
293  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
294  ++p;
295  else
296  return p;
297 
298  // The rest of string using SIMD
299  static const char whitespace[16] = " \n\r\t";
300  const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
301 
302  for (;; p += 16) {
303  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
304  const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
305  if (r != 16) // some of characters is non-whitespace
306  return p + r;
307  }
308 }
309 
310 inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
311  // Fast return for single non-whitespace
312  if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
313  ++p;
314  else
315  return p;
316 
317  // The middle of string using SIMD
318  static const char whitespace[16] = " \n\r\t";
319  const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
320 
321  for (; p <= end - 16; p += 16) {
322  const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
323  const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
324  if (r != 16) // some of characters is non-whitespace
325  return p + r;
326  }
327 
328  return SkipWhitespace(p, end);
329 }
330 
331 #elif defined(RAPIDJSON_SSE2)
332 
334 inline const char *SkipWhitespace_SIMD(const char* p) {
335  // Fast return for single non-whitespace
336  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
337  ++p;
338  else
339  return p;
340 
341  // 16-byte align to the next boundary
342  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
343  while (p != nextAligned)
344  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
345  ++p;
346  else
347  return p;
348 
349  // The rest of string
350  #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
351  static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
352  #undef C16
353 
354  const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
355  const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
356  const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
357  const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
358 
359  for (;; p += 16) {
360  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
361  __m128i x = _mm_cmpeq_epi8(s, w0);
362  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
363  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
364  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
365  unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
366  if (r != 0) { // some of characters may be non-whitespace
367 #ifdef _MSC_VER // Find the index of first non-whitespace
368  unsigned long offset;
369  _BitScanForward(&offset, r);
370  return p + offset;
371 #else
372  return p + __builtin_ffs(r) - 1;
373 #endif
374  }
375  }
376 }
377 
378 inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
379  // Fast return for single non-whitespace
380  if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
381  ++p;
382  else
383  return p;
384 
385  // The rest of string
386  #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
387  static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
388  #undef C16
389 
390  const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
391  const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
392  const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
393  const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
394 
395  for (; p <= end - 16; p += 16) {
396  const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
397  __m128i x = _mm_cmpeq_epi8(s, w0);
398  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
399  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
400  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
401  unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
402  if (r != 0) { // some of characters may be non-whitespace
403 #ifdef _MSC_VER // Find the index of first non-whitespace
404  unsigned long offset;
405  _BitScanForward(&offset, r);
406  return p + offset;
407 #else
408  return p + __builtin_ffs(r) - 1;
409 #endif
410  }
411  }
412 
413  return SkipWhitespace(p, end);
414 }
415 
416 #elif defined(RAPIDJSON_NEON)
417 
419 inline const char *SkipWhitespace_SIMD(const char* p) {
420  // Fast return for single non-whitespace
421  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
422  ++p;
423  else
424  return p;
425 
426  // 16-byte align to the next boundary
427  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
428  while (p != nextAligned)
429  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
430  ++p;
431  else
432  return p;
433 
434  const uint8x16_t w0 = vmovq_n_u8(' ');
435  const uint8x16_t w1 = vmovq_n_u8('\n');
436  const uint8x16_t w2 = vmovq_n_u8('\r');
437  const uint8x16_t w3 = vmovq_n_u8('\t');
438 
439  for (;; p += 16) {
440  const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
441  uint8x16_t x = vceqq_u8(s, w0);
442  x = vorrq_u8(x, vceqq_u8(s, w1));
443  x = vorrq_u8(x, vceqq_u8(s, w2));
444  x = vorrq_u8(x, vceqq_u8(s, w3));
445 
446  x = vmvnq_u8(x); // Negate
447  x = vrev64q_u8(x); // Rev in 64
448  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
449  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
450 
451  if (low == 0) {
452  if (high != 0) {
453  int lz =__builtin_clzll(high);;
454  return p + 8 + (lz >> 3);
455  }
456  } else {
457  int lz = __builtin_clzll(low);;
458  return p + (lz >> 3);
459  }
460  }
461 }
462 
463 inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
464  // Fast return for single non-whitespace
465  if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
466  ++p;
467  else
468  return p;
469 
470  const uint8x16_t w0 = vmovq_n_u8(' ');
471  const uint8x16_t w1 = vmovq_n_u8('\n');
472  const uint8x16_t w2 = vmovq_n_u8('\r');
473  const uint8x16_t w3 = vmovq_n_u8('\t');
474 
475  for (; p <= end - 16; p += 16) {
476  const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
477  uint8x16_t x = vceqq_u8(s, w0);
478  x = vorrq_u8(x, vceqq_u8(s, w1));
479  x = vorrq_u8(x, vceqq_u8(s, w2));
480  x = vorrq_u8(x, vceqq_u8(s, w3));
481 
482  x = vmvnq_u8(x); // Negate
483  x = vrev64q_u8(x); // Rev in 64
484  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
485  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
486 
487  if (low == 0) {
488  if (high != 0) {
489  int lz = __builtin_clzll(high);
490  return p + 8 + (lz >> 3);
491  }
492  } else {
493  int lz = __builtin_clzll(low);
494  return p + (lz >> 3);
495  }
496  }
497 
498  return SkipWhitespace(p, end);
499 }
500 
501 #endif // RAPIDJSON_NEON
502 
503 #ifdef RAPIDJSON_SIMD
504 template<> inline void SkipWhitespace(InsituStringStream& is) {
506  is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
507 }
508 
510 template<> inline void SkipWhitespace(StringStream& is) {
511  is.src_ = SkipWhitespace_SIMD(is.src_);
512 }
513 
514 template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
515  is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
516 }
517 #endif // RAPIDJSON_SIMD
518 
520 // GenericReader
521 
523 
538 template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
539 class GenericReader {
540 public:
541  typedef typename SourceEncoding::Ch Ch;
542 
544 
547  GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
548 
550 
557  template <unsigned parseFlags, typename InputStream, typename Handler>
558  ParseResult Parse(InputStream& is, Handler& handler) {
559  if (parseFlags & kParseIterativeFlag)
560  return IterativeParse<parseFlags>(is, handler);
561 
562  parseResult_.Clear();
563 
564  ClearStackOnExit scope(*this);
565 
566  SkipWhitespaceAndComments<parseFlags>(is);
567  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
568 
569  if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) {
571  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
572  }
573  else {
574  ParseValue<parseFlags>(is, handler);
575  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
576 
577  if (!(parseFlags & kParseStopWhenDoneFlag)) {
578  SkipWhitespaceAndComments<parseFlags>(is);
579  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
580 
581  if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) {
583  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
584  }
585  }
586  }
587 
588  return parseResult_;
589  }
590 
592 
598  template <typename InputStream, typename Handler>
599  ParseResult Parse(InputStream& is, Handler& handler) {
600  return Parse<kParseDefaultFlags>(is, handler);
601  }
602 
604 
607  parseResult_.Clear();
608  state_ = IterativeParsingStartState;
609  }
610 
612 
618  template <unsigned parseFlags, typename InputStream, typename Handler>
619  bool IterativeParseNext(InputStream& is, Handler& handler) {
620  while (RAPIDJSON_LIKELY(is.Peek() != '\0')) {
621  SkipWhitespaceAndComments<parseFlags>(is);
622 
623  Token t = Tokenize(is.Peek());
624  IterativeParsingState n = Predict(state_, t);
625  IterativeParsingState d = Transit<parseFlags>(state_, t, n, is, handler);
626 
627  // If we've finished or hit an error...
628  if (RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d))) {
629  // Report errors.
630  if (d == IterativeParsingErrorState) {
631  HandleError(state_, is);
632  return false;
633  }
634 
635  // Transition to the finish state.
636  RAPIDJSON_ASSERT(d == IterativeParsingFinishState);
637  state_ = d;
638 
639  // If StopWhenDone is not set...
640  if (!(parseFlags & kParseStopWhenDoneFlag)) {
641  // ... and extra non-whitespace data is found...
642  SkipWhitespaceAndComments<parseFlags>(is);
643  if (is.Peek() != '\0') {
644  // ... this is considered an error.
645  HandleError(state_, is);
646  return false;
647  }
648  }
649 
650  // Success! We are done!
651  return true;
652  }
653 
654  // Transition to the new state.
655  state_ = d;
656 
657  // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now.
658  if (!IsIterativeParsingDelimiterState(n))
659  return true;
660  }
661 
662  // We reached the end of file.
663  stack_.Clear();
664 
665  if (state_ != IterativeParsingFinishState) {
666  HandleError(state_, is);
667  return false;
668  }
669 
670  return true;
671  }
672 
674 
676  RAPIDJSON_FORCEINLINE bool IterativeParseComplete() {
677  return IsIterativeParsingCompleteState(state_);
678  }
679 
681  bool HasParseError() const { return parseResult_.IsError(); }
682 
684  ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
685 
687  size_t GetErrorOffset() const { return parseResult_.Offset(); }
688 
689 protected:
690  void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
691 
692 private:
693  // Prohibit copy constructor & assignment operator.
695  GenericReader& operator=(const GenericReader&);
696 
697  void ClearStack() { stack_.Clear(); }
698 
699  // clear stack on any exit from ParseStream, e.g. due to exception
701  explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
702  ~ClearStackOnExit() { r_.ClearStack(); }
703  private:
706  ClearStackOnExit& operator=(const ClearStackOnExit&);
707  };
708 
709  template<unsigned parseFlags, typename InputStream>
710  void SkipWhitespaceAndComments(InputStream& is) {
711  SkipWhitespace(is);
712 
713  if (parseFlags & kParseCommentsFlag) {
714  while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) {
715  if (Consume(is, '*')) {
716  while (true) {
717  if (RAPIDJSON_UNLIKELY(is.Peek() == '\0'))
719  else if (Consume(is, '*')) {
720  if (Consume(is, '/'))
721  break;
722  }
723  else
724  is.Take();
725  }
726  }
727  else if (RAPIDJSON_LIKELY(Consume(is, '/')))
728  while (is.Peek() != '\0' && is.Take() != '\n') {}
729  else
731 
732  SkipWhitespace(is);
733  }
734  }
735  }
736 
737  // Parse object: { string : value, ... }
738  template<unsigned parseFlags, typename InputStream, typename Handler>
739  void ParseObject(InputStream& is, Handler& handler) {
740  RAPIDJSON_ASSERT(is.Peek() == '{');
741  is.Take(); // Skip '{'
742 
743  if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
745 
746  SkipWhitespaceAndComments<parseFlags>(is);
747  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
748 
749  if (Consume(is, '}')) {
750  if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object
752  return;
753  }
754 
755  for (SizeType memberCount = 0;;) {
756  if (RAPIDJSON_UNLIKELY(is.Peek() != '"'))
758 
759  ParseString<parseFlags>(is, handler, true);
760  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
761 
762  SkipWhitespaceAndComments<parseFlags>(is);
763  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
764 
765  if (RAPIDJSON_UNLIKELY(!Consume(is, ':')))
767 
768  SkipWhitespaceAndComments<parseFlags>(is);
769  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
770 
771  ParseValue<parseFlags>(is, handler);
772  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
773 
774  SkipWhitespaceAndComments<parseFlags>(is);
775  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
776 
777  ++memberCount;
778 
779  switch (is.Peek()) {
780  case ',':
781  is.Take();
782  SkipWhitespaceAndComments<parseFlags>(is);
783  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
784  break;
785  case '}':
786  is.Take();
787  if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
789  return;
790  default:
791  RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy
792  }
793 
794  if (parseFlags & kParseTrailingCommasFlag) {
795  if (is.Peek() == '}') {
796  if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
798  is.Take();
799  return;
800  }
801  }
802  }
803  }
804 
805  // Parse array: [ value, ... ]
806  template<unsigned parseFlags, typename InputStream, typename Handler>
807  void ParseArray(InputStream& is, Handler& handler) {
808  RAPIDJSON_ASSERT(is.Peek() == '[');
809  is.Take(); // Skip '['
810 
811  if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
813 
814  SkipWhitespaceAndComments<parseFlags>(is);
815  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
816 
817  if (Consume(is, ']')) {
818  if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array
820  return;
821  }
822 
823  for (SizeType elementCount = 0;;) {
824  ParseValue<parseFlags>(is, handler);
825  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
826 
827  ++elementCount;
828  SkipWhitespaceAndComments<parseFlags>(is);
829  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
830 
831  if (Consume(is, ',')) {
832  SkipWhitespaceAndComments<parseFlags>(is);
833  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
834  }
835  else if (Consume(is, ']')) {
836  if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
838  return;
839  }
840  else
842 
843  if (parseFlags & kParseTrailingCommasFlag) {
844  if (is.Peek() == ']') {
845  if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
847  is.Take();
848  return;
849  }
850  }
851  }
852  }
853 
854  template<unsigned parseFlags, typename InputStream, typename Handler>
855  void ParseNull(InputStream& is, Handler& handler) {
856  RAPIDJSON_ASSERT(is.Peek() == 'n');
857  is.Take();
858 
859  if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) {
860  if (RAPIDJSON_UNLIKELY(!handler.Null()))
862  }
863  else
865  }
866 
867  template<unsigned parseFlags, typename InputStream, typename Handler>
868  void ParseTrue(InputStream& is, Handler& handler) {
869  RAPIDJSON_ASSERT(is.Peek() == 't');
870  is.Take();
871 
872  if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) {
873  if (RAPIDJSON_UNLIKELY(!handler.Bool(true)))
875  }
876  else
878  }
879 
880  template<unsigned parseFlags, typename InputStream, typename Handler>
881  void ParseFalse(InputStream& is, Handler& handler) {
882  RAPIDJSON_ASSERT(is.Peek() == 'f');
883  is.Take();
884 
885  if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) {
886  if (RAPIDJSON_UNLIKELY(!handler.Bool(false)))
888  }
889  else
891  }
892 
893  template<typename InputStream>
894  RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
895  if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
896  is.Take();
897  return true;
898  }
899  else
900  return false;
901  }
902 
903  // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
904  template<typename InputStream>
905  unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
906  unsigned codepoint = 0;
907  for (int i = 0; i < 4; i++) {
908  Ch c = is.Peek();
909  codepoint <<= 4;
910  codepoint += static_cast<unsigned>(c);
911  if (c >= '0' && c <= '9')
912  codepoint -= '0';
913  else if (c >= 'A' && c <= 'F')
914  codepoint -= 'A' - 10;
915  else if (c >= 'a' && c <= 'f')
916  codepoint -= 'a' - 10;
917  else {
919  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
920  }
921  is.Take();
922  }
923  return codepoint;
924  }
925 
926  template <typename CharType>
927  class StackStream {
928  public:
929  typedef CharType Ch;
930 
931  StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
932  RAPIDJSON_FORCEINLINE void Put(Ch c) {
933  *stack_.template Push<Ch>() = c;
934  ++length_;
935  }
936 
937  RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
938  length_ += count;
939  return stack_.template Push<Ch>(count);
940  }
941 
942  size_t Length() const { return length_; }
943 
944  Ch* Pop() {
945  return stack_.template Pop<Ch>(length_);
946  }
947 
948  private:
949  StackStream(const StackStream&);
950  StackStream& operator=(const StackStream&);
951 
954  };
955 
956  // Parse string and generate String event. Different code paths for kParseInsituFlag.
957  template<unsigned parseFlags, typename InputStream, typename Handler>
958  void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
960  InputStream& s(copy.s);
961 
962  RAPIDJSON_ASSERT(s.Peek() == '\"');
963  s.Take(); // Skip '\"'
964 
965  bool success = false;
966  if (parseFlags & kParseInsituFlag) {
967  typename InputStream::Ch *head = s.PutBegin();
968  ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
969  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
970  size_t length = s.PutEnd(head) - 1;
971  RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
972  const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
973  success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
974  }
975  else {
976  StackStream<typename TargetEncoding::Ch> stackStream(stack_);
977  ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
978  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
979  SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
980  const typename TargetEncoding::Ch* const str = stackStream.Pop();
981  success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
982  }
983  if (RAPIDJSON_UNLIKELY(!success))
985  }
986 
987  // Parse string to an output is
988  // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
989  template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
990  RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
992 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
993  static const char escape[256] = {
994  Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
995  Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
996  0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
997  0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
998  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
999  };
1000 #undef Z16
1001 
1003  for (;;) {
1004  // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
1005  if (!(parseFlags & kParseValidateEncodingFlag))
1006  ScanCopyUnescapedString(is, os);
1007 
1008  Ch c = is.Peek();
1009  if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape
1010  size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset
1011  is.Take();
1012  Ch e = is.Peek();
1013  if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
1014  is.Take();
1015  os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
1016  }
1017  else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode
1018  is.Take();
1019  unsigned codepoint = ParseHex4(is, escapeOffset);
1020  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1021  if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) {
1022  // Handle UTF-16 surrogate pair
1023  if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
1025  unsigned codepoint2 = ParseHex4(is, escapeOffset);
1026  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1027  if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
1029  codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
1030  }
1031  TEncoding::Encode(os, codepoint);
1032  }
1033  else
1035  }
1036  else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote
1037  is.Take();
1038  os.Put('\0'); // null-terminate the string
1039  return;
1040  }
1041  else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
1042  if (c == '\0')
1044  else
1046  }
1047  else {
1048  size_t offset = is.Tell();
1049  if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
1053  }
1054  }
1055  }
1056 
1057  template<typename InputStream, typename OutputStream>
1058  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
1059  // Do nothing for generic version
1060  }
1061 
1062 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
1063  // StringStream -> StackStream<char>
1064  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
1065  const char* p = is.src_;
1066 
1067  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1068  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1069  while (p != nextAligned)
1070  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1071  is.src_ = p;
1072  return;
1073  }
1074  else
1075  os.Put(*p++);
1076 
1077  // The rest of string using SIMD
1078  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1079  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1080  static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
1081  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
1082  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
1083  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
1084 
1085  for (;; p += 16) {
1086  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
1087  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1088  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1089  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
1090  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1091  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1092  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
1093  SizeType length;
1094  #ifdef _MSC_VER // Find the index of first escaped
1095  unsigned long offset;
1096  _BitScanForward(&offset, r);
1097  length = offset;
1098  #else
1099  length = static_cast<SizeType>(__builtin_ffs(r) - 1);
1100  #endif
1101  if (length != 0) {
1102  char* q = reinterpret_cast<char*>(os.Push(length));
1103  for (size_t i = 0; i < length; i++)
1104  q[i] = p[i];
1105 
1106  p += length;
1107  }
1108  break;
1109  }
1110  _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
1111  }
1112 
1113  is.src_ = p;
1114  }
1115 
1116  // InsituStringStream -> InsituStringStream
1117  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
1118  RAPIDJSON_ASSERT(&is == &os);
1119  (void)os;
1120 
1121  if (is.src_ == is.dst_) {
1122  SkipUnescapedString(is);
1123  return;
1124  }
1125 
1126  char* p = is.src_;
1127  char *q = is.dst_;
1128 
1129  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1130  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1131  while (p != nextAligned)
1132  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1133  is.src_ = p;
1134  is.dst_ = q;
1135  return;
1136  }
1137  else
1138  *q++ = *p++;
1139 
1140  // The rest of string using SIMD
1141  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1142  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1143  static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
1144  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
1145  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
1146  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
1147 
1148  for (;; p += 16, q += 16) {
1149  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
1150  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1151  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1152  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
1153  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1154  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1155  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
1156  size_t length;
1157 #ifdef _MSC_VER // Find the index of first escaped
1158  unsigned long offset;
1159  _BitScanForward(&offset, r);
1160  length = offset;
1161 #else
1162  length = static_cast<size_t>(__builtin_ffs(r) - 1);
1163 #endif
1164  for (const char* pend = p + length; p != pend; )
1165  *q++ = *p++;
1166  break;
1167  }
1168  _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s);
1169  }
1170 
1171  is.src_ = p;
1172  is.dst_ = q;
1173  }
1174 
1175  // When read/write pointers are the same for insitu stream, just skip unescaped characters
1176  static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
1177  RAPIDJSON_ASSERT(is.src_ == is.dst_);
1178  char* p = is.src_;
1179 
1180  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1181  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1182  for (; p != nextAligned; p++)
1183  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1184  is.src_ = is.dst_ = p;
1185  return;
1186  }
1187 
1188  // The rest of string using SIMD
1189  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1190  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1191  static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
1192  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
1193  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
1194  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
1195 
1196  for (;; p += 16) {
1197  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
1198  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1199  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1200  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
1201  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1202  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1203  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
1204  size_t length;
1205 #ifdef _MSC_VER // Find the index of first escaped
1206  unsigned long offset;
1207  _BitScanForward(&offset, r);
1208  length = offset;
1209 #else
1210  length = static_cast<size_t>(__builtin_ffs(r) - 1);
1211 #endif
1212  p += length;
1213  break;
1214  }
1215  }
1216 
1217  is.src_ = is.dst_ = p;
1218  }
1219 #elif defined(RAPIDJSON_NEON)
1220  // StringStream -> StackStream<char>
1221  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
1222  const char* p = is.src_;
1223 
1224  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1225  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1226  while (p != nextAligned)
1227  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1228  is.src_ = p;
1229  return;
1230  }
1231  else
1232  os.Put(*p++);
1233 
1234  // The rest of string using SIMD
1235  const uint8x16_t s0 = vmovq_n_u8('"');
1236  const uint8x16_t s1 = vmovq_n_u8('\\');
1237  const uint8x16_t s2 = vmovq_n_u8('\b');
1238  const uint8x16_t s3 = vmovq_n_u8(32);
1239 
1240  for (;; p += 16) {
1241  const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
1242  uint8x16_t x = vceqq_u8(s, s0);
1243  x = vorrq_u8(x, vceqq_u8(s, s1));
1244  x = vorrq_u8(x, vceqq_u8(s, s2));
1245  x = vorrq_u8(x, vcltq_u8(s, s3));
1246 
1247  x = vrev64q_u8(x); // Rev in 64
1248  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
1249  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
1250 
1251  SizeType length = 0;
1252  bool escaped = false;
1253  if (low == 0) {
1254  if (high != 0) {
1255  unsigned lz = (unsigned)__builtin_clzll(high);;
1256  length = 8 + (lz >> 3);
1257  escaped = true;
1258  }
1259  } else {
1260  unsigned lz = (unsigned)__builtin_clzll(low);;
1261  length = lz >> 3;
1262  escaped = true;
1263  }
1264  if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
1265  if (length != 0) {
1266  char* q = reinterpret_cast<char*>(os.Push(length));
1267  for (size_t i = 0; i < length; i++)
1268  q[i] = p[i];
1269 
1270  p += length;
1271  }
1272  break;
1273  }
1274  vst1q_u8(reinterpret_cast<uint8_t *>(os.Push(16)), s);
1275  }
1276 
1277  is.src_ = p;
1278  }
1279 
1280  // InsituStringStream -> InsituStringStream
1281  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
1282  RAPIDJSON_ASSERT(&is == &os);
1283  (void)os;
1284 
1285  if (is.src_ == is.dst_) {
1286  SkipUnescapedString(is);
1287  return;
1288  }
1289 
1290  char* p = is.src_;
1291  char *q = is.dst_;
1292 
1293  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1294  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1295  while (p != nextAligned)
1296  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1297  is.src_ = p;
1298  is.dst_ = q;
1299  return;
1300  }
1301  else
1302  *q++ = *p++;
1303 
1304  // The rest of string using SIMD
1305  const uint8x16_t s0 = vmovq_n_u8('"');
1306  const uint8x16_t s1 = vmovq_n_u8('\\');
1307  const uint8x16_t s2 = vmovq_n_u8('\b');
1308  const uint8x16_t s3 = vmovq_n_u8(32);
1309 
1310  for (;; p += 16, q += 16) {
1311  const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
1312  uint8x16_t x = vceqq_u8(s, s0);
1313  x = vorrq_u8(x, vceqq_u8(s, s1));
1314  x = vorrq_u8(x, vceqq_u8(s, s2));
1315  x = vorrq_u8(x, vcltq_u8(s, s3));
1316 
1317  x = vrev64q_u8(x); // Rev in 64
1318  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
1319  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
1320 
1321  SizeType length = 0;
1322  bool escaped = false;
1323  if (low == 0) {
1324  if (high != 0) {
1325  unsigned lz = (unsigned)__builtin_clzll(high);
1326  length = 8 + (lz >> 3);
1327  escaped = true;
1328  }
1329  } else {
1330  unsigned lz = (unsigned)__builtin_clzll(low);
1331  length = lz >> 3;
1332  escaped = true;
1333  }
1334  if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
1335  for (const char* pend = p + length; p != pend; ) {
1336  *q++ = *p++;
1337  }
1338  break;
1339  }
1340  vst1q_u8(reinterpret_cast<uint8_t *>(q), s);
1341  }
1342 
1343  is.src_ = p;
1344  is.dst_ = q;
1345  }
1346 
1347  // When read/write pointers are the same for insitu stream, just skip unescaped characters
1348  static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
1349  RAPIDJSON_ASSERT(is.src_ == is.dst_);
1350  char* p = is.src_;
1351 
1352  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1353  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1354  for (; p != nextAligned; p++)
1355  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1356  is.src_ = is.dst_ = p;
1357  return;
1358  }
1359 
1360  // The rest of string using SIMD
1361  const uint8x16_t s0 = vmovq_n_u8('"');
1362  const uint8x16_t s1 = vmovq_n_u8('\\');
1363  const uint8x16_t s2 = vmovq_n_u8('\b');
1364  const uint8x16_t s3 = vmovq_n_u8(32);
1365 
1366  for (;; p += 16) {
1367  const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
1368  uint8x16_t x = vceqq_u8(s, s0);
1369  x = vorrq_u8(x, vceqq_u8(s, s1));
1370  x = vorrq_u8(x, vceqq_u8(s, s2));
1371  x = vorrq_u8(x, vcltq_u8(s, s3));
1372 
1373  x = vrev64q_u8(x); // Rev in 64
1374  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
1375  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
1376 
1377  if (low == 0) {
1378  if (high != 0) {
1379  int lz = __builtin_clzll(high);
1380  p += 8 + (lz >> 3);
1381  break;
1382  }
1383  } else {
1384  int lz = __builtin_clzll(low);
1385  p += lz >> 3;
1386  break;
1387  }
1388  }
1389 
1390  is.src_ = is.dst_ = p;
1391  }
1392 #endif // RAPIDJSON_NEON
1393 
1394  template<typename InputStream, bool backup, bool pushOnTake>
1396 
1397  template<typename InputStream>
1398  class NumberStream<InputStream, false, false> {
1399  public:
1400  typedef typename InputStream::Ch Ch;
1401 
1402  NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
1403 
1404  RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
1405  RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
1406  RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
1407  RAPIDJSON_FORCEINLINE void Push(char) {}
1408 
1409  size_t Tell() { return is.Tell(); }
1410  size_t Length() { return 0; }
1411  const char* Pop() { return 0; }
1412 
1413  protected:
1414  NumberStream& operator=(const NumberStream&);
1415 
1416  InputStream& is;
1417  };
1418 
1419  template<typename InputStream>
1420  class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
1422  public:
1423  NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
1424 
1425  RAPIDJSON_FORCEINLINE Ch TakePush() {
1426  stackStream.Put(static_cast<char>(Base::is.Peek()));
1427  return Base::is.Take();
1428  }
1429 
1430  RAPIDJSON_FORCEINLINE void Push(char c) {
1431  stackStream.Put(c);
1432  }
1433 
1434  size_t Length() { return stackStream.Length(); }
1435 
1436  const char* Pop() {
1437  stackStream.Put('\0');
1438  return stackStream.Pop();
1439  }
1440 
1441  private:
1443  };
1444 
1445  template<typename InputStream>
1446  class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
1448  public:
1449  NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
1450 
1451  RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
1452  };
1453 
1454  template<unsigned parseFlags, typename InputStream, typename Handler>
1455  void ParseNumber(InputStream& is, Handler& handler) {
1457  NumberStream<InputStream,
1458  ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
1459  ((parseFlags & kParseInsituFlag) == 0) :
1460  ((parseFlags & kParseFullPrecisionFlag) != 0),
1461  (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
1462  (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
1463 
1464  size_t startOffset = s.Tell();
1465  double d = 0.0;
1466  bool useNanOrInf = false;
1467 
1468  // Parse minus
1469  bool minus = Consume(s, '-');
1470 
1471  // Parse int: zero / ( digit1-9 *DIGIT )
1472  unsigned i = 0;
1473  uint64_t i64 = 0;
1474  bool use64bit = false;
1475  int significandDigit = 0;
1476  if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) {
1477  i = 0;
1478  s.TakePush();
1479  }
1480  else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) {
1481  i = static_cast<unsigned>(s.TakePush() - '0');
1482 
1483  if (minus)
1484  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1485  if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648
1486  if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) {
1487  i64 = i;
1488  use64bit = true;
1489  break;
1490  }
1491  }
1492  i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
1493  significandDigit++;
1494  }
1495  else
1496  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1497  if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295
1498  if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {
1499  i64 = i;
1500  use64bit = true;
1501  break;
1502  }
1503  }
1504  i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
1505  significandDigit++;
1506  }
1507  }
1508  // Parse NaN or Infinity here
1509  else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
1510  if (Consume(s, 'N')) {
1511  if (Consume(s, 'a') && Consume(s, 'N')) {
1512  d = std::numeric_limits<double>::quiet_NaN();
1513  useNanOrInf = true;
1514  }
1515  }
1516  else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) {
1517  if (Consume(s, 'n') && Consume(s, 'f')) {
1518  d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
1519  useNanOrInf = true;
1520 
1521  if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
1522  && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) {
1524  }
1525  }
1526  }
1527 
1528  if (RAPIDJSON_UNLIKELY(!useNanOrInf)) {
1530  }
1531  }
1532  else
1534 
1535  // Parse 64bit int
1536  bool useDouble = false;
1537  if (use64bit) {
1538  if (minus)
1539  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1540  if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
1541  if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
1542  d = static_cast<double>(i64);
1543  useDouble = true;
1544  break;
1545  }
1546  i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1547  significandDigit++;
1548  }
1549  else
1550  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1551  if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615
1552  if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {
1553  d = static_cast<double>(i64);
1554  useDouble = true;
1555  break;
1556  }
1557  i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1558  significandDigit++;
1559  }
1560  }
1561 
1562  // Force double for big integer
1563  if (useDouble) {
1564  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1565  if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0
1567  d = d * 10 + (s.TakePush() - '0');
1568  }
1569  }
1570 
1571  // Parse frac = decimal-point 1*DIGIT
1572  int expFrac = 0;
1573  size_t decimalPosition;
1574  if (Consume(s, '.')) {
1575  decimalPosition = s.Length();
1576 
1577  if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
1579 
1580  if (!useDouble) {
1581 #if RAPIDJSON_64BIT
1582  // Use i64 to store significand in 64-bit architecture
1583  if (!use64bit)
1584  i64 = i;
1585 
1586  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1587  if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
1588  break;
1589  else {
1590  i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1591  --expFrac;
1592  if (i64 != 0)
1593  significandDigit++;
1594  }
1595  }
1596 
1597  d = static_cast<double>(i64);
1598 #else
1599  // Use double to store significand in 32-bit architecture
1600  d = static_cast<double>(use64bit ? i64 : i);
1601 #endif
1602  useDouble = true;
1603  }
1604 
1605  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1606  if (significandDigit < 17) {
1607  d = d * 10.0 + (s.TakePush() - '0');
1608  --expFrac;
1609  if (RAPIDJSON_LIKELY(d > 0.0))
1610  significandDigit++;
1611  }
1612  else
1613  s.TakePush();
1614  }
1615  }
1616  else
1617  decimalPosition = s.Length(); // decimal position at the end of integer.
1618 
1619  // Parse exp = e [ minus / plus ] 1*DIGIT
1620  int exp = 0;
1621  if (Consume(s, 'e') || Consume(s, 'E')) {
1622  if (!useDouble) {
1623  d = static_cast<double>(use64bit ? i64 : i);
1624  useDouble = true;
1625  }
1626 
1627  bool expMinus = false;
1628  if (Consume(s, '+'))
1629  ;
1630  else if (Consume(s, '-'))
1631  expMinus = true;
1632 
1633  if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1634  exp = static_cast<int>(s.Take() - '0');
1635  if (expMinus) {
1636  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1637  exp = exp * 10 + static_cast<int>(s.Take() - '0');
1638  if (exp >= 214748364) { // Issue #313: prevent overflow exponent
1639  while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent
1640  s.Take();
1641  }
1642  }
1643  }
1644  else { // positive exp
1645  int maxExp = 308 - expFrac;
1646  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1647  exp = exp * 10 + static_cast<int>(s.Take() - '0');
1648  if (RAPIDJSON_UNLIKELY(exp > maxExp))
1650  }
1651  }
1652  }
1653  else
1655 
1656  if (expMinus)
1657  exp = -exp;
1658  }
1659 
1660  // Finish parsing, call event according to the type of number.
1661  bool cont = true;
1662 
1663  if (parseFlags & kParseNumbersAsStringsFlag) {
1664  if (parseFlags & kParseInsituFlag) {
1665  s.Pop(); // Pop stack no matter if it will be used or not.
1666  typename InputStream::Ch* head = is.PutBegin();
1667  const size_t length = s.Tell() - startOffset;
1668  RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
1669  // unable to insert the \0 character here, it will erase the comma after this number
1670  const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
1671  cont = handler.RawNumber(str, SizeType(length), false);
1672  }
1673  else {
1674  SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
1675  StringStream srcStream(s.Pop());
1676  StackStream<typename TargetEncoding::Ch> dstStream(stack_);
1677  while (numCharsToCopy--) {
1678  Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);
1679  }
1680  dstStream.Put('\0');
1681  const typename TargetEncoding::Ch* str = dstStream.Pop();
1682  const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;
1683  cont = handler.RawNumber(str, SizeType(length), true);
1684  }
1685  }
1686  else {
1687  size_t length = s.Length();
1688  const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
1689 
1690  if (useDouble) {
1691  int p = exp + expFrac;
1692  if (parseFlags & kParseFullPrecisionFlag)
1693  d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
1694  else
1696 
1697  cont = handler.Double(minus ? -d : d);
1698  }
1699  else if (useNanOrInf) {
1700  cont = handler.Double(d);
1701  }
1702  else {
1703  if (use64bit) {
1704  if (minus)
1705  cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
1706  else
1707  cont = handler.Uint64(i64);
1708  }
1709  else {
1710  if (minus)
1711  cont = handler.Int(static_cast<int32_t>(~i + 1));
1712  else
1713  cont = handler.Uint(i);
1714  }
1715  }
1716  }
1717  if (RAPIDJSON_UNLIKELY(!cont))
1719  }
1720 
1721  // Parse any JSON value
1722  template<unsigned parseFlags, typename InputStream, typename Handler>
1723  void ParseValue(InputStream& is, Handler& handler) {
1724  switch (is.Peek()) {
1725  case 'n': ParseNull <parseFlags>(is, handler); break;
1726  case 't': ParseTrue <parseFlags>(is, handler); break;
1727  case 'f': ParseFalse <parseFlags>(is, handler); break;
1728  case '"': ParseString<parseFlags>(is, handler); break;
1729  case '{': ParseObject<parseFlags>(is, handler); break;
1730  case '[': ParseArray <parseFlags>(is, handler); break;
1731  default :
1732  ParseNumber<parseFlags>(is, handler);
1733  break;
1734 
1735  }
1736  }
1737 
1738  // Iterative Parsing
1739 
1740  // States
1742  IterativeParsingFinishState = 0, // sink states at top
1743  IterativeParsingErrorState, // sink states at top
1745 
1746  // Object states
1751 
1752  // Array states
1756 
1757  // Single value state
1759 
1760  // Delimiter states (at bottom)
1764 
1765  cIterativeParsingStateCount
1766  };
1767 
1768  // Tokens
1769  enum Token {
1770  LeftBracketToken = 0,
1772 
1775 
1778 
1784 
1785  kTokenCount
1786  };
1787 
1788  RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
1789 
1791 #define N NumberToken
1792 #define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
1793  // Maps from ASCII to Token
1794  static const unsigned char tokenMap[256] = {
1795  N16, // 00~0F
1796  N16, // 10~1F
1797  N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
1798  N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
1799  N16, // 40~4F
1800  N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
1801  N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
1802  N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
1803  N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
1804  };
1805 #undef N
1806 #undef N16
1807 
1809  if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
1810  return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
1811  else
1812  return NumberToken;
1813  }
1814 
1815  RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
1816  // current state x one lookahead token -> new state
1817  static const char G[cIterativeParsingStateCount][kTokenCount] = {
1818  // Finish(sink state)
1819  {
1820  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1821  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1822  IterativeParsingErrorState
1823  },
1824  // Error(sink state)
1825  {
1826  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1827  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1828  IterativeParsingErrorState
1829  },
1830  // Start
1831  {
1832  IterativeParsingArrayInitialState, // Left bracket
1833  IterativeParsingErrorState, // Right bracket
1834  IterativeParsingObjectInitialState, // Left curly bracket
1835  IterativeParsingErrorState, // Right curly bracket
1836  IterativeParsingErrorState, // Comma
1837  IterativeParsingErrorState, // Colon
1838  IterativeParsingValueState, // String
1839  IterativeParsingValueState, // False
1840  IterativeParsingValueState, // True
1841  IterativeParsingValueState, // Null
1842  IterativeParsingValueState // Number
1843  },
1844  // ObjectInitial
1845  {
1846  IterativeParsingErrorState, // Left bracket
1847  IterativeParsingErrorState, // Right bracket
1848  IterativeParsingErrorState, // Left curly bracket
1849  IterativeParsingObjectFinishState, // Right curly bracket
1850  IterativeParsingErrorState, // Comma
1851  IterativeParsingErrorState, // Colon
1852  IterativeParsingMemberKeyState, // String
1853  IterativeParsingErrorState, // False
1854  IterativeParsingErrorState, // True
1855  IterativeParsingErrorState, // Null
1856  IterativeParsingErrorState // Number
1857  },
1858  // MemberKey
1859  {
1860  IterativeParsingErrorState, // Left bracket
1861  IterativeParsingErrorState, // Right bracket
1862  IterativeParsingErrorState, // Left curly bracket
1863  IterativeParsingErrorState, // Right curly bracket
1864  IterativeParsingErrorState, // Comma
1865  IterativeParsingKeyValueDelimiterState, // Colon
1866  IterativeParsingErrorState, // String
1867  IterativeParsingErrorState, // False
1868  IterativeParsingErrorState, // True
1869  IterativeParsingErrorState, // Null
1870  IterativeParsingErrorState // Number
1871  },
1872  // MemberValue
1873  {
1874  IterativeParsingErrorState, // Left bracket
1875  IterativeParsingErrorState, // Right bracket
1876  IterativeParsingErrorState, // Left curly bracket
1877  IterativeParsingObjectFinishState, // Right curly bracket
1878  IterativeParsingMemberDelimiterState, // Comma
1879  IterativeParsingErrorState, // Colon
1880  IterativeParsingErrorState, // String
1881  IterativeParsingErrorState, // False
1882  IterativeParsingErrorState, // True
1883  IterativeParsingErrorState, // Null
1884  IterativeParsingErrorState // Number
1885  },
1886  // ObjectFinish(sink state)
1887  {
1888  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1889  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1890  IterativeParsingErrorState
1891  },
1892  // ArrayInitial
1893  {
1894  IterativeParsingArrayInitialState, // Left bracket(push Element state)
1895  IterativeParsingArrayFinishState, // Right bracket
1896  IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
1897  IterativeParsingErrorState, // Right curly bracket
1898  IterativeParsingErrorState, // Comma
1899  IterativeParsingErrorState, // Colon
1900  IterativeParsingElementState, // String
1901  IterativeParsingElementState, // False
1902  IterativeParsingElementState, // True
1903  IterativeParsingElementState, // Null
1904  IterativeParsingElementState // Number
1905  },
1906  // Element
1907  {
1908  IterativeParsingErrorState, // Left bracket
1909  IterativeParsingArrayFinishState, // Right bracket
1910  IterativeParsingErrorState, // Left curly bracket
1911  IterativeParsingErrorState, // Right curly bracket
1912  IterativeParsingElementDelimiterState, // Comma
1913  IterativeParsingErrorState, // Colon
1914  IterativeParsingErrorState, // String
1915  IterativeParsingErrorState, // False
1916  IterativeParsingErrorState, // True
1917  IterativeParsingErrorState, // Null
1918  IterativeParsingErrorState // Number
1919  },
1920  // ArrayFinish(sink state)
1921  {
1922  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1923  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1924  IterativeParsingErrorState
1925  },
1926  // Single Value (sink state)
1927  {
1928  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1929  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1930  IterativeParsingErrorState
1931  },
1932  // ElementDelimiter
1933  {
1934  IterativeParsingArrayInitialState, // Left bracket(push Element state)
1935  IterativeParsingArrayFinishState, // Right bracket
1936  IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
1937  IterativeParsingErrorState, // Right curly bracket
1938  IterativeParsingErrorState, // Comma
1939  IterativeParsingErrorState, // Colon
1940  IterativeParsingElementState, // String
1941  IterativeParsingElementState, // False
1942  IterativeParsingElementState, // True
1943  IterativeParsingElementState, // Null
1944  IterativeParsingElementState // Number
1945  },
1946  // MemberDelimiter
1947  {
1948  IterativeParsingErrorState, // Left bracket
1949  IterativeParsingErrorState, // Right bracket
1950  IterativeParsingErrorState, // Left curly bracket
1951  IterativeParsingObjectFinishState, // Right curly bracket
1952  IterativeParsingErrorState, // Comma
1953  IterativeParsingErrorState, // Colon
1954  IterativeParsingMemberKeyState, // String
1955  IterativeParsingErrorState, // False
1956  IterativeParsingErrorState, // True
1957  IterativeParsingErrorState, // Null
1958  IterativeParsingErrorState // Number
1959  },
1960  // KeyValueDelimiter
1961  {
1962  IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
1963  IterativeParsingErrorState, // Right bracket
1964  IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
1965  IterativeParsingErrorState, // Right curly bracket
1966  IterativeParsingErrorState, // Comma
1967  IterativeParsingErrorState, // Colon
1968  IterativeParsingMemberValueState, // String
1969  IterativeParsingMemberValueState, // False
1970  IterativeParsingMemberValueState, // True
1971  IterativeParsingMemberValueState, // Null
1972  IterativeParsingMemberValueState // Number
1973  },
1974  }; // End of G
1975 
1976  return static_cast<IterativeParsingState>(G[state][token]);
1977  }
1978 
1979  // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
1980  // May return a new state on state pop.
1981  template <unsigned parseFlags, typename InputStream, typename Handler>
1982  RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
1983  (void)token;
1984 
1985  switch (dst) {
1986  case IterativeParsingErrorState:
1987  return dst;
1988 
1989  case IterativeParsingObjectInitialState:
1990  case IterativeParsingArrayInitialState:
1991  {
1992  // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
1993  // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
1994  IterativeParsingState n = src;
1995  if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
1996  n = IterativeParsingElementState;
1997  else if (src == IterativeParsingKeyValueDelimiterState)
1998  n = IterativeParsingMemberValueState;
1999  // Push current state.
2000  *stack_.template Push<SizeType>(1) = n;
2001  // Initialize and push the member/element count.
2002  *stack_.template Push<SizeType>(1) = 0;
2003  // Call handler
2004  bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
2005  // On handler short circuits the parsing.
2006  if (!hr) {
2008  return IterativeParsingErrorState;
2009  }
2010  else {
2011  is.Take();
2012  return dst;
2013  }
2014  }
2015 
2016  case IterativeParsingMemberKeyState:
2017  ParseString<parseFlags>(is, handler, true);
2018  if (HasParseError())
2019  return IterativeParsingErrorState;
2020  else
2021  return dst;
2022 
2023  case IterativeParsingKeyValueDelimiterState:
2024  RAPIDJSON_ASSERT(token == ColonToken);
2025  is.Take();
2026  return dst;
2027 
2028  case IterativeParsingMemberValueState:
2029  // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2030  ParseValue<parseFlags>(is, handler);
2031  if (HasParseError()) {
2032  return IterativeParsingErrorState;
2033  }
2034  return dst;
2035 
2036  case IterativeParsingElementState:
2037  // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2038  ParseValue<parseFlags>(is, handler);
2039  if (HasParseError()) {
2040  return IterativeParsingErrorState;
2041  }
2042  return dst;
2043 
2044  case IterativeParsingMemberDelimiterState:
2045  case IterativeParsingElementDelimiterState:
2046  is.Take();
2047  // Update member/element count.
2048  *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
2049  return dst;
2050 
2051  case IterativeParsingObjectFinishState:
2052  {
2053  // Transit from delimiter is only allowed when trailing commas are enabled
2054  if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {
2056  return IterativeParsingErrorState;
2057  }
2058  // Get member count.
2059  SizeType c = *stack_.template Pop<SizeType>(1);
2060  // If the object is not empty, count the last member.
2061  if (src == IterativeParsingMemberValueState)
2062  ++c;
2063  // Restore the state.
2064  IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
2065  // Transit to Finish state if this is the topmost scope.
2066  if (n == IterativeParsingStartState)
2067  n = IterativeParsingFinishState;
2068  // Call handler
2069  bool hr = handler.EndObject(c);
2070  // On handler short circuits the parsing.
2071  if (!hr) {
2073  return IterativeParsingErrorState;
2074  }
2075  else {
2076  is.Take();
2077  return n;
2078  }
2079  }
2080 
2081  case IterativeParsingArrayFinishState:
2082  {
2083  // Transit from delimiter is only allowed when trailing commas are enabled
2084  if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) {
2086  return IterativeParsingErrorState;
2087  }
2088  // Get element count.
2089  SizeType c = *stack_.template Pop<SizeType>(1);
2090  // If the array is not empty, count the last element.
2091  if (src == IterativeParsingElementState)
2092  ++c;
2093  // Restore the state.
2094  IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
2095  // Transit to Finish state if this is the topmost scope.
2096  if (n == IterativeParsingStartState)
2097  n = IterativeParsingFinishState;
2098  // Call handler
2099  bool hr = handler.EndArray(c);
2100  // On handler short circuits the parsing.
2101  if (!hr) {
2103  return IterativeParsingErrorState;
2104  }
2105  else {
2106  is.Take();
2107  return n;
2108  }
2109  }
2110 
2111  default:
2112  // This branch is for IterativeParsingValueState actually.
2113  // Use `default:` rather than
2114  // `case IterativeParsingValueState:` is for code coverage.
2115 
2116  // The IterativeParsingStartState is not enumerated in this switch-case.
2117  // It is impossible for that case. And it can be caught by following assertion.
2118 
2119  // The IterativeParsingFinishState is not enumerated in this switch-case either.
2120  // It is a "derivative" state which cannot triggered from Predict() directly.
2121  // Therefore it cannot happen here. And it can be caught by following assertion.
2122  RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
2123 
2124  // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2125  ParseValue<parseFlags>(is, handler);
2126  if (HasParseError()) {
2127  return IterativeParsingErrorState;
2128  }
2129  return IterativeParsingFinishState;
2130  }
2131  }
2132 
2133  template <typename InputStream>
2134  void HandleError(IterativeParsingState src, InputStream& is) {
2135  if (HasParseError()) {
2136  // Error flag has been set.
2137  return;
2138  }
2139 
2140  switch (src) {
2141  case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
2142  case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
2143  case IterativeParsingObjectInitialState:
2144  case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return;
2145  case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return;
2146  case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return;
2147  case IterativeParsingKeyValueDelimiterState:
2148  case IterativeParsingArrayInitialState:
2149  case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;
2150  default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
2151  }
2152  }
2153 
2155  return s >= IterativeParsingElementDelimiterState;
2156  }
2157 
2159  return s <= IterativeParsingErrorState;
2160  }
2161 
2162  template <unsigned parseFlags, typename InputStream, typename Handler>
2163  ParseResult IterativeParse(InputStream& is, Handler& handler) {
2164  parseResult_.Clear();
2165  ClearStackOnExit scope(*this);
2166  IterativeParsingState state = IterativeParsingStartState;
2167 
2168  SkipWhitespaceAndComments<parseFlags>(is);
2169  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
2170  while (is.Peek() != '\0') {
2171  Token t = Tokenize(is.Peek());
2172  IterativeParsingState n = Predict(state, t);
2173  IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
2174 
2175  if (d == IterativeParsingErrorState) {
2176  HandleError(state, is);
2177  break;
2178  }
2179 
2180  state = d;
2181 
2182  // Do not further consume streams if a root JSON has been parsed.
2183  if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
2184  break;
2185 
2186  SkipWhitespaceAndComments<parseFlags>(is);
2187  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
2188  }
2189 
2190  // Handle the end of file.
2191  if (state != IterativeParsingFinishState)
2192  HandleError(state, is);
2193 
2194  return parseResult_;
2195  }
2196 
2197  static const size_t kDefaultStackCapacity = 256;
2201 }; // class GenericReader
2202 
2205 
2207 
2208 #ifdef __clang__
2209 RAPIDJSON_DIAG_POP
2210 #endif
2211 
2212 
2213 #ifdef __GNUC__
2214 RAPIDJSON_DIAG_POP
2215 #endif
2216 
2217 #ifdef _MSC_VER
2218 RAPIDJSON_DIAG_POP
2219 #endif
2220 
2221 #endif // RAPIDJSON_READER_H_
bool Default()
Definition: reader.h:203
bool RawNumber(const Ch *str, SizeType len, bool copy)
enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) ...
Definition: reader.h:212
d
RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream &is, OutputStream &os)
Definition: reader.h:990
StreamLocalCopy(Stream &original)
Definition: reader.h:233
bool StartArray()
Definition: reader.h:217
Encoding conversion.
Definition: encodings.h:658
void HandleError(IterativeParsingState src, InputStream &is)
Definition: reader.h:2134
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text.
Definition: reader.h:558
void ClearStack()
Definition: reader.h:697
Invalid value.
Definition: error.h:70
Encoding::Ch Ch
Definition: reader.h:199
double StrtodFullPrecision(double d, int p, const char *decimals, size_t length, size_t decimalPosition, int exp)
Definition: strtod.h:224
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:389
Iterative(constant complexity in terms of function call stack size) parsing.
Definition: reader.h:151
Represents an in-memory input byte stream.
Definition: memorystream.h:40
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:411
Parsing was terminated.
Definition: error.h:88
Missing a comma or &#39;}&#39; after an object member.
Definition: error.h:74
ParseResult parseResult_
Definition: reader.h:2199
#define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
Definition: rapidjson.h:294
bool Int64(int64_t)
Definition: reader.h:208
Default implementation of Handler.
Definition: fwd.h:85
RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream &is, Handler &handler)
Definition: reader.h:1982
NumberStream(GenericReader &reader, InputStream &is)
Definition: reader.h:1423
Read-only string stream.
Definition: fwd.h:47
StackStream(internal::Stack< StackAllocator > &stack)
Definition: reader.h:931
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:124
GenericReader< UTF8<>, UTF8<> > Reader
Reader with UTF8 encoding and default allocator.
Definition: reader.h:2204
The document is empty.
Definition: error.h:67
Missing a comma or &#39;]&#39; after an array element.
Definition: error.h:76
RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token)
Definition: reader.h:1815
RAPIDJSON_FORCEINLINE bool IterativeParseComplete()
Check if token-by-token parsing JSON text is complete.
Definition: reader.h:676
XmlRpcServer s
bool Uint64(uint64_t)
Definition: reader.h:209
bool EndObject(SizeType)
Definition: reader.h:216
bool Uint(unsigned)
Definition: reader.h:207
bool String(const Ch *, SizeType, bool)
Definition: reader.h:213
ParseErrorCode GetParseErrorCode() const
Get the ParseErrorCode of last parsing.
Definition: reader.h:684
RAPIDJSON_FORCEINLINE Token Tokenize(Ch c)
Definition: reader.h:1788
const Ch * src_
Current read position.
Definition: stream.h:124
No flags are set.
Definition: reader.h:148
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text (with kParseDefaultFlags)
Definition: reader.h:599
bool EndArray(SizeType)
Definition: reader.h:218
bool StartObject()
Definition: reader.h:214
void SetParseError(ParseErrorCode code, size_t offset)
Definition: reader.h:690
void ParseString(InputStream &is, Handler &handler, bool isKey=false)
Definition: reader.h:958
RAPIDJSON_FORCEINLINE void Put(Ch c)
Definition: reader.h:932
Missing a name for object member.
Definition: error.h:72
Result of parsing (wraps ParseErrorCode)
Definition: error.h:106
Allow trailing commas at the end of objects and arrays.
Definition: reader.h:156
void ParseValue(InputStream &is, Handler &handler)
Definition: reader.h:1723
void ParseArray(InputStream &is, Handler &handler)
Definition: reader.h:807
NumberStream< InputStream, false, false > Base
Definition: reader.h:1421
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:121
bool Int(int)
Definition: reader.h:206
internal::SelectIf< internal::IsSame< Derived, void >, BaseReaderHandler, Derived >::Type Override
Definition: reader.h:201
#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset)
Macro to indicate a parse error.
Definition: reader.h:101
Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
Definition: reader.h:157
size_t Length() const
Definition: reader.h:942
internal::Stack< StackAllocator > & stack_
Definition: reader.h:952
Number too big to be stored in double.
Definition: error.h:84
Parse all numbers (ints/doubles) as strings.
Definition: reader.h:155
NumberStream(GenericReader &reader, InputStream &s)
Definition: reader.h:1402
After parsing a complete JSON root from stream, stop further processing the rest of stream...
Definition: reader.h:152
SourceEncoding::Ch Ch
SourceEncoding character type.
Definition: reader.h:541
unsigned ParseHex4(InputStream &is, size_t escapeOffset)
Definition: reader.h:905
Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS. ...
Definition: reader.h:158
Parse number in full precision (but slower).
Definition: reader.h:153
UTF-8 encoding.
Definition: encodings.h:96
void ParseTrue(InputStream &is, Handler &handler)
Definition: reader.h:868
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
Definition: fwd.h:88
bool HasParseError() const
Whether a parse error has occured in the last parsing.
Definition: reader.h:681
double StrtodNormalPrecision(double d, int p)
Definition: strtod.h:35
bool Key(const Ch *str, SizeType len, bool copy)
Definition: reader.h:215
RAPIDJSON_FORCEINLINE void * Push(SizeType count)
Definition: reader.h:937
RAPIDJSON_FORCEINLINE Ch Peek() const
Definition: reader.h:1404
ParseFlag
Combination of parseFlags.
Definition: reader.h:147
ParseErrorCode
Error code of parsing.
Definition: error.h:64
void SkipWhitespaceAndComments(InputStream &is)
Definition: reader.h:710
#define RAPIDJSON_PARSE_DEFAULT_FLAGS
Definition: reader.h:141
unsigned __int64 uint64_t
Definition: stdint.h:136
IterativeParsingState state_
Definition: reader.h:2200
RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s)
Definition: reader.h:2158
Input byte stream wrapper with a statically bound encoding.
Definition: encodedstream.h:39
bool IterativeParseNext(InputStream &is, Handler &handler)
Parse one token from JSON text.
Definition: reader.h:619
Miss exponent in number.
Definition: error.h:86
void ParseFalse(InputStream &is, Handler &handler)
Definition: reader.h:881
Invalid escape character in string.
Definition: error.h:80
Invalid encoding in string.
Definition: error.h:82
void ParseNumber(InputStream &is, Handler &handler)
Definition: reader.h:1455
bool Bool(bool)
Definition: reader.h:205
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:468
RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s)
Definition: reader.h:2154
RAPIDJSON_FORCEINLINE void Push(char c)
Definition: reader.h:1430
void SkipWhitespace(InputStream &is)
Skip the JSON white spaces in a stream.
Definition: reader.h:266
#define Z16
void ParseObject(InputStream &is, Handler &handler)
Definition: reader.h:739
bool Double(double)
Definition: reader.h:210
Validate encoding of JSON strings.
Definition: reader.h:150
signed __int64 int64_t
Definition: stdint.h:135
Miss fraction part in number.
Definition: error.h:85
size_t GetErrorOffset() const
Get the position of last parsing error in input, 0 otherwise.
Definition: reader.h:687
internal::Stack< StackAllocator > stack_
A stack for storing decoded string temporarily during non-destructive parsing.
Definition: reader.h:2198
Incorrect hex digit after \u escape in string.
Definition: error.h:78
#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset)
(Internal) macro to indicate and handle a parse error.
Definition: reader.h:120
void Clear()
Reset error code.
Definition: error.h:134
static RAPIDJSON_FORCEINLINE bool Consume(InputStream &is, typename InputStream::Ch expect)
Definition: reader.h:894
Unspecific syntax error.
Definition: error.h:89
void IterativeParseInit()
Initialize JSON text token-by-token parsing.
Definition: reader.h:606
The surrogate pair in string is invalid.
Definition: error.h:79
void ParseNull(InputStream &is, Handler &handler)
Definition: reader.h:855
Missing a colon after a name of object member.
Definition: error.h:73
ParseResult IterativeParse(InputStream &is, Handler &handler)
Definition: reader.h:2163
NumberStream< InputStream, true, false > Base
Definition: reader.h:1447
Type
Type of JSON value.
Definition: rapidjson.h:616
StreamLocalCopy(Stream &original)
Definition: reader.h:248
GenericReader(StackAllocator *stackAllocator=0, size_t stackCapacity=kDefaultStackCapacity)
Constructor.
Definition: reader.h:547
ClearStackOnExit(GenericReader &r)
Definition: reader.h:701
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:481
Missing a closing quotation mark in string.
Definition: error.h:81
static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream &, OutputStream &)
Definition: reader.h:1058
NumberStream(GenericReader &reader, InputStream &is)
Definition: reader.h:1449
The document root must not follow by other values.
Definition: error.h:68
In-situ(destructive) parsing.
Definition: reader.h:149
Allow one-line (//) and multi-line (/**/) comments.
Definition: reader.h:154


choreo_rapidjson
Author(s):
autogenerated on Thu Jul 18 2019 03:59:09