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


livox_ros_driver
Author(s): Livox Dev Team
autogenerated on Mon Mar 15 2021 02:40:46