reader.h Source File

reader.h Source File#

Composable Kernel: 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
19
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__
42RAPIDJSON_DIAG_PUSH
43RAPIDJSON_DIAG_OFF(old - style - cast)
44RAPIDJSON_DIAG_OFF(padded)
45RAPIDJSON_DIAG_OFF(switch - enum)
46#elif defined(_MSC_VER)
47RAPIDJSON_DIAG_PUSH
48RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
49RAPIDJSON_DIAG_OFF(4702) // unreachable code
50#endif
51
52#ifdef __GNUC__
53RAPIDJSON_DIAG_PUSH
54RAPIDJSON_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
169
171// Handler
172
189 bool RawNumber(const Ch* str, SizeType length, bool copy);
190 bool String(const Ch* str, SizeType length, bool copy);
191 bool StartObject();
192 bool Key(const Ch* str, SizeType length, bool copy);
193 bool EndObject(SizeType memberCount);
194 bool StartArray();
195 bool EndArray(SizeType elementCount);
196};
197\endcode
198*/
200// BaseReaderHandler
201
203
206template <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
241namespace internal {
242
243template <typename Stream, int = StreamTraits<Stream>::copyOptimization>
245
247template <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
263template <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
284template <typename InputStream>
285void 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
295inline 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
304inline 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
337inline 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
366inline 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
417inline 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
464inline 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
515inline 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
563template <>
564inline void SkipWhitespace(InsituStringStream& is)
565{
566 is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
567}
568
570template <>
571inline void SkipWhitespace(StringStream& is)
572{
573 is.src_ = SkipWhitespace_SIMD(is.src_);
574}
575
576template <>
578{
579 is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
580}
581#endif // RAPIDJSON_SIMD
582
584// GenericReader
585
587
602template <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
1073 internal::Stack<StackAllocator>& stack_;
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 {
1081 internal::StreamLocalCopy<InputStream> copy(is);
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,
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,
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
1826 internal::StreamLocalCopy<InputStream> copy(is);
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 {
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 {
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
2132 if(d > (std::numeric_limits<double>::max)())
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;
2760 internal::Stack<StackAllocator>
2761 stack_;
2762 ParseResult parseResult_;
2763 IterativeParsingState state_;
2764}; // class GenericReader
2765
2768
2770
2771#if defined(__clang__) || defined(_MSC_VER)
2772RAPIDJSON_DIAG_POP
2773#endif
2774
2775#ifdef __GNUC__
2776RAPIDJSON_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
UTF8< char >::Ch Ch
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.
__device__ void copy(const SrcTensorType &src_tensor, DstTensorType &dst_tensor)
Perform optimized copy between two tensors partitions (threadwise copy). Tensors must have the same s...
Definition copy.hpp:36
GenericStringStream< UTF8< char > > StringStream
Definition fwd.h:58
GenericInsituStringStream< UTF8< char > > InsituStringStream
Definition fwd.h:63
GenericReader< UTF8< char >, UTF8< char >, CrtAllocator > Reader
Definition fwd.h:99
#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
@ offset
Definition coordinate_transform.hpp:26
__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
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
internal::SelectIf< internal::IsSame< Derived, void >, BaseReaderHandler, Derived >::Type Override
Definition reader.h:212
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
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
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
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
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream &is, OutputStream &os)
Definition encodings.h:827
static RAPIDJSON_FORCEINLINE bool Validate(InputStream &is, OutputStream &os)
Validate one Unicode codepoint from an encoded stream.
Definition encodings.h:848
UTF-8 encoding.
Definition encodings.h:98
#define Z16