/home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-composable-kernel/checkouts/develop/include/rapidjson/reader.h Source File

/home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-composable-kernel/checkouts/develop/include/rapidjson/reader.h Source File#

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