RetroArch
reader.h
Go to the documentation of this file.
1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // http://opensource.org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #ifndef RAPIDJSON_READER_H_
16 #define RAPIDJSON_READER_H_
17 
20 #include "allocators.h"
21 #include "stream.h"
22 #include "encodedstream.h"
23 #include "internal/meta.h"
24 #include "internal/stack.h"
25 #include "internal/strtod.h"
26 #include <limits>
27 
28 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
29 #include <intrin.h>
30 #pragma intrinsic(_BitScanForward)
31 #endif
32 #ifdef RAPIDJSON_SSE42
33 #include <nmmintrin.h>
34 #elif defined(RAPIDJSON_SSE2)
35 #include <emmintrin.h>
36 #endif
37 
38 #ifdef _MSC_VER
39 RAPIDJSON_DIAG_PUSH
40 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
41 RAPIDJSON_DIAG_OFF(4702) // unreachable code
42 #endif
43 
44 #ifdef __clang__
45 RAPIDJSON_DIAG_PUSH
46 RAPIDJSON_DIAG_OFF(old-style-cast)
47 RAPIDJSON_DIAG_OFF(padded)
48 RAPIDJSON_DIAG_OFF(switch-enum)
49 #endif
50 
51 #ifdef __GNUC__
52 RAPIDJSON_DIAG_PUSH
53 RAPIDJSON_DIAG_OFF(effc++)
54 #endif
55 
57 #define RAPIDJSON_NOTHING /* deliberately empty */
58 #ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
59 #define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
60  RAPIDJSON_MULTILINEMACRO_BEGIN \
61  if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
62  RAPIDJSON_MULTILINEMACRO_END
63 #endif
64 #define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
65  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
66 
98 #ifndef RAPIDJSON_PARSE_ERROR_NORETURN
99 #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \
100  RAPIDJSON_MULTILINEMACRO_BEGIN \
101  RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
102  SetParseError(parseErrorCode, offset); \
103  RAPIDJSON_MULTILINEMACRO_END
104 #endif
105 
117 #ifndef RAPIDJSON_PARSE_ERROR
118 #define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \
119  RAPIDJSON_MULTILINEMACRO_BEGIN \
120  RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
121  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
122  RAPIDJSON_MULTILINEMACRO_END
123 #endif
124 
125 #include "error/error.h" // ParseErrorCode, ParseResult
126 
128 
130 // ParseFlag
131 
138 #ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS
139 #define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
140 #endif
141 
143 
145 enum ParseFlag {
157 };
158 
160 // Handler
161 
178 
188 // BaseReaderHandler
190 
192 
195 template<typename Encoding = UTF8<>, typename Derived = void>
196 struct BaseReaderHandler {
197  typedef typename Encoding::Ch Ch;
198 
199  typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;
200 
201  bool Default() { return true; }
202  bool Null() { return static_cast<Override&>(*this).Default(); }
203  bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
204  bool Int(int) { return static_cast<Override&>(*this).Default(); }
205  bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }
206  bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); }
207  bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); }
208  bool Double(double) { return static_cast<Override&>(*this).Default(); }
210  bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
211  bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); }
212  bool StartObject() { return static_cast<Override&>(*this).Default(); }
213  bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
214  bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }
215  bool StartArray() { return static_cast<Override&>(*this).Default(); }
216  bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
217 };
218 
220 // StreamLocalCopy
221 
222 namespace internal {
223 
224 template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
226 
228 template<typename Stream>
229 class StreamLocalCopy<Stream, 1> {
230 public:
231  StreamLocalCopy(Stream& original) : s(original), original_(original) {}
232  ~StreamLocalCopy() { original_ = s; }
233 
234  Stream s;
235 
236 private:
237  StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
238 
239  Stream& original_;
240 };
241 
243 template<typename Stream>
244 class StreamLocalCopy<Stream, 0> {
245 public:
246  StreamLocalCopy(Stream& original) : s(original) {}
247 
248  Stream& s;
249 
250 private:
251  StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
252 };
253 
254 } // namespace internal
255 
257 // SkipWhitespace
258 
260 
263 template<typename InputStream>
264 void SkipWhitespace(InputStream& is) {
266  InputStream& s(copy.s);
267 
268  typename InputStream::Ch c;
269  while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t')
270  s.Take();
271 }
272 
273 inline const char* SkipWhitespace(const char* p, const char* end) {
274  while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
275  ++p;
276  return p;
277 }
278 
279 #ifdef RAPIDJSON_SSE42
280 inline const char *SkipWhitespace_SIMD(const char* p) {
282  // Fast return for single non-whitespace
283  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
284  ++p;
285  else
286  return p;
287 
288  // 16-byte align to the next boundary
289  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
290  while (p != nextAligned)
291  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
292  ++p;
293  else
294  return p;
295 
296  // The rest of string using SIMD
297  static const char whitespace[16] = " \n\r\t";
298  const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
299 
300  for (;; p += 16) {
301  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
302  const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
303  if (r != 0) { // some of characters is non-whitespace
304 #ifdef _MSC_VER // Find the index of first non-whitespace
305  unsigned long offset;
306  _BitScanForward(&offset, r);
307  return p + offset;
308 #else
309  return p + __builtin_ffs(r) - 1;
310 #endif
311  }
312  }
313 }
314 
315 inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
316  // Fast return for single non-whitespace
317  if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
318  ++p;
319  else
320  return p;
321 
322  // The middle of string using SIMD
323  static const char whitespace[16] = " \n\r\t";
324  const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
325 
326  for (; p <= end - 16; p += 16) {
327  const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
328  const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
329  if (r != 0) { // some of characters is non-whitespace
330 #ifdef _MSC_VER // Find the index of first non-whitespace
331  unsigned long offset;
332  _BitScanForward(&offset, r);
333  return p + offset;
334 #else
335  return p + __builtin_ffs(r) - 1;
336 #endif
337  }
338  }
339 
340  return SkipWhitespace(p, end);
341 }
342 
343 #elif defined(RAPIDJSON_SSE2)
344 
346 inline const char *SkipWhitespace_SIMD(const char* p) {
347  // Fast return for single non-whitespace
348  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
349  ++p;
350  else
351  return p;
352 
353  // 16-byte align to the next boundary
354  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
355  while (p != nextAligned)
356  if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
357  ++p;
358  else
359  return p;
360 
361  // The rest of string
362  #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
363  static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
364  #undef C16
365 
366  const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
367  const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
368  const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
369  const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
370 
371  for (;; p += 16) {
372  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
373  __m128i x = _mm_cmpeq_epi8(s, w0);
374  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
375  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
376  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
377  unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
378  if (r != 0) { // some of characters may be non-whitespace
379 #ifdef _MSC_VER // Find the index of first non-whitespace
380  unsigned long offset;
381  _BitScanForward(&offset, r);
382  return p + offset;
383 #else
384  return p + __builtin_ffs(r) - 1;
385 #endif
386  }
387  }
388 }
389 
390 inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
391  // Fast return for single non-whitespace
392  if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
393  ++p;
394  else
395  return p;
396 
397  // The rest of string
398  #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
399  static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
400  #undef C16
401 
402  const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
403  const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
404  const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
405  const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
406 
407  for (; p <= end - 16; p += 16) {
408  const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
409  __m128i x = _mm_cmpeq_epi8(s, w0);
410  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
411  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
412  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
413  unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
414  if (r != 0) { // some of characters may be non-whitespace
415 #ifdef _MSC_VER // Find the index of first non-whitespace
416  unsigned long offset;
417  _BitScanForward(&offset, r);
418  return p + offset;
419 #else
420  return p + __builtin_ffs(r) - 1;
421 #endif
422  }
423  }
424 
425  return SkipWhitespace(p, end);
426 }
427 
428 #endif // RAPIDJSON_SSE2
429 
430 #ifdef RAPIDJSON_SIMD
431 template<> inline void SkipWhitespace(InsituStringStream& is) {
433  is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
434 }
435 
437 template<> inline void SkipWhitespace(StringStream& is) {
438  is.src_ = SkipWhitespace_SIMD(is.src_);
439 }
440 
441 template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
442  is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
443 }
444 #endif // RAPIDJSON_SIMD
445 
447 // GenericReader
448 
450 
465 template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
466 class GenericReader {
467 public:
468  typedef typename SourceEncoding::Ch Ch;
469 
471 
474  GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
475 
477 
484  template <unsigned parseFlags, typename InputStream, typename Handler>
485  ParseResult Parse(InputStream& is, Handler& handler) {
486  if (parseFlags & kParseIterativeFlag)
487  return IterativeParse<parseFlags>(is, handler);
488 
490 
491  ClearStackOnExit scope(*this);
492 
493  SkipWhitespaceAndComments<parseFlags>(is);
494  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
495 
496  if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) {
498  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
499  }
500  else {
501  ParseValue<parseFlags>(is, handler);
502  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
503 
504  if (!(parseFlags & kParseStopWhenDoneFlag)) {
505  SkipWhitespaceAndComments<parseFlags>(is);
506  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
507 
508  if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) {
510  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
511  }
512  }
513  }
514 
515  return parseResult_;
516  }
517 
519 
525  template <typename InputStream, typename Handler>
526  ParseResult Parse(InputStream& is, Handler& handler) {
527  return Parse<kParseDefaultFlags>(is, handler);
528  }
529 
531  bool HasParseError() const { return parseResult_.IsError(); }
532 
535 
537  size_t GetErrorOffset() const { return parseResult_.Offset(); }
538 
539 protected:
541 
542 private:
543  // Prohibit copy constructor & assignment operator.
546 
547  void ClearStack() { stack_.Clear(); }
548 
549  // clear stack on any exit from ParseStream, e.g. due to exception
553  private:
557  };
558 
559  template<unsigned parseFlags, typename InputStream>
560  void SkipWhitespaceAndComments(InputStream& is) {
561  SkipWhitespace(is);
562 
563  if (parseFlags & kParseCommentsFlag) {
564  while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) {
565  if (Consume(is, '*')) {
566  while (true) {
567  if (RAPIDJSON_UNLIKELY(is.Peek() == '\0'))
569  else if (Consume(is, '*')) {
570  if (Consume(is, '/'))
571  break;
572  }
573  else
574  is.Take();
575  }
576  }
577  else if (RAPIDJSON_LIKELY(Consume(is, '/')))
578  while (is.Peek() != '\0' && is.Take() != '\n');
579  else
581 
582  SkipWhitespace(is);
583  }
584  }
585  }
586 
587  // Parse object: { string : value, ... }
588  template<unsigned parseFlags, typename InputStream, typename Handler>
589  void ParseObject(InputStream& is, Handler& handler) {
590  RAPIDJSON_ASSERT(is.Peek() == '{');
591  is.Take(); // Skip '{'
592 
593  if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
595 
596  SkipWhitespaceAndComments<parseFlags>(is);
597  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
598 
599  if (Consume(is, '}')) {
600  if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object
602  return;
603  }
604 
605  for (SizeType memberCount = 0;;) {
606  if (RAPIDJSON_UNLIKELY(is.Peek() != '"'))
608 
609  ParseString<parseFlags>(is, handler, true);
610  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
611 
612  SkipWhitespaceAndComments<parseFlags>(is);
613  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
614 
615  if (RAPIDJSON_UNLIKELY(!Consume(is, ':')))
617 
618  SkipWhitespaceAndComments<parseFlags>(is);
619  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
620 
621  ParseValue<parseFlags>(is, handler);
622  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
623 
624  SkipWhitespaceAndComments<parseFlags>(is);
625  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
626 
627  ++memberCount;
628 
629  switch (is.Peek()) {
630  case ',':
631  is.Take();
632  SkipWhitespaceAndComments<parseFlags>(is);
633  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
634  break;
635  case '}':
636  is.Take();
637  if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
639  return;
640  default:
641  RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy
642  }
643 
644  if (parseFlags & kParseTrailingCommasFlag) {
645  if (is.Peek() == '}') {
646  if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
648  is.Take();
649  return;
650  }
651  }
652  }
653  }
654 
655  // Parse array: [ value, ... ]
656  template<unsigned parseFlags, typename InputStream, typename Handler>
657  void ParseArray(InputStream& is, Handler& handler) {
658  RAPIDJSON_ASSERT(is.Peek() == '[');
659  is.Take(); // Skip '['
660 
661  if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
663 
664  SkipWhitespaceAndComments<parseFlags>(is);
665  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
666 
667  if (Consume(is, ']')) {
668  if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array
670  return;
671  }
672 
673  for (SizeType elementCount = 0;;) {
674  ParseValue<parseFlags>(is, handler);
675  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
676 
677  ++elementCount;
678  SkipWhitespaceAndComments<parseFlags>(is);
679  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
680 
681  if (Consume(is, ',')) {
682  SkipWhitespaceAndComments<parseFlags>(is);
683  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
684  }
685  else if (Consume(is, ']')) {
686  if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
688  return;
689  }
690  else
692 
693  if (parseFlags & kParseTrailingCommasFlag) {
694  if (is.Peek() == ']') {
695  if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
697  is.Take();
698  return;
699  }
700  }
701  }
702  }
703 
704  template<unsigned parseFlags, typename InputStream, typename Handler>
705  void ParseNull(InputStream& is, Handler& handler) {
706  RAPIDJSON_ASSERT(is.Peek() == 'n');
707  is.Take();
708 
709  if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) {
710  if (RAPIDJSON_UNLIKELY(!handler.Null()))
712  }
713  else
715  }
716 
717  template<unsigned parseFlags, typename InputStream, typename Handler>
718  void ParseTrue(InputStream& is, Handler& handler) {
719  RAPIDJSON_ASSERT(is.Peek() == 't');
720  is.Take();
721 
722  if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) {
723  if (RAPIDJSON_UNLIKELY(!handler.Bool(true)))
725  }
726  else
728  }
729 
730  template<unsigned parseFlags, typename InputStream, typename Handler>
731  void ParseFalse(InputStream& is, Handler& handler) {
732  RAPIDJSON_ASSERT(is.Peek() == 'f');
733  is.Take();
734 
735  if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) {
736  if (RAPIDJSON_UNLIKELY(!handler.Bool(false)))
738  }
739  else
741  }
742 
743  template<typename InputStream>
744  RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
745  if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
746  is.Take();
747  return true;
748  }
749  else
750  return false;
751  }
752 
753  // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
754  template<typename InputStream>
755  unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
756  unsigned codepoint = 0;
757  for (int i = 0; i < 4; i++) {
758  Ch c = is.Peek();
759  codepoint <<= 4;
760  codepoint += static_cast<unsigned>(c);
761  if (c >= '0' && c <= '9')
762  codepoint -= '0';
763  else if (c >= 'A' && c <= 'F')
764  codepoint -= 'A' - 10;
765  else if (c >= 'a' && c <= 'f')
766  codepoint -= 'a' - 10;
767  else {
769  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
770  }
771  is.Take();
772  }
773  return codepoint;
774  }
775 
776  template <typename CharType>
777  class StackStream {
778  public:
779  typedef CharType Ch;
780 
782  RAPIDJSON_FORCEINLINE void Put(Ch c) {
783  *stack_.template Push<Ch>() = c;
784  ++length_;
785  }
786 
787  RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
788  length_ += count;
789  return stack_.template Push<Ch>(count);
790  }
791 
792  size_t Length() const { return length_; }
793 
794  Ch* Pop() {
795  return stack_.template Pop<Ch>(length_);
796  }
797 
798  private:
799  StackStream(const StackStream&);
801 
804  };
805 
806  // Parse string and generate String event. Different code paths for kParseInsituFlag.
807  template<unsigned parseFlags, typename InputStream, typename Handler>
808  void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
810  InputStream& s(copy.s);
811 
812  RAPIDJSON_ASSERT(s.Peek() == '\"');
813  s.Take(); // Skip '\"'
814 
815  bool success = false;
816  if (parseFlags & kParseInsituFlag) {
817  typename InputStream::Ch *head = s.PutBegin();
818  ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
819  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
820  size_t length = s.PutEnd(head) - 1;
821  RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
822  const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
823  success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
824  }
825  else {
827  ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
828  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
829  SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
830  const typename TargetEncoding::Ch* const str = stackStream.Pop();
831  success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
832  }
835  }
836 
837  // Parse string to an output is
838  // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
839  template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
840  RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
842 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
843  static const char escape[256] = {
844  Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
845  Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
846  0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
847  0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
848  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
849  };
850 #undef Z16
851 
853  for (;;) {
854  // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
855  if (!(parseFlags & kParseValidateEncodingFlag))
856  ScanCopyUnescapedString(is, os);
857 
858  Ch c = is.Peek();
859  if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape
860  size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset
861  is.Take();
862  Ch e = is.Peek();
863  if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
864  is.Take();
865  os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
866  }
867  else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode
868  is.Take();
869  unsigned codepoint = ParseHex4(is, escapeOffset);
870  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
871  if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) {
872  // Handle UTF-16 surrogate pair
873  if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
875  unsigned codepoint2 = ParseHex4(is, escapeOffset);
876  RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
877  if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
879  codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
880  }
881  TEncoding::Encode(os, codepoint);
882  }
883  else
885  }
886  else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote
887  is.Take();
888  os.Put('\0'); // null-terminate the string
889  return;
890  }
891  else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
892  if (c == '\0')
894  else
896  }
897  else {
898  size_t offset = is.Tell();
903  }
904  }
905  }
906 
907  template<typename InputStream, typename OutputStream>
908  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
909  // Do nothing for generic version
910  }
911 
912 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
913  // StringStream -> StackStream<char>
914  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
915  const char* p = is.src_;
916 
917  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
918  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
919  while (p != nextAligned)
920  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
921  is.src_ = p;
922  return;
923  }
924  else
925  os.Put(*p++);
926 
927  // The rest of string using SIMD
928  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
929  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
930  static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
931  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
932  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
933  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
934 
935  for (;; p += 16) {
936  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
937  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
938  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
939  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
940  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
941  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
942  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
944  #ifdef _MSC_VER // Find the index of first escaped
945  unsigned long offset;
946  _BitScanForward(&offset, r);
947  length = offset;
948  #else
949  length = static_cast<SizeType>(__builtin_ffs(r) - 1);
950  #endif
951  char* q = reinterpret_cast<char*>(os.Push(length));
952  for (size_t i = 0; i < length; i++)
953  q[i] = p[i];
954 
955  p += length;
956  break;
957  }
958  _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
959  }
960 
961  is.src_ = p;
962  }
963 
964  // InsituStringStream -> InsituStringStream
965  static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
966  RAPIDJSON_ASSERT(&is == &os);
967  (void)os;
968 
969  if (is.src_ == is.dst_) {
970  SkipUnescapedString(is);
971  return;
972  }
973 
974  char* p = is.src_;
975  char *q = is.dst_;
976 
977  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
978  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
979  while (p != nextAligned)
980  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
981  is.src_ = p;
982  is.dst_ = q;
983  return;
984  }
985  else
986  *q++ = *p++;
987 
988  // The rest of string using SIMD
989  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
990  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
991  static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
992  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
993  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
994  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
995 
996  for (;; p += 16, q += 16) {
997  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
998  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
999  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1000  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
1001  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1002  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1003  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
1004  size_t length;
1005 #ifdef _MSC_VER // Find the index of first escaped
1006  unsigned long offset;
1007  _BitScanForward(&offset, r);
1008  length = offset;
1009 #else
1010  length = static_cast<size_t>(__builtin_ffs(r) - 1);
1011 #endif
1012  for (const char* pend = p + length; p != pend; )
1013  *q++ = *p++;
1014  break;
1015  }
1016  _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s);
1017  }
1018 
1019  is.src_ = p;
1020  is.dst_ = q;
1021  }
1022 
1023  // When read/write pointers are the same for insitu stream, just skip unescaped characters
1024  static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
1025  RAPIDJSON_ASSERT(is.src_ == is.dst_);
1026  char* p = is.src_;
1027 
1028  // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1029  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1030  for (; p != nextAligned; p++)
1031  if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1032  is.src_ = is.dst_ = p;
1033  return;
1034  }
1035 
1036  // The rest of string using SIMD
1037  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1038  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1039  static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
1040  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
1041  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
1042  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
1043 
1044  for (;; p += 16) {
1045  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
1046  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1047  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1048  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
1049  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1050  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1051  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
1052  size_t length;
1053 #ifdef _MSC_VER // Find the index of first escaped
1054  unsigned long offset;
1055  _BitScanForward(&offset, r);
1056  length = offset;
1057 #else
1058  length = static_cast<size_t>(__builtin_ffs(r) - 1);
1059 #endif
1060  p += length;
1061  break;
1062  }
1063  }
1064 
1065  is.src_ = is.dst_ = p;
1066  }
1067 #endif
1068 
1069  template<typename InputStream, bool backup, bool pushOnTake>
1071 
1072  template<typename InputStream>
1073  class NumberStream<InputStream, false, false> {
1074  public:
1075  typedef typename InputStream::Ch Ch;
1076 
1077  NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
1079 
1080  RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
1081  RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
1082  RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
1083  RAPIDJSON_FORCEINLINE void Push(char) {}
1084 
1085  size_t Tell() { return is.Tell(); }
1086  size_t Length() { return 0; }
1087  const char* Pop() { return 0; }
1088 
1089  protected:
1091 
1092  InputStream& is;
1093  };
1094 
1095  template<typename InputStream>
1096  class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
1098  public:
1099  NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
1101 
1102  RAPIDJSON_FORCEINLINE Ch TakePush() {
1103  stackStream.Put(static_cast<char>(Base::is.Peek()));
1104  return Base::is.Take();
1105  }
1106 
1107  RAPIDJSON_FORCEINLINE void Push(char c) {
1108  stackStream.Put(c);
1109  }
1110 
1111  size_t Length() { return stackStream.Length(); }
1112 
1113  const char* Pop() {
1114  stackStream.Put('\0');
1115  return stackStream.Pop();
1116  }
1117 
1118  private:
1120  };
1121 
1122  template<typename InputStream>
1123  class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
1125  public:
1126  NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
1128 
1129  RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
1130  };
1131 
1132  template<unsigned parseFlags, typename InputStream, typename Handler>
1133  void ParseNumber(InputStream& is, Handler& handler) {
1135  NumberStream<InputStream,
1136  ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
1137  ((parseFlags & kParseInsituFlag) == 0) :
1138  ((parseFlags & kParseFullPrecisionFlag) != 0),
1139  (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
1140  (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
1141 
1142  size_t startOffset = s.Tell();
1143  double d = 0.0;
1144  bool useNanOrInf = false;
1145 
1146  // Parse minus
1147  bool minus = Consume(s, '-');
1148 
1149  // Parse int: zero / ( digit1-9 *DIGIT )
1150  unsigned i = 0;
1151  uint64_t i64 = 0;
1152  bool use64bit = false;
1153  int significandDigit = 0;
1154  if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) {
1155  i = 0;
1156  s.TakePush();
1157  }
1158  else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) {
1159  i = static_cast<unsigned>(s.TakePush() - '0');
1160 
1161  if (minus)
1162  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1163  if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648
1164  if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) {
1165  i64 = i;
1166  use64bit = true;
1167  break;
1168  }
1169  }
1170  i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
1171  significandDigit++;
1172  }
1173  else
1174  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1175  if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295
1176  if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {
1177  i64 = i;
1178  use64bit = true;
1179  break;
1180  }
1181  }
1182  i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
1183  significandDigit++;
1184  }
1185  }
1186  // Parse NaN or Infinity here
1187  else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
1188  useNanOrInf = true;
1189  if (RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) {
1190  d = std::numeric_limits<double>::quiet_NaN();
1191  }
1192  else if (RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) {
1193  d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
1194  if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
1195  && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y'))))
1197  }
1198  else
1200  }
1201  else
1203 
1204  // Parse 64bit int
1205  bool useDouble = false;
1206  if (use64bit) {
1207  if (minus)
1208  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1209  if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
1210  if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
1211  d = static_cast<double>(i64);
1212  useDouble = true;
1213  break;
1214  }
1215  i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1216  significandDigit++;
1217  }
1218  else
1219  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1220  if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615
1221  if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {
1222  d = static_cast<double>(i64);
1223  useDouble = true;
1224  break;
1225  }
1226  i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1227  significandDigit++;
1228  }
1229  }
1230 
1231  // Force double for big integer
1232  if (useDouble) {
1233  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1234  if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0
1236  d = d * 10 + (s.TakePush() - '0');
1237  }
1238  }
1239 
1240  // Parse frac = decimal-point 1*DIGIT
1241  int expFrac = 0;
1242  size_t decimalPosition;
1243  if (Consume(s, '.')) {
1244  decimalPosition = s.Length();
1245 
1246  if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
1248 
1249  if (!useDouble) {
1250 #if RAPIDJSON_64BIT
1251  // Use i64 to store significand in 64-bit architecture
1252  if (!use64bit)
1253  i64 = i;
1254 
1255  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1256  if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
1257  break;
1258  else {
1259  i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1260  --expFrac;
1261  if (i64 != 0)
1262  significandDigit++;
1263  }
1264  }
1265 
1266  d = static_cast<double>(i64);
1267 #else
1268  // Use double to store significand in 32-bit architecture
1269  d = static_cast<double>(use64bit ? i64 : i);
1270 #endif
1271  useDouble = true;
1272  }
1273 
1274  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1275  if (significandDigit < 17) {
1276  d = d * 10.0 + (s.TakePush() - '0');
1277  --expFrac;
1278  if (RAPIDJSON_LIKELY(d > 0.0))
1279  significandDigit++;
1280  }
1281  else
1282  s.TakePush();
1283  }
1284  }
1285  else
1286  decimalPosition = s.Length(); // decimal position at the end of integer.
1287 
1288  // Parse exp = e [ minus / plus ] 1*DIGIT
1289  int exp = 0;
1290  if (Consume(s, 'e') || Consume(s, 'E')) {
1291  if (!useDouble) {
1292  d = static_cast<double>(use64bit ? i64 : i);
1293  useDouble = true;
1294  }
1295 
1296  bool expMinus = false;
1297  if (Consume(s, '+'))
1298  ;
1299  else if (Consume(s, '-'))
1300  expMinus = true;
1301 
1302  if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1303  exp = static_cast<int>(s.Take() - '0');
1304  if (expMinus) {
1305  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1306  exp = exp * 10 + static_cast<int>(s.Take() - '0');
1307  if (exp >= 214748364) { // Issue #313: prevent overflow exponent
1308  while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent
1309  s.Take();
1310  }
1311  }
1312  }
1313  else { // positive exp
1314  int maxExp = 308 - expFrac;
1315  while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1316  exp = exp * 10 + static_cast<int>(s.Take() - '0');
1317  if (RAPIDJSON_UNLIKELY(exp > maxExp))
1319  }
1320  }
1321  }
1322  else
1324 
1325  if (expMinus)
1326  exp = -exp;
1327  }
1328 
1329  // Finish parsing, call event according to the type of number.
1330  bool cont = true;
1331 
1332  if (parseFlags & kParseNumbersAsStringsFlag) {
1333  if (parseFlags & kParseInsituFlag) {
1334  s.Pop(); // Pop stack no matter if it will be used or not.
1335  typename InputStream::Ch* head = is.PutBegin();
1336  const size_t length = s.Tell() - startOffset;
1337  RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
1338  // unable to insert the \0 character here, it will erase the comma after this number
1339  const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
1340  cont = handler.RawNumber(str, SizeType(length), false);
1341  }
1342  else {
1343  SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
1344  StringStream srcStream(s.Pop());
1346  while (numCharsToCopy--) {
1347  Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);
1348  }
1349  dstStream.Put('\0');
1350  const typename TargetEncoding::Ch* str = dstStream.Pop();
1351  const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;
1352  cont = handler.RawNumber(str, SizeType(length), true);
1353  }
1354  }
1355  else {
1356  size_t length = s.Length();
1357  const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
1358 
1359  if (useDouble) {
1360  int p = exp + expFrac;
1361  if (parseFlags & kParseFullPrecisionFlag)
1362  d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
1363  else
1365 
1366  cont = handler.Double(minus ? -d : d);
1367  }
1368  else if (useNanOrInf) {
1369  cont = handler.Double(d);
1370  }
1371  else {
1372  if (use64bit) {
1373  if (minus)
1374  cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
1375  else
1376  cont = handler.Uint64(i64);
1377  }
1378  else {
1379  if (minus)
1380  cont = handler.Int(static_cast<int32_t>(~i + 1));
1381  else
1382  cont = handler.Uint(i);
1383  }
1384  }
1385  }
1386  if (RAPIDJSON_UNLIKELY(!cont))
1388  }
1389 
1390  // Parse any JSON value
1391  template<unsigned parseFlags, typename InputStream, typename Handler>
1392  void ParseValue(InputStream& is, Handler& handler) {
1393  switch (is.Peek()) {
1394  case 'n': ParseNull <parseFlags>(is, handler); break;
1395  case 't': ParseTrue <parseFlags>(is, handler); break;
1396  case 'f': ParseFalse <parseFlags>(is, handler); break;
1397  case '"': ParseString<parseFlags>(is, handler); break;
1398  case '{': ParseObject<parseFlags>(is, handler); break;
1399  case '[': ParseArray <parseFlags>(is, handler); break;
1400  default :
1401  ParseNumber<parseFlags>(is, handler);
1402  break;
1403 
1404  }
1405  }
1406 
1407  // Iterative Parsing
1408 
1409  // States
1414 
1415  // Object states
1422 
1423  // Array states
1428 
1429  // Single value state
1431  };
1432 
1434 
1435  // Tokens
1436  enum Token {
1439 
1442 
1445 
1451 
1453  };
1454 
1455  RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
1456 
1458 #define N NumberToken
1459 #define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
1460  // Maps from ASCII to Token
1461  static const unsigned char tokenMap[256] = {
1462  N16, // 00~0F
1463  N16, // 10~1F
1464  N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
1465  N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
1466  N16, // 40~4F
1467  N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
1468  N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
1469  N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
1470  N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
1471  };
1472 #undef N
1473 #undef N16
1474 
1476  if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
1477  return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
1478  else
1479  return NumberToken;
1480  }
1481 
1483  // current state x one lookahead token -> new state
1484  static const char G[cIterativeParsingStateCount][kTokenCount] = {
1485  // Start
1486  {
1487  IterativeParsingArrayInitialState, // Left bracket
1488  IterativeParsingErrorState, // Right bracket
1489  IterativeParsingObjectInitialState, // Left curly bracket
1490  IterativeParsingErrorState, // Right curly bracket
1491  IterativeParsingErrorState, // Comma
1492  IterativeParsingErrorState, // Colon
1493  IterativeParsingValueState, // String
1494  IterativeParsingValueState, // False
1497  IterativeParsingValueState // Number
1498  },
1499  // Finish(sink state)
1500  {
1504  },
1505  // Error(sink state)
1506  {
1510  },
1511  // ObjectInitial
1512  {
1513  IterativeParsingErrorState, // Left bracket
1514  IterativeParsingErrorState, // Right bracket
1515  IterativeParsingErrorState, // Left curly bracket
1516  IterativeParsingObjectFinishState, // Right curly bracket
1517  IterativeParsingErrorState, // Comma
1518  IterativeParsingErrorState, // Colon
1520  IterativeParsingErrorState, // False
1523  IterativeParsingErrorState // Number
1524  },
1525  // MemberKey
1526  {
1527  IterativeParsingErrorState, // Left bracket
1528  IterativeParsingErrorState, // Right bracket
1529  IterativeParsingErrorState, // Left curly bracket
1530  IterativeParsingErrorState, // Right curly bracket
1531  IterativeParsingErrorState, // Comma
1533  IterativeParsingErrorState, // String
1534  IterativeParsingErrorState, // False
1537  IterativeParsingErrorState // Number
1538  },
1539  // KeyValueDelimiter
1540  {
1541  IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
1542  IterativeParsingErrorState, // Right bracket
1543  IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
1544  IterativeParsingErrorState, // Right curly bracket
1545  IterativeParsingErrorState, // Comma
1546  IterativeParsingErrorState, // Colon
1552  },
1553  // MemberValue
1554  {
1555  IterativeParsingErrorState, // Left bracket
1556  IterativeParsingErrorState, // Right bracket
1557  IterativeParsingErrorState, // Left curly bracket
1558  IterativeParsingObjectFinishState, // Right curly bracket
1560  IterativeParsingErrorState, // Colon
1561  IterativeParsingErrorState, // String
1562  IterativeParsingErrorState, // False
1565  IterativeParsingErrorState // Number
1566  },
1567  // MemberDelimiter
1568  {
1569  IterativeParsingErrorState, // Left bracket
1570  IterativeParsingErrorState, // Right bracket
1571  IterativeParsingErrorState, // Left curly bracket
1572  IterativeParsingObjectFinishState, // Right curly bracket
1573  IterativeParsingErrorState, // Comma
1574  IterativeParsingErrorState, // Colon
1576  IterativeParsingErrorState, // False
1579  IterativeParsingErrorState // Number
1580  },
1581  // ObjectFinish(sink state)
1582  {
1586  },
1587  // ArrayInitial
1588  {
1589  IterativeParsingArrayInitialState, // Left bracket(push Element state)
1590  IterativeParsingArrayFinishState, // Right bracket
1591  IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
1592  IterativeParsingErrorState, // Right curly bracket
1593  IterativeParsingErrorState, // Comma
1594  IterativeParsingErrorState, // Colon
1595  IterativeParsingElementState, // String
1600  },
1601  // Element
1602  {
1603  IterativeParsingErrorState, // Left bracket
1604  IterativeParsingArrayFinishState, // Right bracket
1605  IterativeParsingErrorState, // Left curly bracket
1606  IterativeParsingErrorState, // Right curly bracket
1608  IterativeParsingErrorState, // Colon
1609  IterativeParsingErrorState, // String
1610  IterativeParsingErrorState, // False
1613  IterativeParsingErrorState // Number
1614  },
1615  // ElementDelimiter
1616  {
1617  IterativeParsingArrayInitialState, // Left bracket(push Element state)
1618  IterativeParsingArrayFinishState, // Right bracket
1619  IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
1620  IterativeParsingErrorState, // Right curly bracket
1621  IterativeParsingErrorState, // Comma
1622  IterativeParsingErrorState, // Colon
1623  IterativeParsingElementState, // String
1628  },
1629  // ArrayFinish(sink state)
1630  {
1634  },
1635  // Single Value (sink state)
1636  {
1640  }
1641  }; // End of G
1642 
1643  return static_cast<IterativeParsingState>(G[state][token]);
1644  }
1645 
1646  // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
1647  // May return a new state on state pop.
1648  template <unsigned parseFlags, typename InputStream, typename Handler>
1649  RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
1650  (void)token;
1651 
1652  switch (dst) {
1654  return dst;
1655 
1658  {
1659  // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
1660  // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
1666  // Push current state.
1667  *stack_.template Push<SizeType>(1) = n;
1668  // Initialize and push the member/element count.
1669  *stack_.template Push<SizeType>(1) = 0;
1670  // Call handler
1671  bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
1672  // On handler short circuits the parsing.
1673  if (!hr) {
1676  }
1677  else {
1678  is.Take();
1679  return dst;
1680  }
1681  }
1682 
1684  ParseString<parseFlags>(is, handler, true);
1685  if (HasParseError())
1687  else
1688  return dst;
1689 
1691  RAPIDJSON_ASSERT(token == ColonToken);
1692  is.Take();
1693  return dst;
1694 
1696  // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
1697  ParseValue<parseFlags>(is, handler);
1698  if (HasParseError()) {
1700  }
1701  return dst;
1702 
1704  // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
1705  ParseValue<parseFlags>(is, handler);
1706  if (HasParseError()) {
1708  }
1709  return dst;
1710 
1713  is.Take();
1714  // Update member/element count.
1715  *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
1716  return dst;
1717 
1719  {
1720  // Transit from delimiter is only allowed when trailing commas are enabled
1724  }
1725  // Get member count.
1726  SizeType c = *stack_.template Pop<SizeType>(1);
1727  // If the object is not empty, count the last member.
1729  ++c;
1730  // Restore the state.
1731  IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
1732  // Transit to Finish state if this is the topmost scope.
1735  // Call handler
1736  bool hr = handler.EndObject(c);
1737  // On handler short circuits the parsing.
1738  if (!hr) {
1741  }
1742  else {
1743  is.Take();
1744  return n;
1745  }
1746  }
1747 
1749  {
1750  // Transit from delimiter is only allowed when trailing commas are enabled
1754  }
1755  // Get element count.
1756  SizeType c = *stack_.template Pop<SizeType>(1);
1757  // If the array is not empty, count the last element.
1759  ++c;
1760  // Restore the state.
1761  IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
1762  // Transit to Finish state if this is the topmost scope.
1765  // Call handler
1766  bool hr = handler.EndArray(c);
1767  // On handler short circuits the parsing.
1768  if (!hr) {
1771  }
1772  else {
1773  is.Take();
1774  return n;
1775  }
1776  }
1777 
1778  default:
1779  // This branch is for IterativeParsingValueState actually.
1780  // Use `default:` rather than
1781  // `case IterativeParsingValueState:` is for code coverage.
1782 
1783  // The IterativeParsingStartState is not enumerated in this switch-case.
1784  // It is impossible for that case. And it can be caught by following assertion.
1785 
1786  // The IterativeParsingFinishState is not enumerated in this switch-case either.
1787  // It is a "derivative" state which cannot triggered from Predict() directly.
1788  // Therefore it cannot happen here. And it can be caught by following assertion.
1790 
1791  // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
1792  ParseValue<parseFlags>(is, handler);
1793  if (HasParseError()) {
1795  }
1797  }
1798  }
1799 
1800  template <typename InputStream>
1801  void HandleError(IterativeParsingState src, InputStream& is) {
1802  if (HasParseError()) {
1803  // Error flag has been set.
1804  return;
1805  }
1806 
1807  switch (src) {
1818  }
1819  }
1820 
1821  template <unsigned parseFlags, typename InputStream, typename Handler>
1822  ParseResult IterativeParse(InputStream& is, Handler& handler) {
1823  parseResult_.Clear();
1824  ClearStackOnExit scope(*this);
1826 
1827  SkipWhitespaceAndComments<parseFlags>(is);
1828  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
1829  while (is.Peek() != '\0') {
1830  Token t = Tokenize(is.Peek());
1832  IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
1833 
1834  if (d == IterativeParsingErrorState) {
1835  HandleError(state, is);
1836  break;
1837  }
1838 
1839  state = d;
1840 
1841  // Do not further consume streams if a root JSON has been parsed.
1842  if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
1843  break;
1844 
1845  SkipWhitespaceAndComments<parseFlags>(is);
1846  RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
1847  }
1848 
1849  // Handle the end of file.
1851  HandleError(state, is);
1852 
1853  return parseResult_;
1854  }
1855 
1856  static const size_t kDefaultStackCapacity = 256;
1859 }; // class GenericReader
1860 
1863 
1865 
1866 #ifdef __clang__
1867 RAPIDJSON_DIAG_POP
1868 #endif
1869 
1870 
1871 #ifdef __GNUC__
1872 RAPIDJSON_DIAG_POP
1873 #endif
1874 
1875 #ifdef _MSC_VER
1876 RAPIDJSON_DIAG_POP
1877 #endif
1878 
1879 #endif // RAPIDJSON_READER_H_
Definition: llex.h:50
Parsing was terminated.
Definition: error.h:88
RAPIDJSON_FORCEINLINE Ch Take()
Definition: reader.h:1129
Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS.
Definition: reader.h:156
double StrtodFullPrecision(double d, int p, const char *decimals, size_t length, size_t decimalPosition, int exp)
Definition: strtod.h:224
RAPIDJSON_FORCEINLINE Ch Peek() const
Definition: reader.h:1080
Ch Peek()
Definition: stream.h:150
void ParseString(InputStream &is, Handler &handler, bool isKey=false)
Definition: reader.h:808
InputStream::Ch Ch
Definition: reader.h:1075
Definition: reader.h:550
Definition: reader.h:1452
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text.
Definition: reader.h:485
NumberStream(GenericReader &reader, InputStream &is)
Definition: reader.h:1099
Encoding::Ch Ch
Definition: reader.h:197
Missing a closing quotation mark in string.
Definition: error.h:81
NumberStream< InputStream, false, false > Base
Definition: reader.h:1097
internal::Stack< StackAllocator > stack_
A stack for storing decoded string temporarily during non-destructive parsing.
Definition: reader.h:1857
#define G(L)
Definition: lstate.h:205
RAPIDJSON_FORCEINLINE Token Tokenize(Ch c)
Definition: reader.h:1455
bool minus
Definition: connect_wiiupro.c:41
static const char * reader(lua_State *L, void *ud, size_t *size)
Definition: luac.c:122
Invalid value.
Definition: error.h:70
Definition: reader.h:1447
static int codepoint(lua_State *L)
Definition: lutf8lib.c:100
bool Null()
Definition: reader.h:202
void ParseNull(InputStream &is, Handler &handler)
Definition: reader.h:705
Invalid escape character in string.
Definition: error.h:80
Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
Definition: reader.h:155
bool HasParseError() const
Whether a parse error has occured in the last parsing.
Definition: reader.h:531
GLdouble GLdouble GLdouble r
Definition: glext.h:6406
A read-write string stream.
Definition: fwd.h:52
GLdouble GLdouble t
Definition: glext.h:6398
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:455
Represents an in-memory input byte stream.
Definition: memorystream.h:40
GLenum GLsizei len
Definition: glext.h:7389
In-situ(destructive) parsing.
Definition: reader.h:147
Encoding conversion.
Definition: encodings.h:658
StackStream & operator=(const StackStream &)
#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset)
Macro to indicate a parse error.
Definition: reader.h:99
bool Uint(unsigned)
Definition: reader.h:205
const Ch * src_
Current read position.
Definition: stream.h:124
GLdouble s
Definition: glext.h:6390
#define cast(t, exp)
Definition: llimits.h:111
RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token)
Definition: reader.h:1482
Definition: reader.h:1450
static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream &, OutputStream &)
Definition: reader.h:908
RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream &is, OutputStream &os)
Definition: reader.h:840
Allow one-line (//) and multi-line (/**/) comments.
Definition: reader.h:152
typedef void(__stdcall *PFN_DESTRUCTION_CALLBACK)(void *pData)
void HandleError(IterativeParsingState src, InputStream &is)
Definition: reader.h:1801
#define exp(a)
Definition: math.h:32
SizeType length_
Definition: reader.h:803
After parsing a complete JSON root from stream, stop further processing the rest of stream....
Definition: reader.h:150
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:119
Read-only string stream.
Definition: fwd.h:47
Incorrect hex digit after \u escape in string.
Definition: error.h:78
bool success(size_t len)
Definition: peglib.h:475
const char * Pop()
Definition: reader.h:1113
const GLubyte * c
Definition: glext.h:9812
bool EndObject(SizeType)
Definition: reader.h:214
Result of parsing (wraps ParseErrorCode)
Definition: error.h:106
GLuint GLuint GLsizei count
Definition: glext.h:6292
bool String(const Ch *, SizeType, bool)
Definition: reader.h:211
static const size_t kDefaultStackCapacity
Default stack capacity in bytes for storing a single decoded string.
Definition: reader.h:1856
StackStream< char > stackStream
Definition: reader.h:1119
Allow trailing commas at the end of objects and arrays.
Definition: reader.h:154
void ParseFalse(InputStream &is, Handler &handler)
Definition: reader.h:731
internal::SelectIf< internal::IsSame< Derived, void >, BaseReaderHandler, Derived >::Type Override
Definition: reader.h:199
The document is empty.
Definition: error.h:67
StreamLocalCopy(Stream &original)
Definition: reader.h:246
Ch Take()
Definition: stream.h:151
void SetParseError(ParseErrorCode code, size_t offset)
Definition: reader.h:540
Definition: reader.h:1449
bool RawNumber(const Ch *str, SizeType len, bool copy)
enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
Definition: reader.h:210
double StrtodNormalPrecision(double d, int p)
Definition: strtod.h:35
bool StartObject()
Definition: reader.h:212
GenericReader< UTF8<>, UTF8<> > Reader
Reader with UTF8 encoding and default allocator.
Definition: reader.h:1862
void SkipWhitespace(InputStream &is)
Skip the JSON white spaces in a stream.
Definition: reader.h:264
Parse all numbers (ints/doubles) as strings.
Definition: reader.h:153
void Clear()
Definition: stack.h:98
Missing a comma or '}' after an object member.
Definition: error.h:74
ClearStackOnExit(GenericReader &r)
Definition: reader.h:551
Ch * Pop()
Definition: reader.h:794
The surrogate pair in string is invalid.
Definition: error.h:79
unsigned ParseHex4(InputStream &is, size_t escapeOffset)
Definition: reader.h:755
GenericReader(StackAllocator *stackAllocator=0, size_t stackCapacity=kDefaultStackCapacity)
Constructor.
Definition: reader.h:474
ParseResult IterativeParse(InputStream &is, Handler &handler)
Definition: reader.h:1822
Default implementation of Handler.
Definition: fwd.h:85
Ch * dst_
Definition: stream.h:165
bool Double(double)
Definition: reader.h:208
Miss fraction part in number.
Definition: error.h:85
Definition: reader.h:225
bool StartArray()
Definition: reader.h:215
Number too big to be stored in double.
Definition: error.h:84
The document root must not follow by other values.
Definition: error.h:68
static uint64_t state[MAX_PADS]
Definition: xenon360_input.c:33
void ParseValue(InputStream &is, Handler &handler)
Definition: reader.h:1392
Definition: reader.h:1446
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:402
GLenum src
Definition: glext.h:6980
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble w1
Definition: glext.h:9211
NumberStream< InputStream, true, false > Base
Definition: reader.h:1124
#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset)
(Internal) macro to indicate and handle a parse error.
Definition: reader.h:118
GLint GLint GLint GLint GLint x
Definition: glext.h:6295
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:6414
Definition: document.h:391
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:468
Definition: inftrees.h:27
SourceEncoding::Ch Ch
SourceEncoding character type.
Definition: reader.h:468
RAPIDJSON_FORCEINLINE void * Push(SizeType count)
Definition: reader.h:787
GLfloat GLfloat p
Definition: glext.h:9809
Definition: reader.h:1070
const char * Pop()
Definition: reader.h:1087
size_t Offset() const
Get the error offset, if IsError(), 0 otherwise.
Definition: error.h:116
bool Int(int)
Definition: reader.h:204
void ClearStack()
Definition: reader.h:547
void Clear()
Reset error code.
Definition: error.h:128
Stream s
Definition: reader.h:234
#define RAPIDJSON_PARSE_DEFAULT_FLAGS
Definition: reader.h:139
RAPIDJSON_FORCEINLINE void Push(char c)
Definition: reader.h:1107
size_t Length() const
Definition: reader.h:792
Missing a name for object member.
Definition: error.h:72
bool Default()
Definition: reader.h:201
size_t GetErrorOffset() const
Get the position of last parsing error in input, 0 otherwise.
Definition: reader.h:537
Parse number in full precision (but slower).
Definition: reader.h:151
bool IsError() const
Whether the result is an error.
Definition: error.h:121
void Set(ParseErrorCode code, size_t offset=0)
Update error code and offset.
Definition: error.h:130
ParseErrorCode
Error code of parsing.
Definition: error.h:64
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:116
~ClearStackOnExit()
Definition: reader.h:552
ParseErrorCode Code() const
Get the error code.
Definition: error.h:114
bool Key(const Ch *str, SizeType len, bool copy)
Definition: reader.h:213
ParseResult parseResult_
Definition: reader.h:1858
GenericReader & r_
Definition: reader.h:554
NumberStream(GenericReader &reader, InputStream &is)
Definition: reader.h:1126
Ch * src_
Definition: stream.h:164
bool Bool(bool)
Definition: reader.h:203
RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream &is, Handler &handler)
Definition: reader.h:1649
CharType Ch
Definition: reader.h:779
Missing a comma or ']' after an array element.
Definition: error.h:76
StackStream(internal::Stack< StackAllocator > &stack)
Definition: reader.h:781
bool Uint64(uint64_t)
Definition: reader.h:207
Input byte stream wrapper with a statically bound encoding.
Definition: encodedstream.h:39
JSON_Parser_EncodingDetectedHandler handler
Definition: jsonsax_full.h:561
signed __int64 int64_t
Definition: stdint.h:135
Definition: reader.h:1441
bool Int64(int64_t)
Definition: reader.h:206
Definition: reader.h:1444
static RAPIDJSON_FORCEINLINE bool Consume(InputStream &is, typename InputStream::Ch expect)
Definition: reader.h:744
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
Definition: glext.h:9211
Validate encoding of JSON strings.
Definition: reader.h:148
RAPIDJSON_FORCEINLINE Ch TakePush()
Definition: reader.h:1102
void ParseNumber(InputStream &is, Handler &handler)
Definition: reader.h:1133
StreamLocalCopy(Stream &original)
Definition: reader.h:231
ClearStackOnExit & operator=(const ClearStackOnExit &)
InputStream & is
Definition: reader.h:1092
void ParseObject(InputStream &is, Handler &handler)
Definition: reader.h:589
bool EndArray(SizeType)
Definition: reader.h:216
No flags are set.
Definition: reader.h:146
Definition: reader.h:1440
internal::Stack< StackAllocator > & stack_
Definition: reader.h:802
Type
Type of JSON value.
Definition: rapidjson.h:603
GLenum GLenum dst
Definition: glext.h:6980
ParseFlag
Combination of parseFlags.
Definition: reader.h:145
ParseErrorCode GetParseErrorCode() const
Get the ParseErrorCode of last parsing.
Definition: reader.h:534
vu8 head
Definition: keyboard.c:426
void ParseArray(InputStream &is, Handler &handler)
Definition: reader.h:657
GLuint GLuint end
Definition: glext.h:6292
void SkipWhitespaceAndComments(InputStream &is)
Definition: reader.h:560
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6742
RAPIDJSON_FORCEINLINE Ch TakePush()
Definition: reader.h:1081
#define false
Definition: ordinals.h:83
UTF-8 encoding.
Definition: encodings.h:96
Definition: reader.h:1438
RAPIDJSON_FORCEINLINE void Push(char)
Definition: reader.h:1083
#define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
Definition: rapidjson.h:289
GLintptr offset
Definition: glext.h:6560
#define true
Definition: ordinals.h:82
RAPIDJSON_FORCEINLINE void Put(Ch c)
Definition: reader.h:782
Miss exponent in number.
Definition: error.h:86
Definition: reader.h:777
RAPIDJSON_FORCEINLINE Ch Take()
Definition: reader.h:1082
Stream & s
Definition: reader.h:248
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
Definition: fwd.h:88
Invalid encoding in string.
Definition: error.h:82
IterativeParsingState
Definition: reader.h:1410
#define Z16
Unspecific syntax error.
Definition: error.h:89
void ParseTrue(InputStream &is, Handler &handler)
Definition: reader.h:718
unsigned __int64 uint64_t
Definition: stdint.h:136
GLenum GLuint GLenum GLsizei length
Definition: glext.h:6233
Stream & original_
Definition: reader.h:239
GLdouble n
Definition: glext.h:8396
Iterative(constant complexity in terms of function call stack size) parsing.
Definition: reader.h:149
Definition: reader.h:1448
const char *const str
Definition: portlistingparse.c:18
GenericReader & operator=(const GenericReader &)
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:380
Definition: reader.h:1437
Missing a colon after a name of object member.
Definition: error.h:73
size_t Tell()
Definition: stream.h:152
~StreamLocalCopy()
Definition: reader.h:232
Definition: reader.h:1443
NumberStream(GenericReader &reader, InputStream &s)
Definition: reader.h:1077
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text (with kParseDefaultFlags)
Definition: reader.h:526