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 #if 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 #if __clang__
41 RAPIDJSON_DIAG_PUSH
42 RAPIDJSON_DIAG_OFF(old - style - cast)
43 RAPIDJSON_DIAG_OFF(padded)
44 RAPIDJSON_DIAG_OFF(switch - enum)
45 #elif defined(_MSC_VER)
46 RAPIDJSON_DIAG_PUSH
47 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
48 RAPIDJSON_DIAG_OFF(4702) // unreachable code
49 #endif
50 
51 #if __GNUC__
52 RAPIDJSON_DIAG_PUSH
53 RAPIDJSON_DIAG_OFF(effc++)
54 #endif
55 
57 #define RAPIDJSON_NOTHING /* deliberately empty */
58 #ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
59 #define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
60  RAPIDJSON_MULTILINEMACRO_BEGIN \
61  if (RAPIDJSON_UNLIKELY(HasParseError())) \
62  { \
63  return value; \
64  } \
65  RAPIDJSON_MULTILINEMACRO_END
66 #endif
67 #define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID 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 
148 {
162 };
164 
166 // Handler
167 
184 
194 // BaseReaderHandler
196 
198 
201 template <typename Encoding = UTF8<>, typename Derived = void>
202 struct BaseReaderHandler
203 {
204  typedef typename Encoding::Ch Ch;
205 
206  typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;
207 
208  bool Default()
209  {
210  return true;
211  }
212  bool Null()
213  {
214  return static_cast<Override&>(*this).Default();
215  }
216  bool Bool(bool)
217  {
218  return static_cast<Override&>(*this).Default();
219  }
220  bool Int(int)
221  {
222  return static_cast<Override&>(*this).Default();
223  }
224  bool Uint(unsigned)
225  {
226  return static_cast<Override&>(*this).Default();
227  }
229  {
230  return static_cast<Override&>(*this).Default();
231  }
233  {
234  return static_cast<Override&>(*this).Default();
235  }
236  bool Double(double)
237  {
238  return static_cast<Override&>(*this).Default();
239  }
241  bool RawNumber(const Ch* str, SizeType len, bool copy)
242  {
243  return static_cast<Override&>(*this).String(str, len, copy);
244  }
245  bool String(const Ch*, SizeType, bool)
246  {
247  return static_cast<Override&>(*this).Default();
248  }
249  bool StartObject()
250  {
251  return static_cast<Override&>(*this).Default();
252  }
253  bool Key(const Ch* str, SizeType len, bool copy)
254  {
255  return static_cast<Override&>(*this).String(str, len, copy);
256  }
258  {
259  return static_cast<Override&>(*this).Default();
260  }
261  bool StartArray()
262  {
263  return static_cast<Override&>(*this).Default();
264  }
266  {
267  return static_cast<Override&>(*this).Default();
268  }
269 };
270 
272 // StreamLocalCopy
273 
274 namespace internal
275 {
276 template <typename Stream, int = StreamTraits<Stream>::copyOptimization>
278 
280 template <typename Stream>
281 class StreamLocalCopy<Stream, 1>
282 {
283 public:
284  StreamLocalCopy(Stream& original) : s(original), original_(original)
285  {
286  }
288  {
289  original_ = s;
290  }
291 
292  Stream s;
293 
294 private:
295  StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
296 
297  Stream& original_;
298 };
299 
301 template <typename Stream>
302 class StreamLocalCopy<Stream, 0>
303 {
304 public:
305  StreamLocalCopy(Stream& original) : s(original)
306  {
307  }
308 
309  Stream& s;
310 
311 private:
312  StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
313 };
314 
315 } // namespace internal
316 
318 // SkipWhitespace
319 
321 
324 template <typename InputStream>
325 void SkipWhitespace(InputStream& is)
326 {
328  InputStream& s(copy.s);
329 
330  typename InputStream::Ch c;
331  while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t')
332  s.Take();
333 }
334 
335 inline const char* SkipWhitespace(const char* p, const char* end)
336 {
337  while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
338  ++p;
339  return p;
340 }
341 
342 #if RAPIDJSON_SSE42
343 inline const char* SkipWhitespace_SIMD(const char* p)
345 {
346  // Fast return for single non-whitespace
347  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
348  ++p;
349  else
350  return p;
351 
352  // 16-byte align to the next boundary
353  const char* nextAligned =
354  reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
355  while (p != nextAligned)
356  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
357  ++p;
358  else
359  return p;
360 
361  // The rest of string using SIMD
362  static const char whitespace[16] = " \n\r\t";
363  const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespace[0]));
364 
365  for (;; p += 16)
366  {
367  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
368  const int r =
369  _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
370  if (r != 16) // some of characters is non-whitespace
371  return p + r;
372  }
373 }
374 
375 inline const char* SkipWhitespace_SIMD(const char* p, const char* end)
376 {
377  // Fast return for single non-whitespace
378  if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
379  ++p;
380  else
381  return p;
382 
383  // The middle of string using SIMD
384  static const char whitespace[16] = " \n\r\t";
385  const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespace[0]));
386 
387  for (; p <= end - 16; p += 16)
388  {
389  const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p));
390  const int r =
391  _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
392  if (r != 16) // some of characters is non-whitespace
393  return p + r;
394  }
395 
396  return SkipWhitespace(p, end);
397 }
398 
399 #elif defined(RAPIDJSON_SSE2)
400 
402 inline const char* SkipWhitespace_SIMD(const char* p)
403 {
404  // Fast return for single non-whitespace
405  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
406  ++p;
407  else
408  return p;
409 
410  // 16-byte align to the next boundary
411  const char* nextAligned =
412  reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
413  while (p != nextAligned)
414  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
415  ++p;
416  else
417  return p;
418 
419 // The rest of string
420 #define C16(c) \
421  { \
422  c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c \
423  }
424  static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
425 #undef C16
426 
427  const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[0][0]));
428  const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[1][0]));
429  const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[2][0]));
430  const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[3][0]));
431 
432  for (;; p += 16)
433  {
434  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
435  __m128i x = _mm_cmpeq_epi8(s, w0);
436  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
437  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
438  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
439  unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
440  if (r != 0)
441  { // some of characters may be non-whitespace
442 #if _MSC_VER // Find the index of first non-whitespace
443  unsigned long offset;
444  _BitScanForward(&offset, r);
445  return p + offset;
446 #else
447  return p + __builtin_ffs(r) - 1;
448 #endif
449  }
450  }
451 }
452 
453 inline const char* SkipWhitespace_SIMD(const char* p, const char* end)
454 {
455  // Fast return for single non-whitespace
456  if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
457  ++p;
458  else
459  return p;
460 
461 // The rest of string
462 #define C16(c) \
463  { \
464  c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c \
465  }
466  static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
467 #undef C16
468 
469  const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[0][0]));
470  const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[1][0]));
471  const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[2][0]));
472  const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[3][0]));
473 
474  for (; p <= end - 16; p += 16)
475  {
476  const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p));
477  __m128i x = _mm_cmpeq_epi8(s, w0);
478  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
479  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
480  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
481  unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
482  if (r != 0)
483  { // some of characters may be non-whitespace
484 #if _MSC_VER // Find the index of first non-whitespace
485  unsigned long offset;
486  _BitScanForward(&offset, r);
487  return p + offset;
488 #else
489  return p + __builtin_ffs(r) - 1;
490 #endif
491  }
492  }
493 
494  return SkipWhitespace(p, end);
495 }
496 
497 #elif defined(RAPIDJSON_NEON)
498 
500 inline const char* SkipWhitespace_SIMD(const char* p)
501 {
502  // Fast return for single non-whitespace
503  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
504  ++p;
505  else
506  return p;
507 
508  // 16-byte align to the next boundary
509  const char* nextAligned =
510  reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
511  while (p != nextAligned)
512  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
513  ++p;
514  else
515  return p;
516 
517  const uint8x16_t w0 = vmovq_n_u8(' ');
518  const uint8x16_t w1 = vmovq_n_u8('\n');
519  const uint8x16_t w2 = vmovq_n_u8('\r');
520  const uint8x16_t w3 = vmovq_n_u8('\t');
521 
522  for (;; p += 16)
523  {
524  const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p));
525  uint8x16_t x = vceqq_u8(s, w0);
526  x = vorrq_u8(x, vceqq_u8(s, w1));
527  x = vorrq_u8(x, vceqq_u8(s, w2));
528  x = vorrq_u8(x, vceqq_u8(s, w3));
529 
530  x = vmvnq_u8(x); // Negate
531  x = vrev64q_u8(x); // Rev in 64
532  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
533  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
534 
535  if (low == 0)
536  {
537  if (high != 0)
538  {
539  int lz = __builtin_clzll(high);
540  ;
541  return p + 8 + (lz >> 3);
542  }
543  }
544  else
545  {
546  int lz = __builtin_clzll(low);
547  ;
548  return p + (lz >> 3);
549  }
550  }
551 }
552 
553 inline const char* SkipWhitespace_SIMD(const char* p, const char* end)
554 {
555  // Fast return for single non-whitespace
556  if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
557  ++p;
558  else
559  return p;
560 
561  const uint8x16_t w0 = vmovq_n_u8(' ');
562  const uint8x16_t w1 = vmovq_n_u8('\n');
563  const uint8x16_t w2 = vmovq_n_u8('\r');
564  const uint8x16_t w3 = vmovq_n_u8('\t');
565 
566  for (; p <= end - 16; p += 16)
567  {
568  const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p));
569  uint8x16_t x = vceqq_u8(s, w0);
570  x = vorrq_u8(x, vceqq_u8(s, w1));
571  x = vorrq_u8(x, vceqq_u8(s, w2));
572  x = vorrq_u8(x, vceqq_u8(s, w3));
573 
574  x = vmvnq_u8(x); // Negate
575  x = vrev64q_u8(x); // Rev in 64
576  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
577  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
578 
579  if (low == 0)
580  {
581  if (high != 0)
582  {
583  int lz = __builtin_clzll(high);
584  return p + 8 + (lz >> 3);
585  }
586  }
587  else
588  {
589  int lz = __builtin_clzll(low);
590  return p + (lz >> 3);
591  }
592  }
593 
594  return SkipWhitespace(p, end);
595 }
596 
597 #endif // RAPIDJSON_NEON
598 
599 #if RAPIDJSON_SIMD
600 template <>
602 inline void SkipWhitespace(InsituStringStream& is)
603 {
604  is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
605 }
606 
608 template <>
609 inline void SkipWhitespace(StringStream& is)
610 {
611  is.src_ = SkipWhitespace_SIMD(is.src_);
612 }
613 
614 template <>
616 {
617  is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
618 }
619 #endif // RAPIDJSON_SIMD
620 
622 // GenericReader
623 
625 
640 template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
641 class GenericReader
642 {
643 public:
644  typedef typename SourceEncoding::Ch Ch;
645 
647 
651  GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity)
652  : stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState)
653  {
654  }
655 
657 
664  template <unsigned parseFlags, typename InputStream, typename Handler>
665  ParseResult Parse(InputStream& is, Handler& handler)
666  {
667  if (parseFlags & kParseIterativeFlag)
668  return IterativeParse<parseFlags>(is, handler);
669 
670  parseResult_.Clear();
671 
672  ClearStackOnExit scope(*this);
673 
674  SkipWhitespaceAndComments<parseFlags>(is);
675  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
676 
677  if (RAPIDJSON_UNLIKELY(is.Peek() == '\0'))
678  {
680  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
681  }
682  else
683  {
684  ParseValue<parseFlags>(is, handler);
685  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
686 
687  if (!(parseFlags & kParseStopWhenDoneFlag))
688  {
689  SkipWhitespaceAndComments<parseFlags>(is);
690  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
691 
692  if (RAPIDJSON_UNLIKELY(is.Peek() != '\0'))
693  {
695  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
696  }
697  }
698  }
699 
700  return parseResult_;
701  }
702 
704 
710  template <typename InputStream, typename Handler>
711  ParseResult Parse(InputStream& is, Handler& handler)
712  {
713  return Parse<kParseDefaultFlags>(is, handler);
714  }
715 
717 
720  {
721  parseResult_.Clear();
722  state_ = IterativeParsingStartState;
723  }
724 
726 
732  template <unsigned parseFlags, typename InputStream, typename Handler>
733  bool IterativeParseNext(InputStream& is, Handler& handler)
734  {
735  while (RAPIDJSON_LIKELY(is.Peek() != '\0'))
736  {
737  SkipWhitespaceAndComments<parseFlags>(is);
738 
739  Token t = Tokenize(is.Peek());
740  IterativeParsingState n = Predict(state_, t);
741  IterativeParsingState d = Transit<parseFlags>(state_, t, n, is, handler);
742 
743  // If we've finished or hit an error...
744  if (RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d)))
745  {
746  // Report errors.
747  if (d == IterativeParsingErrorState)
748  {
749  HandleError(state_, is);
750  return false;
751  }
752 
753  // Transition to the finish state.
754  RAPIDJSON_ASSERT(d == IterativeParsingFinishState);
755  state_ = d;
756 
757  // If StopWhenDone is not set...
758  if (!(parseFlags & kParseStopWhenDoneFlag))
759  {
760  // ... and extra non-whitespace data is found...
761  SkipWhitespaceAndComments<parseFlags>(is);
762  if (is.Peek() != '\0')
763  {
764  // ... this is considered an error.
765  HandleError(state_, is);
766  return false;
767  }
768  }
769 
770  // Success! We are done!
771  return true;
772  }
773 
774  // Transition to the new state.
775  state_ = d;
776 
777  // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now.
778  if (!IsIterativeParsingDelimiterState(n))
779  return true;
780  }
781 
782  // We reached the end of file.
783  stack_.Clear();
784 
785  if (state_ != IterativeParsingFinishState)
786  {
787  HandleError(state_, is);
788  return false;
789  }
790 
791  return true;
792  }
793 
795 
797  RAPIDJSON_FORCEINLINE bool IterativeParseComplete() const
798  {
799  return IsIterativeParsingCompleteState(state_);
800  }
801 
803  bool HasParseError() const
804  {
805  return parseResult_.IsError();
806  }
807 
810  {
811  return parseResult_.Code();
812  }
813 
815  size_t GetErrorOffset() const
816  {
817  return parseResult_.Offset();
818  }
819 
820 protected:
821  void SetParseError(ParseErrorCode code, size_t offset)
822  {
823  parseResult_.Set(code, offset);
824  }
825 
826 private:
827  // Prohibit copy constructor & assignment operator.
829  GenericReader& operator=(const GenericReader&);
830 
831  void ClearStack()
832  {
833  stack_.Clear();
834  }
835 
836  // clear stack on any exit from ParseStream, e.g. due to exception
838  {
839  explicit ClearStackOnExit(GenericReader& r) : r_(r)
840  {
841  }
843  {
844  r_.ClearStack();
845  }
846 
847  private:
850  ClearStackOnExit& operator=(const ClearStackOnExit&);
851  };
852 
853  template <unsigned parseFlags, typename InputStream>
854  void SkipWhitespaceAndComments(InputStream& is)
855  {
856  SkipWhitespace(is);
857 
858  if (parseFlags & kParseCommentsFlag)
859  {
860  while (RAPIDJSON_UNLIKELY(Consume(is, '/')))
861  {
862  if (Consume(is, '*'))
863  {
864  while (true)
865  {
866  if (RAPIDJSON_UNLIKELY(is.Peek() == '\0'))
868  else if (Consume(is, '*'))
869  {
870  if (Consume(is, '/'))
871  break;
872  }
873  else
874  is.Take();
875  }
876  }
877  else if (RAPIDJSON_LIKELY(Consume(is, '/')))
878  while (is.Peek() != '\0' && is.Take() != '\n')
879  {
880  }
881  else
883 
884  SkipWhitespace(is);
885  }
886  }
887  }
888 
889  // Parse object: { string : value, ... }
890  template <unsigned parseFlags, typename InputStream, typename Handler>
891  void ParseObject(InputStream& is, Handler& handler)
892  {
893  RAPIDJSON_ASSERT(is.Peek() == '{');
894  is.Take(); // Skip '{'
895 
896  if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
898 
899  SkipWhitespaceAndComments<parseFlags>(is);
900  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
901 
902  if (Consume(is, '}'))
903  {
904  if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object
906  return;
907  }
908 
909  for (SizeType memberCount = 0;;)
910  {
911  if (RAPIDJSON_UNLIKELY(is.Peek() != '"'))
913 
914  ParseString<parseFlags>(is, handler, true);
915  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
916 
917  SkipWhitespaceAndComments<parseFlags>(is);
918  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
919 
920  if (RAPIDJSON_UNLIKELY(!Consume(is, ':')))
922 
923  SkipWhitespaceAndComments<parseFlags>(is);
924  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
925 
926  ParseValue<parseFlags>(is, handler);
927  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
928 
929  SkipWhitespaceAndComments<parseFlags>(is);
930  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
931 
932  ++memberCount;
933 
934  switch (is.Peek())
935  {
936  case ',':
937  is.Take();
938  SkipWhitespaceAndComments<parseFlags>(is);
939  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
940  break;
941  case '}':
942  is.Take();
943  if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
945  return;
946  default:
948  break; // This useless break is only for making warning and coverage happy
949  }
950 
951  if (parseFlags & kParseTrailingCommasFlag)
952  {
953  if (is.Peek() == '}')
954  {
955  if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
957  is.Take();
958  return;
959  }
960  }
961  }
962  }
963 
964  // Parse array: [ value, ... ]
965  template <unsigned parseFlags, typename InputStream, typename Handler>
966  void ParseArray(InputStream& is, Handler& handler)
967  {
968  RAPIDJSON_ASSERT(is.Peek() == '[');
969  is.Take(); // Skip '['
970 
971  if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
973 
974  SkipWhitespaceAndComments<parseFlags>(is);
975  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
976 
977  if (Consume(is, ']'))
978  {
979  if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array
981  return;
982  }
983 
984  for (SizeType elementCount = 0;;)
985  {
986  ParseValue<parseFlags>(is, handler);
987  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
988 
989  ++elementCount;
990  SkipWhitespaceAndComments<parseFlags>(is);
991  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
992 
993  if (Consume(is, ','))
994  {
995  SkipWhitespaceAndComments<parseFlags>(is);
996  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
997  }
998  else if (Consume(is, ']'))
999  {
1000  if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
1002  return;
1003  }
1004  else
1006 
1007  if (parseFlags & kParseTrailingCommasFlag)
1008  {
1009  if (is.Peek() == ']')
1010  {
1011  if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
1013  is.Take();
1014  return;
1015  }
1016  }
1017  }
1018  }
1019 
1020  template <unsigned parseFlags, typename InputStream, typename Handler>
1021  void ParseNull(InputStream& is, Handler& handler)
1022  {
1023  RAPIDJSON_ASSERT(is.Peek() == 'n');
1024  is.Take();
1025 
1026  if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l')))
1027  {
1028  if (RAPIDJSON_UNLIKELY(!handler.Null()))
1030  }
1031  else
1033  }
1034 
1035  template <unsigned parseFlags, typename InputStream, typename Handler>
1036  void ParseTrue(InputStream& is, Handler& handler)
1037  {
1038  RAPIDJSON_ASSERT(is.Peek() == 't');
1039  is.Take();
1040 
1041  if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e')))
1042  {
1043  if (RAPIDJSON_UNLIKELY(!handler.Bool(true)))
1045  }
1046  else
1048  }
1049 
1050  template <unsigned parseFlags, typename InputStream, typename Handler>
1051  void ParseFalse(InputStream& is, Handler& handler)
1052  {
1053  RAPIDJSON_ASSERT(is.Peek() == 'f');
1054  is.Take();
1055 
1056  if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e')))
1057  {
1058  if (RAPIDJSON_UNLIKELY(!handler.Bool(false)))
1060  }
1061  else
1063  }
1064 
1065  template <typename InputStream>
1066  RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect)
1067  {
1068  if (RAPIDJSON_LIKELY(is.Peek() == expect))
1069  {
1070  is.Take();
1071  return true;
1072  }
1073  else
1074  return false;
1075  }
1076 
1077  // Helper function to parse four hexadecimal digits in \uXXXX in ParseString().
1078  template <typename InputStream>
1079  unsigned ParseHex4(InputStream& is, size_t escapeOffset)
1080  {
1081  unsigned codepoint = 0;
1082  for (int i = 0; i < 4; i++)
1083  {
1084  Ch c = is.Peek();
1085  codepoint <<= 4;
1086  codepoint += static_cast<unsigned>(c);
1087  if (c >= '0' && c <= '9')
1088  codepoint -= '0';
1089  else if (c >= 'A' && c <= 'F')
1090  codepoint -= 'A' - 10;
1091  else if (c >= 'a' && c <= 'f')
1092  codepoint -= 'a' - 10;
1093  else
1094  {
1096  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
1097  }
1098  is.Take();
1099  }
1100  return codepoint;
1101  }
1102 
1103  template <typename CharType>
1105  {
1106  public:
1107  typedef CharType Ch;
1108 
1109  StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0)
1110  {
1111  }
1112  RAPIDJSON_FORCEINLINE void Put(Ch c)
1113  {
1114  *stack_.template Push<Ch>() = c;
1115  ++length_;
1116  }
1117 
1118  RAPIDJSON_FORCEINLINE void* Push(SizeType count)
1119  {
1120  length_ += count;
1121  return stack_.template Push<Ch>(count);
1122  }
1123 
1124  size_t Length() const
1125  {
1126  return length_;
1127  }
1128 
1129  Ch* Pop()
1130  {
1131  return stack_.template Pop<Ch>(length_);
1132  }
1133 
1134  private:
1135  StackStream(const StackStream&);
1136  StackStream& operator=(const StackStream&);
1137 
1140  };
1141 
1142  // Parse string and generate String event. Different code paths for kParseInsituFlag.
1143  template <unsigned parseFlags, typename InputStream, typename Handler>
1144  void ParseString(InputStream& is, Handler& handler, bool isKey = false)
1145  {
1147  InputStream& s(copy.s);
1148 
1149  RAPIDJSON_ASSERT(s.Peek() == '\"');
1150  s.Take(); // Skip '\"'
1151 
1152  bool success = false;
1153  if (parseFlags & kParseInsituFlag)
1154  {
1155  typename InputStream::Ch* head = s.PutBegin();
1156  ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
1157  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1158  size_t length = s.PutEnd(head) - 1;
1159  RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
1160  const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
1161  success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
1162  }
1163  else
1164  {
1165  StackStream<typename TargetEncoding::Ch> stackStream(stack_);
1166  ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
1167  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1168  SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
1169  const typename TargetEncoding::Ch* const str = stackStream.Pop();
1170  success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
1171  }
1172  if (RAPIDJSON_UNLIKELY(!success))
1174  }
1175 
1176  // Parse string to an output is
1177  // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
1178  template <unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
1179  RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os)
1180  {
1182 #define Z16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1183  static const char escape[256] = { Z16, Z16, 0, 0, '\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1184  0, '/', Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1185  '\\', 0, 0, 0, 0, 0, '\b', 0, 0, 0, '\f', 0, 0, 0, 0, 0,
1186  0, 0, '\n', 0, 0, 0, '\r', 0, '\t', 0, 0, 0, 0, 0, 0, 0,
1187  0, 0, 0, 0, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 };
1188 #undef Z16
1189 
1191  for (;;)
1192  {
1193  // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
1194  if (!(parseFlags & kParseValidateEncodingFlag))
1195  ScanCopyUnescapedString(is, os);
1196 
1197  Ch c = is.Peek();
1198  if (RAPIDJSON_UNLIKELY(c == '\\'))
1199  { // Escape
1200  size_t escapeOffset = is.Tell(); // For invalid escaping, report the initial '\\' as error offset
1201  is.Take();
1202  Ch e = is.Peek();
1203  if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)]))
1204  {
1205  is.Take();
1206  os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
1207  }
1208  else if (RAPIDJSON_LIKELY(e == 'u'))
1209  { // Unicode
1210  is.Take();
1211  unsigned codepoint = ParseHex4(is, escapeOffset);
1212  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1213  if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF))
1214  {
1215  // Handle UTF-16 surrogate pair
1216  if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
1218  unsigned codepoint2 = ParseHex4(is, escapeOffset);
1219  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1220  if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
1222  codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
1223  }
1224  TEncoding::Encode(os, codepoint);
1225  }
1226  else
1228  }
1229  else if (RAPIDJSON_UNLIKELY(c == '"'))
1230  { // Closing double quote
1231  is.Take();
1232  os.Put('\0'); // null-terminate the string
1233  return;
1234  }
1235  else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20))
1236  { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
1237  if (c == '\0')
1239  else
1241  }
1242  else
1243  {
1244  size_t offset = is.Tell();
1245  if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
1249  }
1250  }
1251  }
1252 
1253  template <typename InputStream, typename OutputStream>
1254  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&)
1255  {
1256  // Do nothing for generic version
1257  }
1258 
1259 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
1260  // StringStream -> StackStream<char>
1261  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os)
1262  {
1263  const char* p = is.src_;
1264 
1265  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1266  const char* nextAligned =
1267  reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1268  while (p != nextAligned)
1269  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') ||
1270  RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20))
1271  {
1272  is.src_ = p;
1273  return;
1274  }
1275  else
1276  os.Put(*p++);
1277 
1278  // The rest of string using SIMD
1279  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"',
1280  '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1281  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\',
1282  '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1283  static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
1284  0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
1285  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0]));
1286  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0]));
1287  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0]));
1288 
1289  for (;; p += 16)
1290  {
1291  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
1292  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1293  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1294  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
1295  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1296  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1297  if (RAPIDJSON_UNLIKELY(r != 0))
1298  { // some of characters is escaped
1299  SizeType length;
1300 #if _MSC_VER // Find the index of first escaped
1301  unsigned long offset;
1302  _BitScanForward(&offset, r);
1303  length = offset;
1304 #else
1305  length = static_cast<SizeType>(__builtin_ffs(r) - 1);
1306 #endif
1307  if (length != 0)
1308  {
1309  char* q = reinterpret_cast<char*>(os.Push(length));
1310  for (size_t i = 0; i < length; i++)
1311  q[i] = p[i];
1312 
1313  p += length;
1314  }
1315  break;
1316  }
1317  _mm_storeu_si128(reinterpret_cast<__m128i*>(os.Push(16)), s);
1318  }
1319 
1320  is.src_ = p;
1321  }
1322 
1323  // InsituStringStream -> InsituStringStream
1324  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os)
1325  {
1326  RAPIDJSON_ASSERT(&is == &os);
1327  (void)os;
1328 
1329  if (is.src_ == is.dst_)
1330  {
1331  SkipUnescapedString(is);
1332  return;
1333  }
1334 
1335  char* p = is.src_;
1336  char* q = is.dst_;
1337 
1338  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1339  const char* nextAligned =
1340  reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1341  while (p != nextAligned)
1342  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') ||
1343  RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20))
1344  {
1345  is.src_ = p;
1346  is.dst_ = q;
1347  return;
1348  }
1349  else
1350  *q++ = *p++;
1351 
1352  // The rest of string using SIMD
1353  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"',
1354  '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1355  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\',
1356  '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1357  static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
1358  0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
1359  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0]));
1360  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0]));
1361  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0]));
1362 
1363  for (;; p += 16, q += 16)
1364  {
1365  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
1366  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1367  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1368  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
1369  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1370  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1371  if (RAPIDJSON_UNLIKELY(r != 0))
1372  { // some of characters is escaped
1373  size_t length;
1374 #if _MSC_VER // Find the index of first escaped
1375  unsigned long offset;
1376  _BitScanForward(&offset, r);
1377  length = offset;
1378 #else
1379  length = static_cast<size_t>(__builtin_ffs(r) - 1);
1380 #endif
1381  for (const char* pend = p + length; p != pend;)
1382  *q++ = *p++;
1383  break;
1384  }
1385  _mm_storeu_si128(reinterpret_cast<__m128i*>(q), s);
1386  }
1387 
1388  is.src_ = p;
1389  is.dst_ = q;
1390  }
1391 
1392  // When read/write pointers are the same for insitu stream, just skip unescaped characters
1393  static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is)
1394  {
1395  RAPIDJSON_ASSERT(is.src_ == is.dst_);
1396  char* p = is.src_;
1397 
1398  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1399  const char* nextAligned =
1400  reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1401  for (; p != nextAligned; p++)
1402  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') ||
1403  RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20))
1404  {
1405  is.src_ = is.dst_ = p;
1406  return;
1407  }
1408 
1409  // The rest of string using SIMD
1410  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"',
1411  '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1412  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\',
1413  '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1414  static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
1415  0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
1416  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0]));
1417  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0]));
1418  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0]));
1419 
1420  for (;; p += 16)
1421  {
1422  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
1423  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1424  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1425  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
1426  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1427  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1428  if (RAPIDJSON_UNLIKELY(r != 0))
1429  { // some of characters is escaped
1430  size_t length;
1431 #if _MSC_VER // Find the index of first escaped
1432  unsigned long offset;
1433  _BitScanForward(&offset, r);
1434  length = offset;
1435 #else
1436  length = static_cast<size_t>(__builtin_ffs(r) - 1);
1437 #endif
1438  p += length;
1439  break;
1440  }
1441  }
1442 
1443  is.src_ = is.dst_ = p;
1444  }
1445 #elif defined(RAPIDJSON_NEON)
1446  // StringStream -> StackStream<char>
1447  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os)
1448  {
1449  const char* p = is.src_;
1450 
1451  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1452  const char* nextAligned =
1453  reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1454  while (p != nextAligned)
1455  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') ||
1456  RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20))
1457  {
1458  is.src_ = p;
1459  return;
1460  }
1461  else
1462  os.Put(*p++);
1463 
1464  // The rest of string using SIMD
1465  const uint8x16_t s0 = vmovq_n_u8('"');
1466  const uint8x16_t s1 = vmovq_n_u8('\\');
1467  const uint8x16_t s2 = vmovq_n_u8('\b');
1468  const uint8x16_t s3 = vmovq_n_u8(32);
1469 
1470  for (;; p += 16)
1471  {
1472  const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p));
1473  uint8x16_t x = vceqq_u8(s, s0);
1474  x = vorrq_u8(x, vceqq_u8(s, s1));
1475  x = vorrq_u8(x, vceqq_u8(s, s2));
1476  x = vorrq_u8(x, vcltq_u8(s, s3));
1477 
1478  x = vrev64q_u8(x); // Rev in 64
1479  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
1480  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
1481 
1482  SizeType length = 0;
1483  bool escaped = false;
1484  if (low == 0)
1485  {
1486  if (high != 0)
1487  {
1488  unsigned lz = (unsigned)__builtin_clzll(high);
1489  ;
1490  length = 8 + (lz >> 3);
1491  escaped = true;
1492  }
1493  }
1494  else
1495  {
1496  unsigned lz = (unsigned)__builtin_clzll(low);
1497  ;
1498  length = lz >> 3;
1499  escaped = true;
1500  }
1501  if (RAPIDJSON_UNLIKELY(escaped))
1502  { // some of characters is escaped
1503  if (length != 0)
1504  {
1505  char* q = reinterpret_cast<char*>(os.Push(length));
1506  for (size_t i = 0; i < length; i++)
1507  q[i] = p[i];
1508 
1509  p += length;
1510  }
1511  break;
1512  }
1513  vst1q_u8(reinterpret_cast<uint8_t*>(os.Push(16)), s);
1514  }
1515 
1516  is.src_ = p;
1517  }
1518 
1519  // InsituStringStream -> InsituStringStream
1520  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os)
1521  {
1522  RAPIDJSON_ASSERT(&is == &os);
1523  (void)os;
1524 
1525  if (is.src_ == is.dst_)
1526  {
1527  SkipUnescapedString(is);
1528  return;
1529  }
1530 
1531  char* p = is.src_;
1532  char* q = is.dst_;
1533 
1534  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1535  const char* nextAligned =
1536  reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1537  while (p != nextAligned)
1538  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') ||
1539  RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20))
1540  {
1541  is.src_ = p;
1542  is.dst_ = q;
1543  return;
1544  }
1545  else
1546  *q++ = *p++;
1547 
1548  // The rest of string using SIMD
1549  const uint8x16_t s0 = vmovq_n_u8('"');
1550  const uint8x16_t s1 = vmovq_n_u8('\\');
1551  const uint8x16_t s2 = vmovq_n_u8('\b');
1552  const uint8x16_t s3 = vmovq_n_u8(32);
1553 
1554  for (;; p += 16, q += 16)
1555  {
1556  const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t*>(p));
1557  uint8x16_t x = vceqq_u8(s, s0);
1558  x = vorrq_u8(x, vceqq_u8(s, s1));
1559  x = vorrq_u8(x, vceqq_u8(s, s2));
1560  x = vorrq_u8(x, vcltq_u8(s, s3));
1561 
1562  x = vrev64q_u8(x); // Rev in 64
1563  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
1564  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
1565 
1566  SizeType length = 0;
1567  bool escaped = false;
1568  if (low == 0)
1569  {
1570  if (high != 0)
1571  {
1572  unsigned lz = (unsigned)__builtin_clzll(high);
1573  length = 8 + (lz >> 3);
1574  escaped = true;
1575  }
1576  }
1577  else
1578  {
1579  unsigned lz = (unsigned)__builtin_clzll(low);
1580  length = lz >> 3;
1581  escaped = true;
1582  }
1583  if (RAPIDJSON_UNLIKELY(escaped))
1584  { // some of characters is escaped
1585  for (const char* pend = p + length; p != pend;)
1586  {
1587  *q++ = *p++;
1588  }
1589  break;
1590  }
1591  vst1q_u8(reinterpret_cast<uint8_t*>(q), s);
1592  }
1593 
1594  is.src_ = p;
1595  is.dst_ = q;
1596  }
1597 
1598  // When read/write pointers are the same for insitu stream, just skip unescaped characters
1599  static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is)
1600  {
1601  RAPIDJSON_ASSERT(is.src_ == is.dst_);
1602  char* p = is.src_;
1603 
1604  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1605  const char* nextAligned =
1606  reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1607  for (; p != nextAligned; p++)
1608  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') ||
1609  RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20))
1610  {
1611  is.src_ = is.dst_ = p;
1612  return;
1613  }
1614 
1615  // The rest of string using SIMD
1616  const uint8x16_t s0 = vmovq_n_u8('"');
1617  const uint8x16_t s1 = vmovq_n_u8('\\');
1618  const uint8x16_t s2 = vmovq_n_u8('\b');
1619  const uint8x16_t s3 = vmovq_n_u8(32);
1620 
1621  for (;; p += 16)
1622  {
1623  const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t*>(p));
1624  uint8x16_t x = vceqq_u8(s, s0);
1625  x = vorrq_u8(x, vceqq_u8(s, s1));
1626  x = vorrq_u8(x, vceqq_u8(s, s2));
1627  x = vorrq_u8(x, vcltq_u8(s, s3));
1628 
1629  x = vrev64q_u8(x); // Rev in 64
1630  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
1631  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
1632 
1633  if (low == 0)
1634  {
1635  if (high != 0)
1636  {
1637  int lz = __builtin_clzll(high);
1638  p += 8 + (lz >> 3);
1639  break;
1640  }
1641  }
1642  else
1643  {
1644  int lz = __builtin_clzll(low);
1645  p += lz >> 3;
1646  break;
1647  }
1648  }
1649 
1650  is.src_ = is.dst_ = p;
1651  }
1652 #endif // RAPIDJSON_NEON
1653 
1654  template <typename InputStream, bool backup, bool pushOnTake>
1656 
1657  template <typename InputStream>
1658  class NumberStream<InputStream, false, false>
1659  {
1660  public:
1661  typedef typename InputStream::Ch Ch;
1662 
1663  NumberStream(GenericReader& reader, InputStream& s) : is(s)
1664  {
1665  (void)reader;
1666  }
1667 
1668  RAPIDJSON_FORCEINLINE Ch Peek() const
1669  {
1670  return is.Peek();
1671  }
1672  RAPIDJSON_FORCEINLINE Ch TakePush()
1673  {
1674  return is.Take();
1675  }
1676  RAPIDJSON_FORCEINLINE Ch Take()
1677  {
1678  return is.Take();
1679  }
1680  RAPIDJSON_FORCEINLINE void Push(char)
1681  {
1682  }
1683 
1684  size_t Tell()
1685  {
1686  return is.Tell();
1687  }
1688  size_t Length()
1689  {
1690  return 0;
1691  }
1692  const char* Pop()
1693  {
1694  return 0;
1695  }
1696 
1697  protected:
1698  NumberStream& operator=(const NumberStream&);
1699 
1700  InputStream& is;
1701  };
1702 
1703  template <typename InputStream>
1704  class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false>
1705  {
1707 
1708  public:
1709  NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_)
1710  {
1711  }
1712 
1713  RAPIDJSON_FORCEINLINE Ch TakePush()
1714  {
1715  stackStream.Put(static_cast<char>(Base::is.Peek()));
1716  return Base::is.Take();
1717  }
1718 
1719  RAPIDJSON_FORCEINLINE void Push(char c)
1720  {
1721  stackStream.Put(c);
1722  }
1723 
1724  size_t Length()
1725  {
1726  return stackStream.Length();
1727  }
1728 
1729  const char* Pop()
1730  {
1731  stackStream.Put('\0');
1732  return stackStream.Pop();
1733  }
1734 
1735  private:
1737  };
1738 
1739  template <typename InputStream>
1740  class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false>
1741  {
1743 
1744  public:
1745  NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is)
1746  {
1747  }
1748 
1749  RAPIDJSON_FORCEINLINE Ch Take()
1750  {
1751  return Base::TakePush();
1752  }
1753  };
1754 
1755  template <unsigned parseFlags, typename InputStream, typename Handler>
1756  void ParseNumber(InputStream& is, Handler& handler)
1757  {
1759  NumberStream<InputStream,
1760  ((parseFlags & kParseNumbersAsStringsFlag) != 0) ? ((parseFlags & kParseInsituFlag) == 0) :
1761  ((parseFlags & kParseFullPrecisionFlag) != 0),
1762  (parseFlags & kParseNumbersAsStringsFlag) != 0 && (parseFlags & kParseInsituFlag) == 0>
1763  s(*this, copy.s);
1764 
1765  size_t startOffset = s.Tell();
1766  double d = 0.0;
1767  bool useNanOrInf = false;
1768 
1769  // Parse minus
1770  bool minus = Consume(s, '-');
1771 
1772  // Parse int: zero / ( digit1-9 *DIGIT )
1773  unsigned i = 0;
1774  uint64_t i64 = 0;
1775  bool use64bit = false;
1776  int significandDigit = 0;
1777  if (RAPIDJSON_UNLIKELY(s.Peek() == '0'))
1778  {
1779  i = 0;
1780  s.TakePush();
1781  }
1782  else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9'))
1783  {
1784  i = static_cast<unsigned>(s.TakePush() - '0');
1785 
1786  if (minus)
1787  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9'))
1788  {
1789  if (RAPIDJSON_UNLIKELY(i >= 214748364))
1790  { // 2^31 = 2147483648
1791  if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8'))
1792  {
1793  i64 = i;
1794  use64bit = true;
1795  break;
1796  }
1797  }
1798  i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
1799  significandDigit++;
1800  }
1801  else
1802  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9'))
1803  {
1804  if (RAPIDJSON_UNLIKELY(i >= 429496729))
1805  { // 2^32 - 1 = 4294967295
1806  if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5'))
1807  {
1808  i64 = i;
1809  use64bit = true;
1810  break;
1811  }
1812  }
1813  i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
1814  significandDigit++;
1815  }
1816  }
1817  // Parse NaN or Infinity here
1818  else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N')))
1819  {
1820  if (Consume(s, 'N'))
1821  {
1822  if (Consume(s, 'a') && Consume(s, 'N'))
1823  {
1824  d = std::numeric_limits<double>::quiet_NaN();
1825  useNanOrInf = true;
1826  }
1827  }
1828  else if (RAPIDJSON_LIKELY(Consume(s, 'I')))
1829  {
1830  if (Consume(s, 'n') && Consume(s, 'f'))
1831  {
1832  d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
1833  useNanOrInf = true;
1834 
1835  if (RAPIDJSON_UNLIKELY(
1836  s.Peek() == 'i' &&
1837  !(Consume(s, 'i') && Consume(s, 'n') && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y'))))
1838  {
1840  }
1841  }
1842  }
1843 
1844  if (RAPIDJSON_UNLIKELY(!useNanOrInf))
1845  {
1847  }
1848  }
1849  else
1851 
1852  // Parse 64bit int
1853  bool useDouble = false;
1854  if (use64bit)
1855  {
1856  if (minus)
1857  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9'))
1858  {
1859  if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
1860  if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8'))
1861  {
1862  d = static_cast<double>(i64);
1863  useDouble = true;
1864  break;
1865  }
1866  i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1867  significandDigit++;
1868  }
1869  else
1870  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9'))
1871  {
1872  if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 =
1873  // 18446744073709551615
1874  if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5'))
1875  {
1876  d = static_cast<double>(i64);
1877  useDouble = true;
1878  break;
1879  }
1880  i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1881  significandDigit++;
1882  }
1883  }
1884 
1885  // Force double for big integer
1886  if (useDouble)
1887  {
1888  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9'))
1889  {
1890  d = d * 10 + (s.TakePush() - '0');
1891  }
1892  }
1893 
1894  // Parse frac = decimal-point 1*DIGIT
1895  int expFrac = 0;
1896  size_t decimalPosition;
1897  if (Consume(s, '.'))
1898  {
1899  decimalPosition = s.Length();
1900 
1901  if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
1903 
1904  if (!useDouble)
1905  {
1906 #if RAPIDJSON_64BIT
1907  // Use i64 to store significand in 64-bit architecture
1908  if (!use64bit)
1909  i64 = i;
1910 
1911  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9'))
1912  {
1913  if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
1914  break;
1915  else
1916  {
1917  i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1918  --expFrac;
1919  if (i64 != 0)
1920  significandDigit++;
1921  }
1922  }
1923 
1924  d = static_cast<double>(i64);
1925 #else
1926  // Use double to store significand in 32-bit architecture
1927  d = static_cast<double>(use64bit ? i64 : i);
1928 #endif
1929  useDouble = true;
1930  }
1931 
1932  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9'))
1933  {
1934  if (significandDigit < 17)
1935  {
1936  d = d * 10.0 + (s.TakePush() - '0');
1937  --expFrac;
1938  if (RAPIDJSON_LIKELY(d > 0.0))
1939  significandDigit++;
1940  }
1941  else
1942  s.TakePush();
1943  }
1944  }
1945  else
1946  decimalPosition = s.Length(); // decimal position at the end of integer.
1947 
1948  // Parse exp = e [ minus / plus ] 1*DIGIT
1949  int exp = 0;
1950  if (Consume(s, 'e') || Consume(s, 'E'))
1951  {
1952  if (!useDouble)
1953  {
1954  d = static_cast<double>(use64bit ? i64 : i);
1955  useDouble = true;
1956  }
1957 
1958  bool expMinus = false;
1959  if (Consume(s, '+'))
1960  ;
1961  else if (Consume(s, '-'))
1962  expMinus = true;
1963 
1964  if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9'))
1965  {
1966  exp = static_cast<int>(s.Take() - '0');
1967  if (expMinus)
1968  {
1969  // (exp + expFrac) must not underflow int => we're detecting when -exp gets
1970  // dangerously close to INT_MIN (a pessimistic next digit 9 would push it into
1971  // underflow territory):
1972  //
1973  // -(exp * 10 + 9) + expFrac >= INT_MIN
1974  // <=> exp <= (expFrac - INT_MIN - 9) / 10
1975  RAPIDJSON_ASSERT(expFrac <= 0);
1976  int maxExp = (expFrac + 2147483639) / 10;
1977 
1978  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9'))
1979  {
1980  exp = exp * 10 + static_cast<int>(s.Take() - '0');
1981  if (RAPIDJSON_UNLIKELY(exp > maxExp))
1982  {
1983  while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent
1984  s.Take();
1985  }
1986  }
1987  }
1988  else
1989  { // positive exp
1990  int maxExp = 308 - expFrac;
1991  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9'))
1992  {
1993  exp = exp * 10 + static_cast<int>(s.Take() - '0');
1994  if (RAPIDJSON_UNLIKELY(exp > maxExp))
1996  }
1997  }
1998  }
1999  else
2001 
2002  if (expMinus)
2003  exp = -exp;
2004  }
2005 
2006  // Finish parsing, call event according to the type of number.
2007  bool cont = true;
2008 
2009  if (parseFlags & kParseNumbersAsStringsFlag)
2010  {
2011  if (parseFlags & kParseInsituFlag)
2012  {
2013  s.Pop(); // Pop stack no matter if it will be used or not.
2014  typename InputStream::Ch* head = is.PutBegin();
2015  const size_t length = s.Tell() - startOffset;
2016  RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
2017  // unable to insert the \0 character here, it will erase the comma after this number
2018  const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
2019  cont = handler.RawNumber(str, SizeType(length), false);
2020  }
2021  else
2022  {
2023  SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
2024  StringStream srcStream(s.Pop());
2025  StackStream<typename TargetEncoding::Ch> dstStream(stack_);
2026  while (numCharsToCopy--)
2027  {
2028  Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);
2029  }
2030  dstStream.Put('\0');
2031  const typename TargetEncoding::Ch* str = dstStream.Pop();
2032  const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;
2033  cont = handler.RawNumber(str, SizeType(length), true);
2034  }
2035  }
2036  else
2037  {
2038  size_t length = s.Length();
2039  const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
2040 
2041  if (useDouble)
2042  {
2043  int p = exp + expFrac;
2044  if (parseFlags & kParseFullPrecisionFlag)
2045  d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
2046  else
2048 
2049  // Use > max, instead of == inf, to fix bogus warning -Wfloat-equal
2050  if (d > (std::numeric_limits<double>::max)())
2051  {
2052  // Overflow
2053  // TODO: internal::StrtodX should report overflow (or underflow)
2055  }
2056 
2057  cont = handler.Double(minus ? -d : d);
2058  }
2059  else if (useNanOrInf)
2060  {
2061  cont = handler.Double(d);
2062  }
2063  else
2064  {
2065  if (use64bit)
2066  {
2067  if (minus)
2068  cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
2069  else
2070  cont = handler.Uint64(i64);
2071  }
2072  else
2073  {
2074  if (minus)
2075  cont = handler.Int(static_cast<int32_t>(~i + 1));
2076  else
2077  cont = handler.Uint(i);
2078  }
2079  }
2080  }
2081  if (RAPIDJSON_UNLIKELY(!cont))
2083  }
2084 
2085  // Parse any JSON value
2086  template <unsigned parseFlags, typename InputStream, typename Handler>
2087  void ParseValue(InputStream& is, Handler& handler)
2088  {
2089  switch (is.Peek())
2090  {
2091  case 'n':
2092  ParseNull<parseFlags>(is, handler);
2093  break;
2094  case 't':
2095  ParseTrue<parseFlags>(is, handler);
2096  break;
2097  case 'f':
2098  ParseFalse<parseFlags>(is, handler);
2099  break;
2100  case '"':
2101  ParseString<parseFlags>(is, handler);
2102  break;
2103  case '{':
2104  ParseObject<parseFlags>(is, handler);
2105  break;
2106  case '[':
2107  ParseArray<parseFlags>(is, handler);
2108  break;
2109  default:
2110  ParseNumber<parseFlags>(is, handler);
2111  break;
2112  }
2113  }
2114 
2115  // Iterative Parsing
2116 
2117  // States
2119  {
2120  IterativeParsingFinishState = 0, // sink states at top
2121  IterativeParsingErrorState, // sink states at top
2123 
2124  // Object states
2129 
2130  // Array states
2134 
2135  // Single value state
2137 
2138  // Delimiter states (at bottom)
2142 
2143  cIterativeParsingStateCount
2144  };
2145 
2146  // Tokens
2147  enum Token
2148  {
2149  LeftBracketToken = 0,
2151 
2154 
2157 
2163 
2164  kTokenCount
2165  };
2166 
2167  RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) const
2168  {
2170 #define N NumberToken
2171 #define N16 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N
2172  // Maps from ASCII to Token
2173  static const unsigned char tokenMap[256] = {
2174  N16, // 00~0F
2175  N16, // 10~1F
2176  N, N,
2177  StringToken, N,
2178  N, N,
2179  N, N,
2180  N, N,
2181  N, N,
2182  CommaToken, N,
2183  N, N, // 20~2F
2184  N, N,
2185  N, N,
2186  N, N,
2187  N, N,
2188  N, N,
2189  ColonToken, N,
2190  N, N,
2191  N, N, // 30~3F
2192  N16, // 40~4F
2193  N, N,
2194  N, N,
2195  N, N,
2196  N, N,
2197  N, N,
2198  N, LeftBracketToken,
2199  N, RightBracketToken,
2200  N, N, // 50~5F
2201  N, N,
2202  N, N,
2203  N, N,
2204  FalseToken, N,
2205  N, N,
2206  N, N,
2207  N, N,
2208  NullToken, N, // 60~6F
2209  N, N,
2210  N, N,
2211  TrueToken, N,
2212  N, N,
2213  N, N,
2214  N, LeftCurlyBracketToken,
2215  N, RightCurlyBracketToken,
2216  N, N, // 70~7F
2217  N16, N16,
2218  N16, N16,
2219  N16, N16,
2220  N16, N16 // 80~FF
2221  };
2222 #undef N
2223 #undef N16
2224 
2226  if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
2227  return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
2228  else
2229  return NumberToken;
2230  }
2231 
2232  RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) const
2233  {
2234  // current state x one lookahead token -> new state
2235  static const char G[cIterativeParsingStateCount][kTokenCount] = {
2236  // Finish(sink state)
2237  { IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
2238  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
2239  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState },
2240  // Error(sink state)
2241  { IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
2242  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
2243  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState },
2244  // Start
2245  {
2246  IterativeParsingArrayInitialState, // Left bracket
2247  IterativeParsingErrorState, // Right bracket
2248  IterativeParsingObjectInitialState, // Left curly bracket
2249  IterativeParsingErrorState, // Right curly bracket
2250  IterativeParsingErrorState, // Comma
2251  IterativeParsingErrorState, // Colon
2252  IterativeParsingValueState, // String
2253  IterativeParsingValueState, // False
2254  IterativeParsingValueState, // True
2255  IterativeParsingValueState, // Null
2256  IterativeParsingValueState // Number
2257  },
2258  // ObjectInitial
2259  {
2260  IterativeParsingErrorState, // Left bracket
2261  IterativeParsingErrorState, // Right bracket
2262  IterativeParsingErrorState, // Left curly bracket
2263  IterativeParsingObjectFinishState, // Right curly bracket
2264  IterativeParsingErrorState, // Comma
2265  IterativeParsingErrorState, // Colon
2266  IterativeParsingMemberKeyState, // String
2267  IterativeParsingErrorState, // False
2268  IterativeParsingErrorState, // True
2269  IterativeParsingErrorState, // Null
2270  IterativeParsingErrorState // Number
2271  },
2272  // MemberKey
2273  {
2274  IterativeParsingErrorState, // Left bracket
2275  IterativeParsingErrorState, // Right bracket
2276  IterativeParsingErrorState, // Left curly bracket
2277  IterativeParsingErrorState, // Right curly bracket
2278  IterativeParsingErrorState, // Comma
2279  IterativeParsingKeyValueDelimiterState, // Colon
2280  IterativeParsingErrorState, // String
2281  IterativeParsingErrorState, // False
2282  IterativeParsingErrorState, // True
2283  IterativeParsingErrorState, // Null
2284  IterativeParsingErrorState // Number
2285  },
2286  // MemberValue
2287  {
2288  IterativeParsingErrorState, // Left bracket
2289  IterativeParsingErrorState, // Right bracket
2290  IterativeParsingErrorState, // Left curly bracket
2291  IterativeParsingObjectFinishState, // Right curly bracket
2292  IterativeParsingMemberDelimiterState, // Comma
2293  IterativeParsingErrorState, // Colon
2294  IterativeParsingErrorState, // String
2295  IterativeParsingErrorState, // False
2296  IterativeParsingErrorState, // True
2297  IterativeParsingErrorState, // Null
2298  IterativeParsingErrorState // Number
2299  },
2300  // ObjectFinish(sink state)
2301  { IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
2302  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
2303  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState },
2304  // ArrayInitial
2305  {
2306  IterativeParsingArrayInitialState, // Left bracket(push Element state)
2307  IterativeParsingArrayFinishState, // Right bracket
2308  IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
2309  IterativeParsingErrorState, // Right curly bracket
2310  IterativeParsingErrorState, // Comma
2311  IterativeParsingErrorState, // Colon
2312  IterativeParsingElementState, // String
2313  IterativeParsingElementState, // False
2314  IterativeParsingElementState, // True
2315  IterativeParsingElementState, // Null
2316  IterativeParsingElementState // Number
2317  },
2318  // Element
2319  {
2320  IterativeParsingErrorState, // Left bracket
2321  IterativeParsingArrayFinishState, // Right bracket
2322  IterativeParsingErrorState, // Left curly bracket
2323  IterativeParsingErrorState, // Right curly bracket
2324  IterativeParsingElementDelimiterState, // Comma
2325  IterativeParsingErrorState, // Colon
2326  IterativeParsingErrorState, // String
2327  IterativeParsingErrorState, // False
2328  IterativeParsingErrorState, // True
2329  IterativeParsingErrorState, // Null
2330  IterativeParsingErrorState // Number
2331  },
2332  // ArrayFinish(sink state)
2333  { IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
2334  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
2335  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState },
2336  // Single Value (sink state)
2337  { IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
2338  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
2339  IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState },
2340  // ElementDelimiter
2341  {
2342  IterativeParsingArrayInitialState, // Left bracket(push Element state)
2343  IterativeParsingArrayFinishState, // Right bracket
2344  IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
2345  IterativeParsingErrorState, // Right curly bracket
2346  IterativeParsingErrorState, // Comma
2347  IterativeParsingErrorState, // Colon
2348  IterativeParsingElementState, // String
2349  IterativeParsingElementState, // False
2350  IterativeParsingElementState, // True
2351  IterativeParsingElementState, // Null
2352  IterativeParsingElementState // Number
2353  },
2354  // MemberDelimiter
2355  {
2356  IterativeParsingErrorState, // Left bracket
2357  IterativeParsingErrorState, // Right bracket
2358  IterativeParsingErrorState, // Left curly bracket
2359  IterativeParsingObjectFinishState, // Right curly bracket
2360  IterativeParsingErrorState, // Comma
2361  IterativeParsingErrorState, // Colon
2362  IterativeParsingMemberKeyState, // String
2363  IterativeParsingErrorState, // False
2364  IterativeParsingErrorState, // True
2365  IterativeParsingErrorState, // Null
2366  IterativeParsingErrorState // Number
2367  },
2368  // KeyValueDelimiter
2369  {
2370  IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
2371  IterativeParsingErrorState, // Right bracket
2372  IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
2373  IterativeParsingErrorState, // Right curly bracket
2374  IterativeParsingErrorState, // Comma
2375  IterativeParsingErrorState, // Colon
2376  IterativeParsingMemberValueState, // String
2377  IterativeParsingMemberValueState, // False
2378  IterativeParsingMemberValueState, // True
2379  IterativeParsingMemberValueState, // Null
2380  IterativeParsingMemberValueState // Number
2381  },
2382  }; // End of G
2383 
2384  return static_cast<IterativeParsingState>(G[state][token]);
2385  }
2386 
2387  // Make an advance in the token stream and state based on the candidate destination state which was returned by
2388  // Transit().
2389  // May return a new state on state pop.
2390  template <unsigned parseFlags, typename InputStream, typename Handler>
2392  InputStream& is, Handler& handler)
2393  {
2394  (void)token;
2395 
2396  switch (dst)
2397  {
2398  case IterativeParsingErrorState:
2399  return dst;
2400 
2401  case IterativeParsingObjectInitialState:
2402  case IterativeParsingArrayInitialState:
2403  {
2404  // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
2405  // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
2406  IterativeParsingState n = src;
2407  if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
2408  n = IterativeParsingElementState;
2409  else if (src == IterativeParsingKeyValueDelimiterState)
2410  n = IterativeParsingMemberValueState;
2411  // Push current state.
2412  *stack_.template Push<SizeType>(1) = n;
2413  // Initialize and push the member/element count.
2414  *stack_.template Push<SizeType>(1) = 0;
2415  // Call handler
2416  bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
2417  // On handler short circuits the parsing.
2418  if (!hr)
2419  {
2421  return IterativeParsingErrorState;
2422  }
2423  else
2424  {
2425  is.Take();
2426  return dst;
2427  }
2428  }
2429 
2430  case IterativeParsingMemberKeyState:
2431  ParseString<parseFlags>(is, handler, true);
2432  if (HasParseError())
2433  return IterativeParsingErrorState;
2434  else
2435  return dst;
2436 
2437  case IterativeParsingKeyValueDelimiterState:
2438  RAPIDJSON_ASSERT(token == ColonToken);
2439  is.Take();
2440  return dst;
2441 
2442  case IterativeParsingMemberValueState:
2443  // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2444  ParseValue<parseFlags>(is, handler);
2445  if (HasParseError())
2446  {
2447  return IterativeParsingErrorState;
2448  }
2449  return dst;
2450 
2451  case IterativeParsingElementState:
2452  // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2453  ParseValue<parseFlags>(is, handler);
2454  if (HasParseError())
2455  {
2456  return IterativeParsingErrorState;
2457  }
2458  return dst;
2459 
2460  case IterativeParsingMemberDelimiterState:
2461  case IterativeParsingElementDelimiterState:
2462  is.Take();
2463  // Update member/element count.
2464  *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
2465  return dst;
2466 
2467  case IterativeParsingObjectFinishState:
2468  {
2469  // Transit from delimiter is only allowed when trailing commas are enabled
2470  if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState)
2471  {
2473  return IterativeParsingErrorState;
2474  }
2475  // Get member count.
2476  SizeType c = *stack_.template Pop<SizeType>(1);
2477  // If the object is not empty, count the last member.
2478  if (src == IterativeParsingMemberValueState)
2479  ++c;
2480  // Restore the state.
2481  IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
2482  // Transit to Finish state if this is the topmost scope.
2483  if (n == IterativeParsingStartState)
2484  n = IterativeParsingFinishState;
2485  // Call handler
2486  bool hr = handler.EndObject(c);
2487  // On handler short circuits the parsing.
2488  if (!hr)
2489  {
2491  return IterativeParsingErrorState;
2492  }
2493  else
2494  {
2495  is.Take();
2496  return n;
2497  }
2498  }
2499 
2500  case IterativeParsingArrayFinishState:
2501  {
2502  // Transit from delimiter is only allowed when trailing commas are enabled
2503  if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState)
2504  {
2506  return IterativeParsingErrorState;
2507  }
2508  // Get element count.
2509  SizeType c = *stack_.template Pop<SizeType>(1);
2510  // If the array is not empty, count the last element.
2511  if (src == IterativeParsingElementState)
2512  ++c;
2513  // Restore the state.
2514  IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
2515  // Transit to Finish state if this is the topmost scope.
2516  if (n == IterativeParsingStartState)
2517  n = IterativeParsingFinishState;
2518  // Call handler
2519  bool hr = handler.EndArray(c);
2520  // On handler short circuits the parsing.
2521  if (!hr)
2522  {
2524  return IterativeParsingErrorState;
2525  }
2526  else
2527  {
2528  is.Take();
2529  return n;
2530  }
2531  }
2532 
2533  default:
2534  // This branch is for IterativeParsingValueState actually.
2535  // Use `default:` rather than
2536  // `case IterativeParsingValueState:` is for code coverage.
2537 
2538  // The IterativeParsingStartState is not enumerated in this switch-case.
2539  // It is impossible for that case. And it can be caught by following assertion.
2540 
2541  // The IterativeParsingFinishState is not enumerated in this switch-case either.
2542  // It is a "derivative" state which cannot triggered from Predict() directly.
2543  // Therefore it cannot happen here. And it can be caught by following assertion.
2544  RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
2545 
2546  // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2547  ParseValue<parseFlags>(is, handler);
2548  if (HasParseError())
2549  {
2550  return IterativeParsingErrorState;
2551  }
2552  return IterativeParsingFinishState;
2553  }
2554  }
2555 
2556  template <typename InputStream>
2557  void HandleError(IterativeParsingState src, InputStream& is)
2558  {
2559  if (HasParseError())
2560  {
2561  // Error flag has been set.
2562  return;
2563  }
2564 
2565  switch (src)
2566  {
2567  case IterativeParsingStartState:
2569  return;
2570  case IterativeParsingFinishState:
2572  return;
2573  case IterativeParsingObjectInitialState:
2574  case IterativeParsingMemberDelimiterState:
2576  return;
2577  case IterativeParsingMemberKeyState:
2579  return;
2580  case IterativeParsingMemberValueState:
2582  return;
2583  case IterativeParsingKeyValueDelimiterState:
2584  case IterativeParsingArrayInitialState:
2585  case IterativeParsingElementDelimiterState:
2587  return;
2588  default:
2589  RAPIDJSON_ASSERT(src == IterativeParsingElementState);
2591  return;
2592  }
2593  }
2594 
2595  RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) const
2596  {
2597  return s >= IterativeParsingElementDelimiterState;
2598  }
2599 
2600  RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) const
2601  {
2602  return s <= IterativeParsingErrorState;
2603  }
2604 
2605  template <unsigned parseFlags, typename InputStream, typename Handler>
2606  ParseResult IterativeParse(InputStream& is, Handler& handler)
2607  {
2608  parseResult_.Clear();
2609  ClearStackOnExit scope(*this);
2610  IterativeParsingState state = IterativeParsingStartState;
2611 
2612  SkipWhitespaceAndComments<parseFlags>(is);
2613  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
2614  while (is.Peek() != '\0')
2615  {
2616  Token t = Tokenize(is.Peek());
2617  IterativeParsingState n = Predict(state, t);
2618  IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
2619 
2620  if (d == IterativeParsingErrorState)
2621  {
2622  HandleError(state, is);
2623  break;
2624  }
2625 
2626  state = d;
2627 
2628  // Do not further consume streams if a root JSON has been parsed.
2629  if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
2630  break;
2631 
2632  SkipWhitespaceAndComments<parseFlags>(is);
2633  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
2634  }
2635 
2636  // Handle the end of file.
2637  if (state != IterativeParsingFinishState)
2638  HandleError(state, is);
2639 
2640  return parseResult_;
2641  }
2642 
2643  static const size_t kDefaultStackCapacity =
2644  256;
2646  ParseResult parseResult_;
2649 }; // class GenericReader
2650 
2653 
2655 
2656 #if defined(__clang__) || defined(_MSC_VER)
2657 RAPIDJSON_DIAG_POP
2658 #endif
2659 
2660 #if __GNUC__
2661 RAPIDJSON_DIAG_POP
2662 #endif
2663 
2664 #endif // RAPIDJSON_READER_H_
bool Default()
Definition: reader.h:208
bool RawNumber(const Ch *str, SizeType len, bool copy)
enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) ...
Definition: reader.h:241
d
RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream &is, OutputStream &os)
Definition: reader.h:1179
StreamLocalCopy(Stream &original)
Definition: reader.h:284
bool StartArray()
Definition: reader.h:261
Encoding conversion.
Definition: encodings.h:817
void HandleError(IterativeParsingState src, InputStream &is)
Definition: reader.h:2557
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text.
Definition: reader.h:665
void ClearStack()
Definition: reader.h:831
Invalid value.
Definition: error.h:71
Encoding::Ch Ch
Definition: reader.h:204
double StrtodFullPrecision(double d, int p, const char *decimals, size_t length, size_t decimalPosition, int exp)
Definition: strtod.h:249
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:394
Iterative(constant complexity in terms of function call stack size) parsing.
Definition: reader.h:152
Represents an in-memory input byte stream.
Definition: memorystream.h:42
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:416
Parsing was terminated.
Definition: error.h:89
Missing a comma or &#39;}&#39; after an object member.
Definition: error.h:75
#define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
Definition: rapidjson.h:294
RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) const
Definition: reader.h:2595
bool Int64(int64_t)
Definition: reader.h:228
Default implementation of Handler.
Definition: fwd.h:94
RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream &is, Handler &handler)
Definition: reader.h:2391
NumberStream(GenericReader &reader, InputStream &is)
Definition: reader.h:1709
Read-only string stream.
Definition: fwd.h:56
StackStream(internal::Stack< StackAllocator > &stack)
Definition: reader.h:1109
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:126
GenericReader< UTF8<>, UTF8<> > Reader
Reader with UTF8 encoding and default allocator.
Definition: reader.h:2652
The document is empty.
Definition: error.h:68
Missing a comma or &#39;]&#39; after an array element.
Definition: error.h:77
XmlRpcServer s
bool Uint64(uint64_t)
Definition: reader.h:232
bool EndObject(SizeType)
Definition: reader.h:257
bool Uint(unsigned)
Definition: reader.h:224
bool String(const Ch *, SizeType, bool)
Definition: reader.h:245
ParseErrorCode GetParseErrorCode() const
Get the ParseErrorCode of last parsing.
Definition: reader.h:809
const Ch * src_
Current read position.
Definition: stream.h:234
No flags are set.
Definition: reader.h:149
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text (with kParseDefaultFlags)
Definition: reader.h:711
bool EndArray(SizeType)
Definition: reader.h:265
bool StartObject()
Definition: reader.h:249
void SetParseError(ParseErrorCode code, size_t offset)
Definition: reader.h:821
void ParseString(InputStream &is, Handler &handler, bool isKey=false)
Definition: reader.h:1144
RAPIDJSON_FORCEINLINE void Put(Ch c)
Definition: reader.h:1112
Missing a name for object member.
Definition: error.h:73
Result of parsing (wraps ParseErrorCode)
Definition: error.h:107
Allow trailing commas at the end of objects and arrays.
Definition: reader.h:159
void ParseValue(InputStream &is, Handler &handler)
Definition: reader.h:2087
void ParseArray(InputStream &is, Handler &handler)
Definition: reader.h:966
NumberStream< InputStream, false, false > Base
Definition: reader.h:1706
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:121
bool Int(int)
Definition: reader.h:220
internal::SelectIf< internal::IsSame< Derived, void >, BaseReaderHandler, Derived >::Type Override
Definition: reader.h:206
#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:160
size_t Length() const
Definition: reader.h:1124
internal::Stack< StackAllocator > & stack_
Definition: reader.h:1138
A read-write string stream.
Definition: fwd.h:61
Number too big to be stored in double.
Definition: error.h:85
Parse all numbers (ints/doubles) as strings.
Definition: reader.h:158
NumberStream(GenericReader &reader, InputStream &s)
Definition: reader.h:1663
SourceEncoding::Ch Ch
SourceEncoding character type.
Definition: reader.h:644
unsigned ParseHex4(InputStream &is, size_t escapeOffset)
Definition: reader.h:1079
Parse number in full precision (but slower).
Definition: reader.h:156
UTF-8 encoding.
Definition: encodings.h:96
void ParseTrue(InputStream &is, Handler &handler)
Definition: reader.h:1036
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
Definition: fwd.h:97
bool HasParseError() const
Whether a parse error has occurred in the last parsing.
Definition: reader.h:803
double StrtodNormalPrecision(double d, int p)
Definition: strtod.h:38
bool Key(const Ch *str, SizeType len, bool copy)
Definition: reader.h:253
RAPIDJSON_FORCEINLINE void * Push(SizeType count)
Definition: reader.h:1118
RAPIDJSON_FORCEINLINE Ch Peek() const
Definition: reader.h:1668
ParseFlag
Combination of parseFlags.
Definition: reader.h:147
ParseErrorCode
Error code of parsing.
Definition: error.h:64
void SkipWhitespaceAndComments(InputStream &is)
Definition: reader.h:854
IterativeParsingState
Definition: reader.h:2118
#define RAPIDJSON_PARSE_DEFAULT_FLAGS
Definition: reader.h:141
unsigned __int64 uint64_t
Definition: stdint.h:136
IterativeParsingState state_
Definition: reader.h:2648
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:733
Miss exponent in number.
Definition: error.h:87
void ParseFalse(InputStream &is, Handler &handler)
Definition: reader.h:1051
Invalid escape character in string.
Definition: error.h:81
Invalid encoding in string.
Definition: error.h:83
void ParseNumber(InputStream &is, Handler &handler)
Definition: reader.h:1756
bool Bool(bool)
Definition: reader.h:216
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:482
RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) const
Definition: reader.h:2600
RAPIDJSON_FORCEINLINE void Push(char c)
Definition: reader.h:1719
void SkipWhitespace(InputStream &is)
Skip the JSON white spaces in a stream.
Definition: reader.h:325
#define Z16
void ParseObject(InputStream &is, Handler &handler)
Definition: reader.h:891
bool Double(double)
Definition: reader.h:236
Validate encoding of JSON strings.
Definition: reader.h:151
signed __int64 int64_t
Definition: stdint.h:135
Miss fraction part in number.
Definition: error.h:86
size_t GetErrorOffset() const
Get the position of last parsing error in input, 0 otherwise.
Definition: reader.h:815
internal::Stack< StackAllocator > stack_
Definition: reader.h:2645
Incorrect hex digit after \u escape in string.
Definition: error.h:79
#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:171
static RAPIDJSON_FORCEINLINE bool Consume(InputStream &is, typename InputStream::Ch expect)
Definition: reader.h:1066
Unspecific syntax error.
Definition: error.h:90
void IterativeParseInit()
Initialize JSON text token-by-token parsing.
Definition: reader.h:719
The surrogate pair in string is invalid.
Definition: error.h:80
void ParseNull(InputStream &is, Handler &handler)
Definition: reader.h:1021
Missing a colon after a name of object member.
Definition: error.h:74
ParseResult IterativeParse(InputStream &is, Handler &handler)
Definition: reader.h:2606
NumberStream< InputStream, true, false > Base
Definition: reader.h:1742
Type
Type of JSON value.
Definition: rapidjson.h:666
StreamLocalCopy(Stream &original)
Definition: reader.h:305
GenericReader(StackAllocator *stackAllocator=0, size_t stackCapacity=kDefaultStackCapacity)
Constructor.
Definition: reader.h:651
ClearStackOnExit(GenericReader &r)
Definition: reader.h:839
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:495
Missing a closing quotation mark in string.
Definition: error.h:82
static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream &, OutputStream &)
Definition: reader.h:1254
RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) const
Definition: reader.h:2167
NumberStream(GenericReader &reader, InputStream &is)
Definition: reader.h:1745
RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) const
Definition: reader.h:2232
The document root must not follow by other values.
Definition: error.h:69
In-situ(destructive) parsing.
Definition: reader.h:150
RAPIDJSON_FORCEINLINE bool IterativeParseComplete() const
Check if token-by-token parsing JSON text is complete.
Definition: reader.h:797
Allow one-line (//) and multi-line (/**/) comments.
Definition: reader.h:157


xbot_talker
Author(s): wangxiaoyun
autogenerated on Sat Oct 10 2020 03:27:53