Monero
Loading...
Searching...
No Matches
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
19
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#elif defined(RAPIDJSON_NEON)
37#include <arm_neon.h>
38#endif
39
40#ifdef __clang__
41RAPIDJSON_DIAG_PUSH
42RAPIDJSON_DIAG_OFF(old-style-cast)
43RAPIDJSON_DIAG_OFF(padded)
44RAPIDJSON_DIAG_OFF(switch-enum)
45#elif defined(_MSC_VER)
46RAPIDJSON_DIAG_PUSH
47RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
48RAPIDJSON_DIAG_OFF(4702) // unreachable code
49#endif
50
51#ifdef __GNUC__
52RAPIDJSON_DIAG_PUSH
53RAPIDJSON_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)
67
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
158
160// Handler
161
178 bool RawNumber(const Ch* str, SizeType length, bool copy);
179 bool String(const Ch* str, SizeType length, bool copy);
180 bool StartObject();
181 bool Key(const Ch* str, SizeType length, bool copy);
182 bool EndObject(SizeType memberCount);
183 bool StartArray();
184 bool EndArray(SizeType elementCount);
185};
186\endcode
187*/
189// BaseReaderHandler
190
192
195template<typename Encoding = UTF8<>, typename Derived = void>
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
222namespace internal {
223
224template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
226
228template<typename Stream>
230public:
231 StreamLocalCopy(Stream& original) : s(original), original_(original) {}
233
235
236private:
238
240};
241
243template<typename Stream>
245public:
246 StreamLocalCopy(Stream& original) : s(original) {}
247
249
250private:
252};
253
254} // namespace internal
255
257// SkipWhitespace
258
260
263template<typename InputStream>
264void 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
273inline 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
281inline 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_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
303 if (r != 16) // some of characters is non-whitespace
304 return p + r;
305 }
306}
307
308inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
309 // Fast return for single non-whitespace
310 if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
311 ++p;
312 else
313 return p;
314
315 // The middle of string using SIMD
316 static const char whitespace[16] = " \n\r\t";
317 const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
318
319 for (; p <= end - 16; p += 16) {
320 const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
321 const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
322 if (r != 16) // some of characters is non-whitespace
323 return p + r;
324 }
325
326 return SkipWhitespace(p, end);
327}
328
329#elif defined(RAPIDJSON_SSE2)
330
332inline const char *SkipWhitespace_SIMD(const char* p) {
333 // Fast return for single non-whitespace
334 if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
335 ++p;
336 else
337 return p;
338
339 // 16-byte align to the next boundary
340 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
341 while (p != nextAligned)
342 if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
343 ++p;
344 else
345 return p;
346
347 // The rest of string
348 #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
349 static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
350 #undef C16
351
352 const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
353 const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
354 const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
355 const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
356
357 for (;; p += 16) {
358 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
359 __m128i x = _mm_cmpeq_epi8(s, w0);
360 x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
361 x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
362 x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
363 unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
364 if (r != 0) { // some of characters may be non-whitespace
365#ifdef _MSC_VER // Find the index of first non-whitespace
366 unsigned long offset;
367 _BitScanForward(&offset, r);
368 return p + offset;
369#else
370 return p + __builtin_ffs(r) - 1;
371#endif
372 }
373 }
374}
375
376inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
377 // Fast return for single non-whitespace
378 if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
379 ++p;
380 else
381 return p;
382
383 // The rest of string
384 #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
385 static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
386 #undef C16
387
388 const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
389 const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
390 const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
391 const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
392
393 for (; p <= end - 16; p += 16) {
394 const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
395 __m128i x = _mm_cmpeq_epi8(s, w0);
396 x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
397 x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
398 x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
399 unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
400 if (r != 0) { // some of characters may be non-whitespace
401#ifdef _MSC_VER // Find the index of first non-whitespace
402 unsigned long offset;
403 _BitScanForward(&offset, r);
404 return p + offset;
405#else
406 return p + __builtin_ffs(r) - 1;
407#endif
408 }
409 }
410
411 return SkipWhitespace(p, end);
412}
413
414#elif defined(RAPIDJSON_NEON)
415
417inline const char *SkipWhitespace_SIMD(const char* p) {
418 // Fast return for single non-whitespace
419 if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
420 ++p;
421 else
422 return p;
423
424 // 16-byte align to the next boundary
425 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
426 while (p != nextAligned)
427 if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
428 ++p;
429 else
430 return p;
431
432 const uint8x16_t w0 = vmovq_n_u8(' ');
433 const uint8x16_t w1 = vmovq_n_u8('\n');
434 const uint8x16_t w2 = vmovq_n_u8('\r');
435 const uint8x16_t w3 = vmovq_n_u8('\t');
436
437 for (;; p += 16) {
438 const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
439 uint8x16_t x = vceqq_u8(s, w0);
440 x = vorrq_u8(x, vceqq_u8(s, w1));
441 x = vorrq_u8(x, vceqq_u8(s, w2));
442 x = vorrq_u8(x, vceqq_u8(s, w3));
443
444 x = vmvnq_u8(x); // Negate
445 x = vrev64q_u8(x); // Rev in 64
446 uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
447 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
448
449 if (low == 0) {
450 if (high != 0) {
451 int lz =__builtin_clzll(high);;
452 return p + 8 + (lz >> 3);
453 }
454 } else {
455 int lz = __builtin_clzll(low);;
456 return p + (lz >> 3);
457 }
458 }
459}
460
461inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
462 // Fast return for single non-whitespace
463 if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
464 ++p;
465 else
466 return p;
467
468 const uint8x16_t w0 = vmovq_n_u8(' ');
469 const uint8x16_t w1 = vmovq_n_u8('\n');
470 const uint8x16_t w2 = vmovq_n_u8('\r');
471 const uint8x16_t w3 = vmovq_n_u8('\t');
472
473 for (; p <= end - 16; p += 16) {
474 const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
475 uint8x16_t x = vceqq_u8(s, w0);
476 x = vorrq_u8(x, vceqq_u8(s, w1));
477 x = vorrq_u8(x, vceqq_u8(s, w2));
478 x = vorrq_u8(x, vceqq_u8(s, w3));
479
480 x = vmvnq_u8(x); // Negate
481 x = vrev64q_u8(x); // Rev in 64
482 uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
483 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
484
485 if (low == 0) {
486 if (high != 0) {
487 int lz = __builtin_clzll(high);
488 return p + 8 + (lz >> 3);
489 }
490 } else {
491 int lz = __builtin_clzll(low);
492 return p + (lz >> 3);
493 }
494 }
495
496 return SkipWhitespace(p, end);
497}
498
499#endif // RAPIDJSON_NEON
500
501#ifdef RAPIDJSON_SIMD
503template<> inline void SkipWhitespace(InsituStringStream& is) {
504 is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
505}
506
508template<> inline void SkipWhitespace(StringStream& is) {
509 is.src_ = SkipWhitespace_SIMD(is.src_);
510}
511
512template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
513 is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
514}
515#endif // RAPIDJSON_SIMD
516
518// GenericReader
519
521
536template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
538public:
539 typedef typename SourceEncoding::Ch Ch;
540
542
545 GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) :
546 stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {}
547
549
556 template <unsigned parseFlags, typename InputStream, typename Handler>
557 ParseResult Parse(InputStream& is, Handler& handler) {
558 if (parseFlags & kParseIterativeFlag)
559 return IterativeParse<parseFlags>(is, handler);
560
561 parseResult_.Clear();
562
563 ClearStackOnExit scope(*this);
564
566 RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
567
568 if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) {
570 RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
571 }
572 else {
573 ParseValue<parseFlags>(is, handler);
574 RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
575
576 if (!(parseFlags & kParseStopWhenDoneFlag)) {
578 RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
579
580 if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) {
582 RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
583 }
584 }
585 }
586
587 return parseResult_;
588 }
589
591
597 template <typename InputStream, typename Handler>
598 ParseResult Parse(InputStream& is, Handler& handler) {
599 return Parse<kParseDefaultFlags>(is, handler);
600 }
601
603
609
611
617 template <unsigned parseFlags, typename InputStream, typename Handler>
618 bool IterativeParseNext(InputStream& is, Handler& handler) {
619 while (RAPIDJSON_LIKELY(is.Peek() != '\0')) {
621
622 Token t = Tokenize(is.Peek());
625
626 // If we've finished or hit an error...
628 // Report errors.
630 HandleError(state_, is);
631 return false;
632 }
633
634 // Transition to the finish state.
636 state_ = d;
637
638 // If StopWhenDone is not set...
639 if (!(parseFlags & kParseStopWhenDoneFlag)) {
640 // ... and extra non-whitespace data is found...
642 if (is.Peek() != '\0') {
643 // ... this is considered an error.
644 HandleError(state_, is);
645 return false;
646 }
647 }
648
649 // Success! We are done!
650 return true;
651 }
652
653 // Transition to the new state.
654 state_ = d;
655
656 // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now.
658 return true;
659 }
660
661 // We reached the end of file.
662 stack_.Clear();
663
665 HandleError(state_, is);
666 return false;
667 }
668
669 return true;
670 }
671
673
675 RAPIDJSON_FORCEINLINE bool IterativeParseComplete() const {
677 }
678
680 bool HasParseError() const { return parseResult_.IsError(); }
681
684
686 size_t GetErrorOffset() const { return parseResult_.Offset(); }
687
688protected:
689 void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
690
691private:
692 // Prohibit copy constructor & assignment operator.
695
696 void ClearStack() { stack_.Clear(); }
697
698 // clear stack on any exit from ParseStream, e.g. due to exception
707
708 template<unsigned parseFlags, typename InputStream>
709 void SkipWhitespaceAndComments(InputStream& is) {
710 SkipWhitespace(is);
711
712 if (parseFlags & kParseCommentsFlag) {
713 while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) {
714 if (Consume(is, '*')) {
715 while (true) {
716 if (RAPIDJSON_UNLIKELY(is.Peek() == '\0'))
718 else if (Consume(is, '*')) {
719 if (Consume(is, '/'))
720 break;
721 }
722 else
723 is.Take();
724 }
725 }
726 else if (RAPIDJSON_LIKELY(Consume(is, '/')))
727 while (is.Peek() != '\0' && is.Take() != '\n') {}
728 else
730
731 SkipWhitespace(is);
732 }
733 }
734 }
735
736 // Parse object: { string : value, ... }
737 template<unsigned parseFlags, typename InputStream, typename Handler>
738 void ParseObject(InputStream& is, Handler& handler) {
739 RAPIDJSON_ASSERT(is.Peek() == '{');
740 is.Take(); // Skip '{'
741
742 if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
744
746 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
747
748 if (Consume(is, '}')) {
749 if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object
751 return;
752 }
753
754 for (SizeType memberCount = 0;;) {
755 if (RAPIDJSON_UNLIKELY(is.Peek() != '"'))
757
758 ParseString<parseFlags>(is, handler, true);
759 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
760
762 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
763
764 if (RAPIDJSON_UNLIKELY(!Consume(is, ':')))
766
768 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
769
770 ParseValue<parseFlags>(is, handler);
771 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
772
774 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
775
776 ++memberCount;
777
778 switch (is.Peek()) {
779 case ',':
780 is.Take();
782 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
783 break;
784 case '}':
785 is.Take();
786 if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
788 return;
789 default:
790 RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy
791 }
792
793 if (parseFlags & kParseTrailingCommasFlag) {
794 if (is.Peek() == '}') {
795 if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
797 is.Take();
798 return;
799 }
800 }
801 }
802 }
803
804 // Parse array: [ value, ... ]
805 template<unsigned parseFlags, typename InputStream, typename Handler>
806 void ParseArray(InputStream& is, Handler& handler) {
807 RAPIDJSON_ASSERT(is.Peek() == '[');
808 is.Take(); // Skip '['
809
810 if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
812
814 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
815
816 if (Consume(is, ']')) {
817 if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array
819 return;
820 }
821
822 for (SizeType elementCount = 0;;) {
823 ParseValue<parseFlags>(is, handler);
824 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
825
826 ++elementCount;
828 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
829
830 if (Consume(is, ',')) {
832 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
833 }
834 else if (Consume(is, ']')) {
835 if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
837 return;
838 }
839 else
841
842 if (parseFlags & kParseTrailingCommasFlag) {
843 if (is.Peek() == ']') {
844 if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
846 is.Take();
847 return;
848 }
849 }
850 }
851 }
852
853 template<unsigned parseFlags, typename InputStream, typename Handler>
854 void ParseNull(InputStream& is, Handler& handler) {
855 RAPIDJSON_ASSERT(is.Peek() == 'n');
856 is.Take();
857
858 if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) {
859 if (RAPIDJSON_UNLIKELY(!handler.Null()))
861 }
862 else
864 }
865
866 template<unsigned parseFlags, typename InputStream, typename Handler>
867 void ParseTrue(InputStream& is, Handler& handler) {
868 RAPIDJSON_ASSERT(is.Peek() == 't');
869 is.Take();
870
871 if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) {
872 if (RAPIDJSON_UNLIKELY(!handler.Bool(true)))
874 }
875 else
877 }
878
879 template<unsigned parseFlags, typename InputStream, typename Handler>
880 void ParseFalse(InputStream& is, Handler& handler) {
881 RAPIDJSON_ASSERT(is.Peek() == 'f');
882 is.Take();
883
884 if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) {
885 if (RAPIDJSON_UNLIKELY(!handler.Bool(false)))
887 }
888 else
890 }
891
892 template<typename InputStream>
893 RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
894 if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
895 is.Take();
896 return true;
897 }
898 else
899 return false;
900 }
901
902 // Helper function to parse four hexadecimal digits in \uXXXX in ParseString().
903 template<typename InputStream>
904 unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
905 unsigned codepoint = 0;
906 for (int i = 0; i < 4; i++) {
907 Ch c = is.Peek();
908 codepoint <<= 4;
909 codepoint += static_cast<unsigned>(c);
910 if (c >= '0' && c <= '9')
911 codepoint -= '0';
912 else if (c >= 'A' && c <= 'F')
913 codepoint -= 'A' - 10;
914 else if (c >= 'a' && c <= 'f')
915 codepoint -= 'a' - 10;
916 else {
918 RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
919 }
920 is.Take();
921 }
922 return codepoint;
923 }
924
925 template <typename CharType>
927 public:
928 typedef CharType Ch;
929
931 RAPIDJSON_FORCEINLINE void Put(Ch c) {
932 *stack_.template Push<Ch>() = c;
933 ++length_;
934 }
935
936 RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
937 length_ += count;
938 return stack_.template Push<Ch>(count);
939 }
940
941 size_t Length() const { return length_; }
942
943 Ch* Pop() {
944 return stack_.template Pop<Ch>(length_);
945 }
946
947 private:
950
953 };
954
955 // Parse string and generate String event. Different code paths for kParseInsituFlag.
956 template<unsigned parseFlags, typename InputStream, typename Handler>
957 void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
959 InputStream& s(copy.s);
960
961 RAPIDJSON_ASSERT(s.Peek() == '\"');
962 s.Take(); // Skip '\"'
963
964 bool success = false;
965 if (parseFlags & kParseInsituFlag) {
966 typename InputStream::Ch *head = s.PutBegin();
968 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
969 size_t length = s.PutEnd(head) - 1;
970 RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
971 const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
972 success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
973 }
974 else {
975 StackStream<typename TargetEncoding::Ch> stackStream(stack_);
977 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
978 SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
979 const typename TargetEncoding::Ch* const str = stackStream.Pop();
980 success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
981 }
984 }
985
986 // Parse string to an output is
987 // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
988 template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
989 RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
991#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
992 static const char escape[256] = {
993 Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
994 Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
995 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
996 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
997 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
998 };
999#undef Z16
1001
1002 for (;;) {
1003 // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
1004 if (!(parseFlags & kParseValidateEncodingFlag))
1006
1007 Ch c = is.Peek();
1008 if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape
1009 size_t escapeOffset = is.Tell(); // For invalid escaping, report the initial '\\' as error offset
1010 is.Take();
1011 Ch e = is.Peek();
1012 if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
1013 is.Take();
1014 os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
1015 }
1016 else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode
1017 is.Take();
1018 unsigned codepoint = ParseHex4(is, escapeOffset);
1019 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1020 if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) {
1021 // Handle UTF-16 surrogate pair
1022 if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
1024 unsigned codepoint2 = ParseHex4(is, escapeOffset);
1025 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1026 if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
1028 codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
1029 }
1030 TEncoding::Encode(os, codepoint);
1031 }
1032 else
1034 }
1035 else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote
1036 is.Take();
1037 os.Put('\0'); // null-terminate the string
1038 return;
1039 }
1040 else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
1041 if (c == '\0')
1043 else
1045 }
1046 else {
1047 size_t offset = is.Tell();
1052 }
1053 }
1054 }
1055
1056 template<typename InputStream, typename OutputStream>
1057 static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
1058 // Do nothing for generic version
1059 }
1060
1061#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
1062 // StringStream -> StackStream<char>
1063 static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
1064 const char* p = is.src_;
1065
1066 // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1067 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1068 while (p != nextAligned)
1069 if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1070 is.src_ = p;
1071 return;
1072 }
1073 else
1074 os.Put(*p++);
1075
1076 // The rest of string using SIMD
1077 static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1078 static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1079 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
1080 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
1081 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
1082 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
1083
1084 for (;; p += 16) {
1085 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
1086 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1087 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1088 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
1089 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1090 unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1091 if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
1092 SizeType length;
1093 #ifdef _MSC_VER // Find the index of first escaped
1094 unsigned long offset;
1095 _BitScanForward(&offset, r);
1096 length = offset;
1097 #else
1098 length = static_cast<SizeType>(__builtin_ffs(r) - 1);
1099 #endif
1100 if (length != 0) {
1101 char* q = reinterpret_cast<char*>(os.Push(length));
1102 for (size_t i = 0; i < length; i++)
1103 q[i] = p[i];
1104
1105 p += length;
1106 }
1107 break;
1108 }
1109 _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
1110 }
1111
1112 is.src_ = p;
1113 }
1114
1115 // InsituStringStream -> InsituStringStream
1116 static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
1117 RAPIDJSON_ASSERT(&is == &os);
1118 (void)os;
1119
1120 if (is.src_ == is.dst_) {
1121 SkipUnescapedString(is);
1122 return;
1123 }
1124
1125 char* p = is.src_;
1126 char *q = is.dst_;
1127
1128 // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1129 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1130 while (p != nextAligned)
1131 if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1132 is.src_ = p;
1133 is.dst_ = q;
1134 return;
1135 }
1136 else
1137 *q++ = *p++;
1138
1139 // The rest of string using SIMD
1140 static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1141 static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1142 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
1143 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
1144 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
1145 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
1146
1147 for (;; p += 16, q += 16) {
1148 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
1149 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1150 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1151 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
1152 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1153 unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1154 if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
1155 size_t length;
1156#ifdef _MSC_VER // Find the index of first escaped
1157 unsigned long offset;
1158 _BitScanForward(&offset, r);
1159 length = offset;
1160#else
1161 length = static_cast<size_t>(__builtin_ffs(r) - 1);
1162#endif
1163 for (const char* pend = p + length; p != pend; )
1164 *q++ = *p++;
1165 break;
1166 }
1167 _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s);
1168 }
1169
1170 is.src_ = p;
1171 is.dst_ = q;
1172 }
1173
1174 // When read/write pointers are the same for insitu stream, just skip unescaped characters
1175 static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
1176 RAPIDJSON_ASSERT(is.src_ == is.dst_);
1177 char* p = is.src_;
1178
1179 // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1180 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1181 for (; p != nextAligned; p++)
1182 if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1183 is.src_ = is.dst_ = p;
1184 return;
1185 }
1186
1187 // The rest of string using SIMD
1188 static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1189 static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1190 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
1191 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
1192 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
1193 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
1194
1195 for (;; p += 16) {
1196 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
1197 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1198 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1199 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
1200 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1201 unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1202 if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
1203 size_t length;
1204#ifdef _MSC_VER // Find the index of first escaped
1205 unsigned long offset;
1206 _BitScanForward(&offset, r);
1207 length = offset;
1208#else
1209 length = static_cast<size_t>(__builtin_ffs(r) - 1);
1210#endif
1211 p += length;
1212 break;
1213 }
1214 }
1215
1216 is.src_ = is.dst_ = p;
1217 }
1218#elif defined(RAPIDJSON_NEON)
1219 // StringStream -> StackStream<char>
1220 static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
1221 const char* p = is.src_;
1222
1223 // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1224 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1225 while (p != nextAligned)
1226 if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1227 is.src_ = p;
1228 return;
1229 }
1230 else
1231 os.Put(*p++);
1232
1233 // The rest of string using SIMD
1234 const uint8x16_t s0 = vmovq_n_u8('"');
1235 const uint8x16_t s1 = vmovq_n_u8('\\');
1236 const uint8x16_t s2 = vmovq_n_u8('\b');
1237 const uint8x16_t s3 = vmovq_n_u8(32);
1238
1239 for (;; p += 16) {
1240 const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
1241 uint8x16_t x = vceqq_u8(s, s0);
1242 x = vorrq_u8(x, vceqq_u8(s, s1));
1243 x = vorrq_u8(x, vceqq_u8(s, s2));
1244 x = vorrq_u8(x, vcltq_u8(s, s3));
1245
1246 x = vrev64q_u8(x); // Rev in 64
1247 uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
1248 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
1249
1250 SizeType length = 0;
1251 bool escaped = false;
1252 if (low == 0) {
1253 if (high != 0) {
1254 unsigned lz = (unsigned)__builtin_clzll(high);;
1255 length = 8 + (lz >> 3);
1256 escaped = true;
1257 }
1258 } else {
1259 unsigned lz = (unsigned)__builtin_clzll(low);;
1260 length = lz >> 3;
1261 escaped = true;
1262 }
1263 if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
1264 if (length != 0) {
1265 char* q = reinterpret_cast<char*>(os.Push(length));
1266 for (size_t i = 0; i < length; i++)
1267 q[i] = p[i];
1268
1269 p += length;
1270 }
1271 break;
1272 }
1273 vst1q_u8(reinterpret_cast<uint8_t *>(os.Push(16)), s);
1274 }
1275
1276 is.src_ = p;
1277 }
1278
1279 // InsituStringStream -> InsituStringStream
1280 static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
1281 RAPIDJSON_ASSERT(&is == &os);
1282 (void)os;
1283
1284 if (is.src_ == is.dst_) {
1285 SkipUnescapedString(is);
1286 return;
1287 }
1288
1289 char* p = is.src_;
1290 char *q = is.dst_;
1291
1292 // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1293 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1294 while (p != nextAligned)
1295 if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1296 is.src_ = p;
1297 is.dst_ = q;
1298 return;
1299 }
1300 else
1301 *q++ = *p++;
1302
1303 // The rest of string using SIMD
1304 const uint8x16_t s0 = vmovq_n_u8('"');
1305 const uint8x16_t s1 = vmovq_n_u8('\\');
1306 const uint8x16_t s2 = vmovq_n_u8('\b');
1307 const uint8x16_t s3 = vmovq_n_u8(32);
1308
1309 for (;; p += 16, q += 16) {
1310 const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
1311 uint8x16_t x = vceqq_u8(s, s0);
1312 x = vorrq_u8(x, vceqq_u8(s, s1));
1313 x = vorrq_u8(x, vceqq_u8(s, s2));
1314 x = vorrq_u8(x, vcltq_u8(s, s3));
1315
1316 x = vrev64q_u8(x); // Rev in 64
1317 uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
1318 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
1319
1320 SizeType length = 0;
1321 bool escaped = false;
1322 if (low == 0) {
1323 if (high != 0) {
1324 unsigned lz = (unsigned)__builtin_clzll(high);
1325 length = 8 + (lz >> 3);
1326 escaped = true;
1327 }
1328 } else {
1329 unsigned lz = (unsigned)__builtin_clzll(low);
1330 length = lz >> 3;
1331 escaped = true;
1332 }
1333 if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
1334 for (const char* pend = p + length; p != pend; ) {
1335 *q++ = *p++;
1336 }
1337 break;
1338 }
1339 vst1q_u8(reinterpret_cast<uint8_t *>(q), s);
1340 }
1341
1342 is.src_ = p;
1343 is.dst_ = q;
1344 }
1345
1346 // When read/write pointers are the same for insitu stream, just skip unescaped characters
1347 static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
1348 RAPIDJSON_ASSERT(is.src_ == is.dst_);
1349 char* p = is.src_;
1350
1351 // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1352 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1353 for (; p != nextAligned; p++)
1354 if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1355 is.src_ = is.dst_ = p;
1356 return;
1357 }
1358
1359 // The rest of string using SIMD
1360 const uint8x16_t s0 = vmovq_n_u8('"');
1361 const uint8x16_t s1 = vmovq_n_u8('\\');
1362 const uint8x16_t s2 = vmovq_n_u8('\b');
1363 const uint8x16_t s3 = vmovq_n_u8(32);
1364
1365 for (;; p += 16) {
1366 const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
1367 uint8x16_t x = vceqq_u8(s, s0);
1368 x = vorrq_u8(x, vceqq_u8(s, s1));
1369 x = vorrq_u8(x, vceqq_u8(s, s2));
1370 x = vorrq_u8(x, vcltq_u8(s, s3));
1371
1372 x = vrev64q_u8(x); // Rev in 64
1373 uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
1374 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
1375
1376 if (low == 0) {
1377 if (high != 0) {
1378 int lz = __builtin_clzll(high);
1379 p += 8 + (lz >> 3);
1380 break;
1381 }
1382 } else {
1383 int lz = __builtin_clzll(low);
1384 p += lz >> 3;
1385 break;
1386 }
1387 }
1388
1389 is.src_ = is.dst_ = p;
1390 }
1391#endif // RAPIDJSON_NEON
1392
1393 template<typename InputStream, bool backup, bool pushOnTake>
1395
1396 template<typename InputStream>
1397 class NumberStream<InputStream, false, false> {
1398 public:
1399 typedef typename InputStream::Ch Ch;
1400
1401 NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
1402
1403 RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
1404 RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
1405 RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
1406 RAPIDJSON_FORCEINLINE void Push(char) {}
1407
1408 size_t Tell() { return is.Tell(); }
1409 size_t Length() { return 0; }
1410 const char* Pop() { return 0; }
1411
1412 protected:
1414
1415 InputStream& is;
1416 };
1417
1418 template<typename InputStream>
1419 class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
1421 public:
1422 NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
1423
1424 RAPIDJSON_FORCEINLINE Ch TakePush() {
1425 stackStream.Put(static_cast<char>(Base::is.Peek()));
1426 return Base::is.Take();
1427 }
1428
1429 RAPIDJSON_FORCEINLINE void Push(char c) {
1430 stackStream.Put(c);
1431 }
1432
1433 size_t Length() { return stackStream.Length(); }
1434
1435 const char* Pop() {
1436 stackStream.Put('\0');
1437 return stackStream.Pop();
1438 }
1439
1440 private:
1442 };
1443
1444 template<typename InputStream>
1445 class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
1447 public:
1448 NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
1449
1450 RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
1451 };
1452
1453 template<unsigned parseFlags, typename InputStream, typename Handler>
1454 void ParseNumber(InputStream& is, Handler& handler) {
1456 NumberStream<InputStream,
1457 ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
1458 ((parseFlags & kParseInsituFlag) == 0) :
1459 ((parseFlags & kParseFullPrecisionFlag) != 0),
1460 (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
1461 (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
1462
1463 size_t startOffset = s.Tell();
1464 double d = 0.0;
1465 bool useNanOrInf = false;
1466
1467 // Parse minus
1468 bool minus = Consume(s, '-');
1469
1470 // Parse int: zero / ( digit1-9 *DIGIT )
1471 unsigned i = 0;
1472 uint64_t i64 = 0;
1473 bool use64bit = false;
1474 int significandDigit = 0;
1475 if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) {
1476 i = 0;
1477 s.TakePush();
1478 }
1479 else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) {
1480 i = static_cast<unsigned>(s.TakePush() - '0');
1481
1482 if (minus)
1483 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1484 if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648
1485 if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) {
1486 i64 = i;
1487 use64bit = true;
1488 break;
1489 }
1490 }
1491 i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
1492 significandDigit++;
1493 }
1494 else
1495 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1496 if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295
1497 if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {
1498 i64 = i;
1499 use64bit = true;
1500 break;
1501 }
1502 }
1503 i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
1504 significandDigit++;
1505 }
1506 }
1507 // Parse NaN or Infinity here
1508 else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
1509 if (Consume(s, 'N')) {
1510 if (Consume(s, 'a') && Consume(s, 'N')) {
1511 d = std::numeric_limits<double>::quiet_NaN();
1512 useNanOrInf = true;
1513 }
1514 }
1515 else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) {
1516 if (Consume(s, 'n') && Consume(s, 'f')) {
1517 d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
1518 useNanOrInf = true;
1519
1520 if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
1521 && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) {
1523 }
1524 }
1525 }
1526
1527 if (RAPIDJSON_UNLIKELY(!useNanOrInf)) {
1529 }
1530 }
1531 else
1533
1534 // Parse 64bit int
1535 bool useDouble = false;
1536 if (use64bit) {
1537 if (minus)
1538 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1539 if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
1540 if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
1541 d = static_cast<double>(i64);
1542 useDouble = true;
1543 break;
1544 }
1545 i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1546 significandDigit++;
1547 }
1548 else
1549 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1550 if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615
1551 if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {
1552 d = static_cast<double>(i64);
1553 useDouble = true;
1554 break;
1555 }
1556 i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1557 significandDigit++;
1558 }
1559 }
1560
1561 // Force double for big integer
1562 if (useDouble) {
1563 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1564 d = d * 10 + (s.TakePush() - '0');
1565 }
1566 }
1567
1568 // Parse frac = decimal-point 1*DIGIT
1569 int expFrac = 0;
1570 size_t decimalPosition;
1571 if (Consume(s, '.')) {
1572 decimalPosition = s.Length();
1573
1574 if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
1576
1577 if (!useDouble) {
1578#if RAPIDJSON_64BIT
1579 // Use i64 to store significand in 64-bit architecture
1580 if (!use64bit)
1581 i64 = i;
1582
1583 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1584 if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
1585 break;
1586 else {
1587 i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1588 --expFrac;
1589 if (i64 != 0)
1590 significandDigit++;
1591 }
1592 }
1593
1594 d = static_cast<double>(i64);
1595#else
1596 // Use double to store significand in 32-bit architecture
1597 d = static_cast<double>(use64bit ? i64 : i);
1598#endif
1599 useDouble = true;
1600 }
1601
1602 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1603 if (significandDigit < 17) {
1604 d = d * 10.0 + (s.TakePush() - '0');
1605 --expFrac;
1606 if (RAPIDJSON_LIKELY(d > 0.0))
1607 significandDigit++;
1608 }
1609 else
1610 s.TakePush();
1611 }
1612 }
1613 else
1614 decimalPosition = s.Length(); // decimal position at the end of integer.
1615
1616 // Parse exp = e [ minus / plus ] 1*DIGIT
1617 int exp = 0;
1618 if (Consume(s, 'e') || Consume(s, 'E')) {
1619 if (!useDouble) {
1620 d = static_cast<double>(use64bit ? i64 : i);
1621 useDouble = true;
1622 }
1623
1624 bool expMinus = false;
1625 if (Consume(s, '+'))
1626 ;
1627 else if (Consume(s, '-'))
1628 expMinus = true;
1629
1630 if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1631 exp = static_cast<int>(s.Take() - '0');
1632 if (expMinus) {
1633 // (exp + expFrac) must not underflow int => we're detecting when -exp gets
1634 // dangerously close to INT_MIN (a pessimistic next digit 9 would push it into
1635 // underflow territory):
1636 //
1637 // -(exp * 10 + 9) + expFrac >= INT_MIN
1638 // <=> exp <= (expFrac - INT_MIN - 9) / 10
1639 RAPIDJSON_ASSERT(expFrac <= 0);
1640 int maxExp = (expFrac + 2147483639) / 10;
1641
1642 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1643 exp = exp * 10 + static_cast<int>(s.Take() - '0');
1644 if (RAPIDJSON_UNLIKELY(exp > maxExp)) {
1645 while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent
1646 s.Take();
1647 }
1648 }
1649 }
1650 else { // positive exp
1651 int maxExp = 308 - expFrac;
1652 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1653 exp = exp * 10 + static_cast<int>(s.Take() - '0');
1654 if (RAPIDJSON_UNLIKELY(exp > maxExp))
1656 }
1657 }
1658 }
1659 else
1661
1662 if (expMinus)
1663 exp = -exp;
1664 }
1665
1666 // Finish parsing, call event according to the type of number.
1667 bool cont = true;
1668
1669 if (parseFlags & kParseNumbersAsStringsFlag) {
1670 if (parseFlags & kParseInsituFlag) {
1671 s.Pop(); // Pop stack no matter if it will be used or not.
1672 typename InputStream::Ch* head = is.PutBegin();
1673 const size_t length = s.Tell() - startOffset;
1674 RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
1675 // unable to insert the \0 character here, it will erase the comma after this number
1676 const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
1677 cont = handler.RawNumber(str, SizeType(length), false);
1678 }
1679 else {
1680 SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
1681 StringStream srcStream(s.Pop());
1682 StackStream<typename TargetEncoding::Ch> dstStream(stack_);
1683 while (numCharsToCopy--) {
1684 Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);
1685 }
1686 dstStream.Put('\0');
1687 const typename TargetEncoding::Ch* str = dstStream.Pop();
1688 const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;
1689 cont = handler.RawNumber(str, SizeType(length), true);
1690 }
1691 }
1692 else {
1693 size_t length = s.Length();
1694 const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
1695
1696 if (useDouble) {
1697 int p = exp + expFrac;
1698 if (parseFlags & kParseFullPrecisionFlag)
1699 d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
1700 else
1702
1703 // Use > max, instead of == inf, to fix bogus warning -Wfloat-equal
1704 if (d > std::numeric_limits<double>::max()) {
1705 // Overflow
1706 // TODO: internal::StrtodX should report overflow (or underflow)
1708 }
1709
1710 cont = handler.Double(minus ? -d : d);
1711 }
1712 else if (useNanOrInf) {
1713 cont = handler.Double(d);
1714 }
1715 else {
1716 if (use64bit) {
1717 if (minus)
1718 cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
1719 else
1720 cont = handler.Uint64(i64);
1721 }
1722 else {
1723 if (minus)
1724 cont = handler.Int(static_cast<int32_t>(~i + 1));
1725 else
1726 cont = handler.Uint(i);
1727 }
1728 }
1729 }
1730 if (RAPIDJSON_UNLIKELY(!cont))
1732 }
1733
1734 // Parse any JSON value
1735 template<unsigned parseFlags, typename InputStream, typename Handler>
1736 void ParseValue(InputStream& is, Handler& handler) {
1737 switch (is.Peek()) {
1738 case 'n': ParseNull <parseFlags>(is, handler); break;
1739 case 't': ParseTrue <parseFlags>(is, handler); break;
1740 case 'f': ParseFalse <parseFlags>(is, handler); break;
1741 case '"': ParseString<parseFlags>(is, handler); break;
1742 case '{': ParseObject<parseFlags>(is, handler); break;
1743 case '[': ParseArray <parseFlags>(is, handler); break;
1744 default :
1745 ParseNumber<parseFlags>(is, handler);
1746 break;
1747
1748 }
1749 }
1750
1751 // Iterative Parsing
1752
1753 // States
1780
1781 // Tokens
1800
1801 RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) const {
1802
1804#define N NumberToken
1805#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
1806 // Maps from ASCII to Token
1807 static const unsigned char tokenMap[256] = {
1808 N16, // 00~0F
1809 N16, // 10~1F
1810 N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
1811 N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
1812 N16, // 40~4F
1813 N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
1814 N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
1815 N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
1816 N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
1817 };
1818#undef N
1819#undef N16
1821
1822 if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
1823 return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
1824 else
1825 return NumberToken;
1826 }
1827
1828 RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) const {
1829 // current state x one lookahead token -> new state
1830 static const char G[cIterativeParsingStateCount][kTokenCount] = {
1831 // Finish(sink state)
1832 {
1836 },
1837 // Error(sink state)
1838 {
1842 },
1843 // Start
1844 {
1845 IterativeParsingArrayInitialState, // Left bracket
1846 IterativeParsingErrorState, // Right bracket
1847 IterativeParsingObjectInitialState, // Left curly bracket
1848 IterativeParsingErrorState, // Right curly bracket
1856 },
1857 // ObjectInitial
1858 {
1859 IterativeParsingErrorState, // Left bracket
1860 IterativeParsingErrorState, // Right bracket
1861 IterativeParsingErrorState, // Left curly bracket
1862 IterativeParsingObjectFinishState, // Right curly bracket
1870 },
1871 // MemberKey
1872 {
1873 IterativeParsingErrorState, // Left bracket
1874 IterativeParsingErrorState, // Right bracket
1875 IterativeParsingErrorState, // Left curly bracket
1876 IterativeParsingErrorState, // Right curly bracket
1884 },
1885 // MemberValue
1886 {
1887 IterativeParsingErrorState, // Left bracket
1888 IterativeParsingErrorState, // Right bracket
1889 IterativeParsingErrorState, // Left curly bracket
1890 IterativeParsingObjectFinishState, // Right curly bracket
1898 },
1899 // ObjectFinish(sink state)
1900 {
1904 },
1905 // ArrayInitial
1906 {
1907 IterativeParsingArrayInitialState, // Left bracket(push Element state)
1908 IterativeParsingArrayFinishState, // Right bracket
1909 IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
1910 IterativeParsingErrorState, // Right curly bracket
1918 },
1919 // Element
1920 {
1921 IterativeParsingErrorState, // Left bracket
1922 IterativeParsingArrayFinishState, // Right bracket
1923 IterativeParsingErrorState, // Left curly bracket
1924 IterativeParsingErrorState, // Right curly bracket
1932 },
1933 // ArrayFinish(sink state)
1934 {
1938 },
1939 // Single Value (sink state)
1940 {
1944 },
1945 // ElementDelimiter
1946 {
1947 IterativeParsingArrayInitialState, // Left bracket(push Element state)
1948 IterativeParsingArrayFinishState, // Right bracket
1949 IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
1950 IterativeParsingErrorState, // Right curly bracket
1958 },
1959 // MemberDelimiter
1960 {
1961 IterativeParsingErrorState, // Left bracket
1962 IterativeParsingErrorState, // Right bracket
1963 IterativeParsingErrorState, // Left curly bracket
1964 IterativeParsingObjectFinishState, // Right curly bracket
1972 },
1973 // KeyValueDelimiter
1974 {
1975 IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
1976 IterativeParsingErrorState, // Right bracket
1977 IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
1978 IterativeParsingErrorState, // Right curly bracket
1986 },
1987 }; // End of G
1988
1989 return static_cast<IterativeParsingState>(G[state][token]);
1990 }
1991
1992 // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
1993 // May return a new state on state pop.
1994 template <unsigned parseFlags, typename InputStream, typename Handler>
1995 RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
1996 (void)token;
1997
1998 switch (dst) {
2000 return dst;
2001
2004 {
2005 // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
2006 // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
2007 IterativeParsingState n = src;
2012 // Push current state.
2013 *stack_.template Push<SizeType>(1) = n;
2014 // Initialize and push the member/element count.
2015 *stack_.template Push<SizeType>(1) = 0;
2016 // Call handler
2017 bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
2018 // On handler short circuits the parsing.
2019 if (!hr) {
2022 }
2023 else {
2024 is.Take();
2025 return dst;
2026 }
2027 }
2028
2030 ParseString<parseFlags>(is, handler, true);
2031 if (HasParseError())
2033 else
2034 return dst;
2035
2037 RAPIDJSON_ASSERT(token == ColonToken);
2038 is.Take();
2039 return dst;
2040
2042 // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2043 ParseValue<parseFlags>(is, handler);
2044 if (HasParseError()) {
2046 }
2047 return dst;
2048
2050 // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2051 ParseValue<parseFlags>(is, handler);
2052 if (HasParseError()) {
2054 }
2055 return dst;
2056
2059 is.Take();
2060 // Update member/element count.
2061 *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
2062 return dst;
2063
2065 {
2066 // Transit from delimiter is only allowed when trailing commas are enabled
2067 if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {
2070 }
2071 // Get member count.
2072 SizeType c = *stack_.template Pop<SizeType>(1);
2073 // If the object is not empty, count the last member.
2075 ++c;
2076 // Restore the state.
2077 IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
2078 // Transit to Finish state if this is the topmost scope.
2081 // Call handler
2082 bool hr = handler.EndObject(c);
2083 // On handler short circuits the parsing.
2084 if (!hr) {
2087 }
2088 else {
2089 is.Take();
2090 return n;
2091 }
2092 }
2093
2095 {
2096 // Transit from delimiter is only allowed when trailing commas are enabled
2100 }
2101 // Get element count.
2102 SizeType c = *stack_.template Pop<SizeType>(1);
2103 // If the array is not empty, count the last element.
2105 ++c;
2106 // Restore the state.
2107 IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
2108 // Transit to Finish state if this is the topmost scope.
2111 // Call handler
2112 bool hr = handler.EndArray(c);
2113 // On handler short circuits the parsing.
2114 if (!hr) {
2117 }
2118 else {
2119 is.Take();
2120 return n;
2121 }
2122 }
2123
2124 default:
2125 // This branch is for IterativeParsingValueState actually.
2126 // Use `default:` rather than
2127 // `case IterativeParsingValueState:` is for code coverage.
2128
2129 // The IterativeParsingStartState is not enumerated in this switch-case.
2130 // It is impossible for that case. And it can be caught by following assertion.
2131
2132 // The IterativeParsingFinishState is not enumerated in this switch-case either.
2133 // It is a "derivative" state which cannot triggered from Predict() directly.
2134 // Therefore it cannot happen here. And it can be caught by following assertion.
2136
2137 // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2138 ParseValue<parseFlags>(is, handler);
2139 if (HasParseError()) {
2141 }
2143 }
2144 }
2145
2146 template <typename InputStream>
2166
2169 }
2170
2171 RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) const {
2172 return s <= IterativeParsingErrorState;
2173 }
2174
2175 template <unsigned parseFlags, typename InputStream, typename Handler>
2176 ParseResult IterativeParse(InputStream& is, Handler& handler) {
2177 parseResult_.Clear();
2178 ClearStackOnExit scope(*this);
2180
2182 RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
2183 while (is.Peek() != '\0') {
2184 Token t = Tokenize(is.Peek());
2186 IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
2187
2189 HandleError(state, is);
2190 break;
2191 }
2192
2193 state = d;
2194
2195 // Do not further consume streams if a root JSON has been parsed.
2197 break;
2198
2200 RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
2201 }
2202
2203 // Handle the end of file.
2205 HandleError(state, is);
2206
2207 return parseResult_;
2208 }
2209
2210 static const size_t kDefaultStackCapacity = 256;
2214}; // class GenericReader
2215
2218
2220
2221#if defined(__clang__) || defined(_MSC_VER)
2222RAPIDJSON_DIAG_POP
2223#endif
2224
2225
2226#ifdef __GNUC__
2227RAPIDJSON_DIAG_POP
2228#endif
2229
2230#endif // RAPIDJSON_READER_H_
#define w1(p)
Definition aesb.c:107
#define s(x, c)
Definition aesb.c:47
#define w0(p)
Definition aesb.c:106
#define w3(p)
Definition aesb.c:109
#define w2(p)
Definition aesb.c:108
#define G(r, i, a, b, c, d)
Input byte stream wrapper with a statically bound encoding.
Definition encodedstream.h:39
NumberStream(GenericReader &reader, InputStream &s)
Definition reader.h:1401
NumberStream & operator=(const NumberStream &)
const char * Pop()
Definition reader.h:1410
RAPIDJSON_FORCEINLINE void Push(char)
Definition reader.h:1406
InputStream & is
Definition reader.h:1415
InputStream::Ch Ch
Definition reader.h:1399
RAPIDJSON_FORCEINLINE Ch Take()
Definition reader.h:1405
RAPIDJSON_FORCEINLINE Ch Peek() const
Definition reader.h:1403
RAPIDJSON_FORCEINLINE Ch TakePush()
Definition reader.h:1404
StackStream< char > stackStream
Definition reader.h:1441
RAPIDJSON_FORCEINLINE Ch TakePush()
Definition reader.h:1424
NumberStream(GenericReader &reader, InputStream &is)
Definition reader.h:1422
const char * Pop()
Definition reader.h:1435
NumberStream< InputStream, false, false > Base
Definition reader.h:1420
RAPIDJSON_FORCEINLINE void Push(char c)
Definition reader.h:1429
RAPIDJSON_FORCEINLINE Ch Take()
Definition reader.h:1450
NumberStream(GenericReader &reader, InputStream &is)
Definition reader.h:1448
NumberStream< InputStream, true, false > Base
Definition reader.h:1446
Definition reader.h:1394
Definition reader.h:926
internal::Stack< StackAllocator > & stack_
Definition reader.h:951
StackStream(internal::Stack< StackAllocator > &stack)
Definition reader.h:930
StackStream & operator=(const StackStream &)
size_t Length() const
Definition reader.h:941
StackStream(const StackStream &)
RAPIDJSON_FORCEINLINE void * Push(SizeType count)
Definition reader.h:936
CharType Ch
Definition reader.h:928
SizeType length_
Definition reader.h:952
RAPIDJSON_FORCEINLINE void Put(Ch c)
Definition reader.h:931
Ch * Pop()
Definition reader.h:943
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
Definition reader.h:537
RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) const
Definition reader.h:1801
RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream &is, Handler &handler)
Definition reader.h:1995
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text.
Definition reader.h:557
RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) const
Definition reader.h:2167
ParseResult parseResult_
Definition reader.h:2212
void ClearStack()
Definition reader.h:696
static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream &, OutputStream &)
Definition reader.h:1057
void ParseNumber(InputStream &is, Handler &handler)
Definition reader.h:1454
bool IterativeParseNext(InputStream &is, Handler &handler)
Parse one token from JSON text.
Definition reader.h:618
RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) const
Definition reader.h:2171
void HandleError(IterativeParsingState src, InputStream &is)
Definition reader.h:2147
void SkipWhitespaceAndComments(InputStream &is)
Definition reader.h:709
static RAPIDJSON_FORCEINLINE bool Consume(InputStream &is, typename InputStream::Ch expect)
Definition reader.h:893
ParseResult IterativeParse(InputStream &is, Handler &handler)
Definition reader.h:2176
GenericReader & operator=(const GenericReader &)
void ParseTrue(InputStream &is, Handler &handler)
Definition reader.h:867
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text (with kParseDefaultFlags).
Definition reader.h:598
internal::Stack< CrtAllocator > stack_
Definition reader.h:2211
void IterativeParseInit()
Initialize JSON text token-by-token parsing.
Definition reader.h:605
void ParseValue(InputStream &is, Handler &handler)
Definition reader.h:1736
void ParseArray(InputStream &is, Handler &handler)
Definition reader.h:806
RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream &is, OutputStream &os)
Definition reader.h:989
ParseErrorCode GetParseErrorCode() const
Get the ParseErrorCode of last parsing.
Definition reader.h:683
RAPIDJSON_FORCEINLINE bool IterativeParseComplete() const
Check if token-by-token parsing JSON text is complete.
Definition reader.h:675
GenericReader(StackAllocator *stackAllocator=0, size_t stackCapacity=kDefaultStackCapacity)
Constructor.
Definition reader.h:545
UTF8< char >::Ch Ch
Definition reader.h:539
void ParseString(InputStream &is, Handler &handler, bool isKey=false)
Definition reader.h:957
bool HasParseError() const
Whether a parse error has occurred in the last parsing.
Definition reader.h:680
static const size_t kDefaultStackCapacity
Definition reader.h:2210
GenericReader(const GenericReader &)
RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) const
Definition reader.h:1828
IterativeParsingState state_
Definition reader.h:2213
void SetParseError(ParseErrorCode code, size_t offset)
Definition reader.h:689
void ParseNull(InputStream &is, Handler &handler)
Definition reader.h:854
size_t GetErrorOffset() const
Get the position of last parsing error in input, 0 otherwise.
Definition reader.h:686
void ParseFalse(InputStream &is, Handler &handler)
Definition reader.h:880
void ParseObject(InputStream &is, Handler &handler)
Definition reader.h:738
unsigned ParseHex4(InputStream &is, size_t escapeOffset)
Definition reader.h:904
Definition expect.h:134
A type-unsafe stack for storing different types of data.
Definition stack.h:36
StreamLocalCopy & operator=(const StreamLocalCopy &)
StreamLocalCopy(Stream &original)
Definition reader.h:246
Stream & s
Definition reader.h:248
Stream s
Definition reader.h:234
Stream & original_
Definition reader.h:239
StreamLocalCopy & operator=(const StreamLocalCopy &)
StreamLocalCopy(Stream &original)
Definition reader.h:231
~StreamLocalCopy()
Definition reader.h:232
Definition reader.h:225
Concept for receiving events from GenericReader upon parsing. The functions return true if no error o...
Concept for reading and writing characters.
bool success
Definition cold-transaction.cpp:57
GenericStringStream< UTF8< char > > StringStream
Definition fwd.h:49
GenericInsituStringStream< UTF8< char > > InsituStringStream
Definition fwd.h:54
GenericReader< UTF8< char >, UTF8< char >, CrtAllocator > Reader
Definition fwd.h:90
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition rapidjson.h:468
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition rapidjson.h:481
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition rapidjson.h:411
#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:99
ParseErrorCode
Error code of parsing.
Definition error.h:64
#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset)
(Internal) macro to indicate and handle a parse error.
Definition reader.h:118
@ kParseErrorDocumentEmpty
The document is empty.
Definition error.h:67
@ kParseErrorNumberMissFraction
Miss fraction part in number.
Definition error.h:85
@ kParseErrorStringInvalidEncoding
Invalid encoding in string.
Definition error.h:82
@ kParseErrorValueInvalid
Invalid value.
Definition error.h:70
@ kParseErrorDocumentRootNotSingular
The document root must not follow by other values.
Definition error.h:68
@ kParseErrorUnspecificSyntaxError
Unspecific syntax error.
Definition error.h:89
@ kParseErrorObjectMissCommaOrCurlyBracket
Missing a comma or '}' after an object member.
Definition error.h:74
@ kParseErrorObjectMissColon
Missing a colon after a name of object member.
Definition error.h:73
@ kParseErrorStringMissQuotationMark
Missing a closing quotation mark in string.
Definition error.h:81
@ kParseErrorTermination
Parsing was terminated.
Definition error.h:88
@ kParseErrorNumberMissExponent
Miss exponent in number.
Definition error.h:86
@ kParseErrorStringEscapeInvalid
Invalid escape character in string.
Definition error.h:80
@ kParseErrorArrayMissCommaOrSquareBracket
Missing a comma or ']' after an array element.
Definition error.h:76
@ kParseErrorStringUnicodeSurrogateInvalid
The surrogate pair in string is invalid.
Definition error.h:79
@ kParseErrorObjectMissName
Missing a name for object member.
Definition error.h:72
@ kParseErrorNumberTooBig
Number too big to be stored in double.
Definition error.h:84
@ kParseErrorStringUnicodeEscapeInvalidHex
Incorrect hex digit after \u escape in string.
Definition error.h:78
#define true
#define false
int q
Definition base.py:2
Definition d.py:1
Definition document.h:406
double StrtodFullPrecision(double d, int p, const char *decimals, size_t length, size_t decimalPosition, int exp)
Definition strtod.h:226
double StrtodNormalPrecision(double d, int p)
Definition strtod.h:37
int i
Definition pymoduletest.py:23
p
Definition pymoduletest.py:75
r
Definition testupnpigd.py:61
const char *const str
Definition portlistingparse.c:23
const portMappingElt code
Definition portlistingparse.c:22
Type
Type of JSON value.
Definition rapidjson.h:623
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.).
Definition rapidjson.h:389
#define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
Definition rapidjson.h:294
void SkipWhitespace(InputStream &is)
Skip the JSON white spaces in a stream.
Definition reader.h:264
#define RAPIDJSON_PARSE_DEFAULT_FLAGS
Definition reader.h:139
ParseFlag
Combination of parseFlags.
Definition reader.h:145
@ kParseFullPrecisionFlag
Parse number in full precision (but slower).
Definition reader.h:151
@ kParseInsituFlag
In-situ(destructive) parsing.
Definition reader.h:147
@ kParseNoFlags
No flags are set.
Definition reader.h:146
@ kParseCommentsFlag
Allow one-line (//) and multi-line (/‍**/) comments.
Definition reader.h:152
@ kParseDefaultFlags
Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS.
Definition reader.h:156
@ kParseTrailingCommasFlag
Allow trailing commas at the end of objects and arrays.
Definition reader.h:154
@ kParseNanAndInfFlag
Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
Definition reader.h:155
@ kParseValidateEncodingFlag
Validate encoding of JSON strings.
Definition reader.h:148
@ kParseNumbersAsStringsFlag
Parse all numbers (ints/doubles) as strings.
Definition reader.h:153
@ kParseIterativeFlag
Iterative(constant complexity in terms of function call stack size) parsing.
Definition reader.h:149
@ kParseStopWhenDoneFlag
After parsing a complete JSON root from stream, stop further processing the rest of stream....
Definition reader.h:150
t2
Definition pow22523.h:103
t1
Definition pow22523.h:58
t3
Definition pow225521.h:103
signed __int64 int64_t
Definition stdint.h:135
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:196
bool Int64(int64_t)
Definition reader.h:206
bool EndObject(SizeType)
Definition reader.h:214
bool Uint(unsigned)
Definition reader.h:205
bool Uint64(uint64_t)
Definition reader.h:207
bool String(const Ch *, SizeType, bool)
Definition reader.h:211
bool Double(double)
Definition reader.h:208
Encoding::Ch Ch
Definition reader.h:197
bool Default()
Definition reader.h:201
bool Int(int)
Definition reader.h:204
internal::SelectIf< internal::IsSame< Derived, void >, BaseReaderHandler, Derived >::Type Override
Definition reader.h:199
bool StartArray()
Definition reader.h:215
bool RawNumber(const Ch *str, SizeType len, bool copy)
enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
Definition reader.h:210
bool Bool(bool)
Definition reader.h:203
bool StartObject()
Definition reader.h:212
bool Key(const Ch *str, SizeType len, bool copy)
Definition reader.h:213
bool Null()
Definition reader.h:202
bool EndArray(SizeType)
Definition reader.h:216
Ch * dst_
Definition stream.h:209
Ch * src_
Definition stream.h:208
GenericReader & r_
Definition reader.h:703
ClearStackOnExit(GenericReader &r)
Definition reader.h:700
ClearStackOnExit(const ClearStackOnExit &)
~ClearStackOnExit()
Definition reader.h:701
ClearStackOnExit & operator=(const ClearStackOnExit &)
const Ch * src_
Current read position.
Definition stream.h:168
Represents an in-memory input byte stream.
Definition memorystream.h:40
Result of parsing (wraps ParseErrorCode).
Definition error.h:106
Encoding conversion.
Definition encodings.h:658
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream &is, OutputStream &os)
Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the outp...
Definition encodings.h:661
static RAPIDJSON_FORCEINLINE bool Validate(InputStream &is, OutputStream &os)
Validate one Unicode codepoint from an encoded stream.
Definition encodings.h:680
UTF-8 encoding.
Definition encodings.h:96
Definition blake256.h:36
#define Z16