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