载入中...
搜索中...
未找到
reader.h
浏览该文件的文档.
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
18/*! \file reader.h */
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 _MSC_VER
41RAPIDJSON_DIAG_PUSH
42RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
43RAPIDJSON_DIAG_OFF(4702) // unreachable code
44#endif
45
46#ifdef __clang__
47RAPIDJSON_DIAG_PUSH
48RAPIDJSON_DIAG_OFF(old-style-cast)
49RAPIDJSON_DIAG_OFF(padded)
50RAPIDJSON_DIAG_OFF(switch-enum)
51#endif
52
53#ifdef __GNUC__
54RAPIDJSON_DIAG_PUSH
55RAPIDJSON_DIAG_OFF(effc++)
56#endif
57
58//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
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)
68//!@endcond
69
70/*! \def RAPIDJSON_PARSE_ERROR_NORETURN
71 \ingroup RAPIDJSON_ERRORS
72 \brief Macro to indicate a parse error.
73 \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
74 \param offset position of the error in JSON input (\c size_t)
75
76 This macros can be used as a customization point for the internal
77 error handling mechanism of RapidJSON.
78
79 A common usage model is to throw an exception instead of requiring the
80 caller to explicitly check the \ref rapidjson::GenericReader::Parse's
81 return value:
82
83 \code
84 #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \
85 throw ParseException(parseErrorCode, #parseErrorCode, offset)
86
87 #include <stdexcept> // std::runtime_error
88 #include "rapidjson/error/error.h" // rapidjson::ParseResult
89
90 struct ParseException : std::runtime_error, rapidjson::ParseResult {
91 ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset)
92 : std::runtime_error(msg), ParseResult(code, offset) {}
93 };
94
95 #include "rapidjson/reader.h"
96 \endcode
97
98 \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse
99 */
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
108/*! \def RAPIDJSON_PARSE_ERROR
109 \ingroup RAPIDJSON_ERRORS
110 \brief (Internal) macro to indicate and handle a parse error.
111 \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
112 \param offset position of the error in JSON input (\c size_t)
113
114 Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing.
115
116 \see RAPIDJSON_PARSE_ERROR_NORETURN
117 \hideinitializer
118 */
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
129RAPIDJSON_NAMESPACE_BEGIN
130
131///////////////////////////////////////////////////////////////////////////////
132// ParseFlag
133
134/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS
135 \ingroup RAPIDJSON_CONFIG
136 \brief User-defined kParseDefaultFlags definition.
137
138 User can define this as any \c ParseFlag combinations.
139*/
140#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS
141#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
142#endif
143
144//! Combination of parseFlags
145/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
146 */
148 kParseNoFlags = 0, //!< No flags are set.
149 kParseInsituFlag = 1, //!< In-situ(destructive) parsing.
150 kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
151 kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing.
152 kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
153 kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower).
154 kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments.
155 kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings.
156 kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays.
157 kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
158 kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
160
161///////////////////////////////////////////////////////////////////////////////
162// Handler
163
164/*! \class rapidjson::Handler
165 \brief Concept for receiving events from GenericReader upon parsing.
166 The functions return true if no error occurs. If they return false,
167 the event publisher should terminate the process.
168\code
169concept Handler {
170 typename Ch;
171
172 bool Null();
173 bool Bool(bool b);
174 bool Int(int i);
175 bool Uint(unsigned i);
176 bool Int64(int64_t i);
177 bool Uint64(uint64_t i);
178 bool Double(double d);
179 /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
180 bool RawNumber(const Ch* str, SizeType length, bool copy);
181 bool String(const Ch* str, SizeType length, bool copy);
182 bool StartObject();
183 bool Key(const Ch* str, SizeType length, bool copy);
184 bool EndObject(SizeType memberCount);
185 bool StartArray();
186 bool EndArray(SizeType elementCount);
187};
188\endcode
189*/
190///////////////////////////////////////////////////////////////////////////////
191// BaseReaderHandler
192
193//! Default implementation of Handler.
194/*! This can be used as base class of any reader handler.
195 \note implements Handler concept
196*/
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(); }
211 /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
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
221///////////////////////////////////////////////////////////////////////////////
222// StreamLocalCopy
223
224namespace internal {
225
226template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
227class StreamLocalCopy;
228
229//! Do copy optimization.
230template<typename Stream>
231class StreamLocalCopy<Stream, 1> {
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
244//! Keep reference.
245template<typename Stream>
246class StreamLocalCopy<Stream, 0> {
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
258///////////////////////////////////////////////////////////////////////////////
259// SkipWhitespace
260
261//! Skip the JSON white spaces in a stream.
262/*! \param is A input stream for skipping white spaces.
263 \note This function has SSE2/SSE4.2 specialization.
264*/
265template<typename InputStream>
267 internal::StreamLocalCopy<InputStream> copy(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
282//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
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
333//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
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
418//! Skip whitespace with ARM Neon instructions, testing 16 8-byte characters at once.
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(reinterpret_cast<uint64x2_t>(x), 0); // extract
449 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
450
451 if (low == 0) {
452 if (high != 0) {
453 int lz =__builtin_clzll(high);;
454 return p + 8 + (lz >> 3);
455 }
456 } else {
457 int lz = __builtin_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(reinterpret_cast<uint64x2_t>(x), 0); // extract
485 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
486
487 if (low == 0) {
488 if (high != 0) {
489 int lz = __builtin_clzll(high);
490 return p + 8 + (lz >> 3);
491 }
492 } else {
493 int lz = __builtin_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
504//! Template function specialization for InsituStringStream
505template<> inline void SkipWhitespace(InsituStringStream& is) {
506 is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
507}
508
509//! Template function specialization for StringStream
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
519///////////////////////////////////////////////////////////////////////////////
520// GenericReader
521
522//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator.
523/*! GenericReader parses JSON text from a stream, and send events synchronously to an
524 object implementing Handler concept.
525
526 It needs to allocate a stack for storing a single decoded string during
527 non-destructive parsing.
528
529 For in-situ parsing, the decoded string is directly written to the source
530 text string, no temporary buffer is required.
531
532 A GenericReader object can be reused for parsing multiple JSON text.
533
534 \tparam SourceEncoding Encoding of the input stream.
535 \tparam TargetEncoding Encoding of the parse output.
536 \tparam StackAllocator Allocator type for stack.
537*/
538template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
540public:
541 typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type
542
543 //! Constructor.
544 /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
545 \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
546 */
547 GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
548
549 //! Parse JSON text.
550 /*! \tparam parseFlags Combination of \ref ParseFlag.
551 \tparam InputStream Type of input stream, implementing Stream concept.
552 \tparam Handler Type of handler, implementing Handler concept.
553 \param is Input stream to be parsed.
554 \param handler The handler to receive events.
555 \return Whether the parsing is successful.
556 */
557 template <unsigned parseFlags, typename InputStream, typename Handler>
561
562 parseResult_.Clear();
563
564 ClearStackOnExit scope(*this);
565
568
569 if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) {
572 }
573 else {
576
580
581 if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) {
584 }
585 }
586 }
587
588 return parseResult_;
589 }
590
591 //! Parse JSON text (with \ref kParseDefaultFlags)
592 /*! \tparam InputStream Type of input stream, implementing Stream concept
593 \tparam Handler Type of handler, implementing Handler concept.
594 \param is Input stream to be parsed.
595 \param handler The handler to receive events.
596 \return Whether the parsing is successful.
597 */
598 template <typename InputStream, typename Handler>
602
603 //! Initialize JSON text token-by-token parsing
604 /*!
605 */
607 parseResult_.Clear();
608 state_ = IterativeParsingStartState;
609 }
610
611 //! Parse one token from JSON text
612 /*! \tparam InputStream Type of input stream, implementing Stream concept
613 \tparam Handler Type of handler, implementing Handler concept.
614 \param is Input stream to be parsed.
615 \param handler The handler to receive events.
616 \return Whether the parsing is successful.
617 */
618 template <unsigned parseFlags, typename InputStream, typename Handler>
620 while (RAPIDJSON_LIKELY(is.Peek() != '\0')) {
622
623 Token t = Tokenize(is.Peek());
624 IterativeParsingState n = Predict(state_, t);
625 IterativeParsingState d = Transit<parseFlags>(state_, t, n, is, handler);
626
627 // If we've finished or hit an error...
628 if (RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d))) {
629 // Report errors.
630 if (d == IterativeParsingErrorState) {
631 HandleError(state_, is);
632 return false;
633 }
634
635 // Transition to the finish state.
636 RAPIDJSON_ASSERT(d == IterativeParsingFinishState);
637 state_ = d;
638
639 // If StopWhenDone is not set...
641 // ... and extra non-whitespace data is found...
643 if (is.Peek() != '\0') {
644 // ... this is considered an error.
645 HandleError(state_, is);
646 return false;
647 }
648 }
649
650 // Success! We are done!
651 return true;
652 }
653
654 // Transition to the new state.
655 state_ = d;
656
657 // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now.
658 if (!IsIterativeParsingDelimiterState(n))
659 return true;
660 }
661
662 // We reached the end of file.
663 stack_.Clear();
664
665 if (state_ != IterativeParsingFinishState) {
666 HandleError(state_, is);
667 return false;
668 }
669
670 return true;
671 }
672
673 //! Check if token-by-token parsing JSON text is complete
674 /*! \return Whether the JSON has been fully decoded.
675 */
677 return IsIterativeParsingCompleteState(state_);
678 }
679
680 //! Whether a parse error has occured in the last parsing.
681 bool HasParseError() const { return parseResult_.IsError(); }
682
683 //! Get the \ref ParseErrorCode of last parsing.
684 ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
685
686 //! Get the position of last parsing error in input, 0 otherwise.
687 size_t GetErrorOffset() const { return parseResult_.Offset(); }
688
689protected:
690 void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
691
692private:
693 // Prohibit copy constructor & assignment operator.
694 GenericReader(const GenericReader&);
695 GenericReader& operator=(const GenericReader&);
696
697 void ClearStack() { stack_.Clear(); }
698
699 // clear stack on any exit from ParseStream, e.g. due to exception
700 struct ClearStackOnExit {
701 explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
702 ~ClearStackOnExit() { r_.ClearStack(); }
703 private:
704 GenericReader& r_;
705 ClearStackOnExit(const ClearStackOnExit&);
706 ClearStackOnExit& operator=(const ClearStackOnExit&);
707 };
708
709 template<unsigned parseFlags, typename InputStream>
710 void SkipWhitespaceAndComments(InputStream& is) {
711 SkipWhitespace(is);
712
713 if (parseFlags & kParseCommentsFlag) {
714 while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) {
715 if (Consume(is, '*')) {
716 while (true) {
717 if (RAPIDJSON_UNLIKELY(is.Peek() == '\0'))
718 RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
719 else if (Consume(is, '*')) {
720 if (Consume(is, '/'))
721 break;
722 }
723 else
724 is.Take();
725 }
726 }
727 else if (RAPIDJSON_LIKELY(Consume(is, '/')))
728 while (is.Peek() != '\0' && is.Take() != '\n') {}
729 else
730 RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
731
732 SkipWhitespace(is);
733 }
734 }
735 }
736
737 // Parse object: { string : value, ... }
738 template<unsigned parseFlags, typename InputStream, typename Handler>
739 void ParseObject(InputStream& is, Handler& handler) {
740 RAPIDJSON_ASSERT(is.Peek() == '{');
741 is.Take(); // Skip '{'
742
743 if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
744 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
745
746 SkipWhitespaceAndComments<parseFlags>(is);
747 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
748
749 if (Consume(is, '}')) {
750 if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object
751 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
752 return;
753 }
754
755 for (SizeType memberCount = 0;;) {
756 if (RAPIDJSON_UNLIKELY(is.Peek() != '"'))
757 RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
758
759 ParseString<parseFlags>(is, handler, true);
760 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
761
762 SkipWhitespaceAndComments<parseFlags>(is);
763 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
764
765 if (RAPIDJSON_UNLIKELY(!Consume(is, ':')))
766 RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
767
768 SkipWhitespaceAndComments<parseFlags>(is);
769 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
770
771 ParseValue<parseFlags>(is, handler);
772 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
773
774 SkipWhitespaceAndComments<parseFlags>(is);
775 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
776
777 ++memberCount;
778
779 switch (is.Peek()) {
780 case ',':
781 is.Take();
782 SkipWhitespaceAndComments<parseFlags>(is);
783 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
784 break;
785 case '}':
786 is.Take();
787 if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
788 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
789 return;
790 default:
791 RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy
792 }
793
794 if (parseFlags & kParseTrailingCommasFlag) {
795 if (is.Peek() == '}') {
796 if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
797 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
798 is.Take();
799 return;
800 }
801 }
802 }
803 }
804
805 // Parse array: [ value, ... ]
806 template<unsigned parseFlags, typename InputStream, typename Handler>
807 void ParseArray(InputStream& is, Handler& handler) {
808 RAPIDJSON_ASSERT(is.Peek() == '[');
809 is.Take(); // Skip '['
810
811 if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
812 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
813
814 SkipWhitespaceAndComments<parseFlags>(is);
815 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
816
817 if (Consume(is, ']')) {
818 if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array
819 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
820 return;
821 }
822
823 for (SizeType elementCount = 0;;) {
824 ParseValue<parseFlags>(is, handler);
825 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
826
827 ++elementCount;
828 SkipWhitespaceAndComments<parseFlags>(is);
829 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
830
831 if (Consume(is, ',')) {
832 SkipWhitespaceAndComments<parseFlags>(is);
833 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
834 }
835 else if (Consume(is, ']')) {
836 if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
837 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
838 return;
839 }
840 else
841 RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
842
843 if (parseFlags & kParseTrailingCommasFlag) {
844 if (is.Peek() == ']') {
845 if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
846 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
847 is.Take();
848 return;
849 }
850 }
851 }
852 }
853
854 template<unsigned parseFlags, typename InputStream, typename Handler>
855 void ParseNull(InputStream& is, Handler& handler) {
856 RAPIDJSON_ASSERT(is.Peek() == 'n');
857 is.Take();
858
859 if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) {
860 if (RAPIDJSON_UNLIKELY(!handler.Null()))
861 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
862 }
863 else
864 RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
865 }
866
867 template<unsigned parseFlags, typename InputStream, typename Handler>
868 void ParseTrue(InputStream& is, Handler& handler) {
869 RAPIDJSON_ASSERT(is.Peek() == 't');
870 is.Take();
871
872 if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) {
873 if (RAPIDJSON_UNLIKELY(!handler.Bool(true)))
874 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
875 }
876 else
877 RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
878 }
879
880 template<unsigned parseFlags, typename InputStream, typename Handler>
881 void ParseFalse(InputStream& is, Handler& handler) {
882 RAPIDJSON_ASSERT(is.Peek() == 'f');
883 is.Take();
884
885 if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) {
886 if (RAPIDJSON_UNLIKELY(!handler.Bool(false)))
887 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
888 }
889 else
890 RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
891 }
892
893 template<typename InputStream>
894 RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
895 if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
896 is.Take();
897 return true;
898 }
899 else
900 return false;
901 }
902
903 // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
904 template<typename InputStream>
905 unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
906 unsigned codepoint = 0;
907 for (int i = 0; i < 4; i++) {
908 Ch c = is.Peek();
909 codepoint <<= 4;
910 codepoint += static_cast<unsigned>(c);
911 if (c >= '0' && c <= '9')
912 codepoint -= '0';
913 else if (c >= 'A' && c <= 'F')
914 codepoint -= 'A' - 10;
915 else if (c >= 'a' && c <= 'f')
916 codepoint -= 'a' - 10;
917 else {
918 RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset);
919 RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
920 }
921 is.Take();
922 }
923 return codepoint;
924 }
925
926 template <typename CharType>
927 class StackStream {
928 public:
929 typedef CharType Ch;
930
931 StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
932 RAPIDJSON_FORCEINLINE void Put(Ch c) {
933 *stack_.template Push<Ch>() = c;
934 ++length_;
935 }
936
937 RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
938 length_ += count;
939 return stack_.template Push<Ch>(count);
940 }
941
942 size_t Length() const { return length_; }
943
944 Ch* Pop() {
945 return stack_.template Pop<Ch>(length_);
946 }
947
948 private:
949 StackStream(const StackStream&);
950 StackStream& operator=(const StackStream&);
951
952 internal::Stack<StackAllocator>& stack_;
953 SizeType length_;
954 };
955
956 // Parse string and generate String event. Different code paths for kParseInsituFlag.
957 template<unsigned parseFlags, typename InputStream, typename Handler>
958 void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
959 internal::StreamLocalCopy<InputStream> copy(is);
960 InputStream& s(copy.s);
961
962 RAPIDJSON_ASSERT(s.Peek() == '\"');
963 s.Take(); // Skip '\"'
964
965 bool success = false;
966 if (parseFlags & kParseInsituFlag) {
967 typename InputStream::Ch *head = s.PutBegin();
968 ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
969 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
970 size_t length = s.PutEnd(head) - 1;
971 RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
972 const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
973 success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
974 }
975 else {
976 StackStream<typename TargetEncoding::Ch> stackStream(stack_);
977 ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
978 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
979 SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
980 const typename TargetEncoding::Ch* const str = stackStream.Pop();
981 success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
982 }
983 if (RAPIDJSON_UNLIKELY(!success))
984 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
985 }
986
987 // Parse string to an output is
988 // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
989 template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
990 RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
991//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
992#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
993 static const char escape[256] = {
994 Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
995 Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
996 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
997 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
998 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
999 };
1000#undef Z16
1001//!@endcond
1002
1003 for (;;) {
1004 // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
1005 if (!(parseFlags & kParseValidateEncodingFlag))
1006 ScanCopyUnescapedString(is, os);
1007
1008 Ch c = is.Peek();
1009 if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape
1010 size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset
1011 is.Take();
1012 Ch e = is.Peek();
1013 if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
1014 is.Take();
1015 os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
1016 }
1017 else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode
1018 is.Take();
1019 unsigned codepoint = ParseHex4(is, escapeOffset);
1020 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1021 if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) {
1022 // Handle UTF-16 surrogate pair
1023 if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
1024 RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
1025 unsigned codepoint2 = ParseHex4(is, escapeOffset);
1026 RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1027 if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
1028 RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
1029 codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
1030 }
1031 TEncoding::Encode(os, codepoint);
1032 }
1033 else
1034 RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset);
1035 }
1036 else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote
1037 is.Take();
1038 os.Put('\0'); // null-terminate the string
1039 return;
1040 }
1041 else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
1042 if (c == '\0')
1043 RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());
1044 else
1045 RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());
1046 }
1047 else {
1048 size_t offset = is.Tell();
1049 if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
1050 !Transcoder<SEncoding, TEncoding>::Validate(is, os) :
1051 !Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
1053 }
1054 }
1055 }
1056
1057 template<typename InputStream, typename OutputStream>
1058 static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
1059 // Do nothing for generic version
1060 }
1061
1062#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
1063 // StringStream -> StackStream<char>
1064 static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
1065 const char* p = is.src_;
1066
1067 // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1068 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1069 while (p != nextAligned)
1070 if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1071 is.src_ = p;
1072 return;
1073 }
1074 else
1075 os.Put(*p++);
1076
1077 // The rest of string using SIMD
1078 static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1079 static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1080 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
1081 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
1082 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
1083 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
1084
1085 for (;; p += 16) {
1086 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
1087 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1088 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1089 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
1090 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1091 unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1092 if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
1093 SizeType length;
1094 #ifdef _MSC_VER // Find the index of first escaped
1095 unsigned long offset;
1096 _BitScanForward(&offset, r);
1097 length = offset;
1098 #else
1099 length = static_cast<SizeType>(__builtin_ffs(r) - 1);
1100 #endif
1101 if (length != 0) {
1102 char* q = reinterpret_cast<char*>(os.Push(length));
1103 for (size_t i = 0; i < length; i++)
1104 q[i] = p[i];
1105
1106 p += length;
1107 }
1108 break;
1109 }
1110 _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
1111 }
1112
1113 is.src_ = p;
1114 }
1115
1116 // InsituStringStream -> InsituStringStream
1117 static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
1118 RAPIDJSON_ASSERT(&is == &os);
1119 (void)os;
1120
1121 if (is.src_ == is.dst_) {
1122 SkipUnescapedString(is);
1123 return;
1124 }
1125
1126 char* p = is.src_;
1127 char *q = is.dst_;
1128
1129 // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1130 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1131 while (p != nextAligned)
1132 if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1133 is.src_ = p;
1134 is.dst_ = q;
1135 return;
1136 }
1137 else
1138 *q++ = *p++;
1139
1140 // The rest of string using SIMD
1141 static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1142 static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1143 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
1144 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
1145 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
1146 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
1147
1148 for (;; p += 16, q += 16) {
1149 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
1150 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1151 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1152 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
1153 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1154 unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1155 if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
1156 size_t length;
1157#ifdef _MSC_VER // Find the index of first escaped
1158 unsigned long offset;
1159 _BitScanForward(&offset, r);
1160 length = offset;
1161#else
1162 length = static_cast<size_t>(__builtin_ffs(r) - 1);
1163#endif
1164 for (const char* pend = p + length; p != pend; )
1165 *q++ = *p++;
1166 break;
1167 }
1168 _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s);
1169 }
1170
1171 is.src_ = p;
1172 is.dst_ = q;
1173 }
1174
1175 // When read/write pointers are the same for insitu stream, just skip unescaped characters
1176 static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
1177 RAPIDJSON_ASSERT(is.src_ == is.dst_);
1178 char* p = is.src_;
1179
1180 // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1181 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1182 for (; p != nextAligned; p++)
1183 if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1184 is.src_ = is.dst_ = p;
1185 return;
1186 }
1187
1188 // The rest of string using SIMD
1189 static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
1190 static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
1191 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
1192 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
1193 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
1194 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
1195
1196 for (;; p += 16) {
1197 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
1198 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
1199 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
1200 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
1201 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
1202 unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
1203 if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
1204 size_t length;
1205#ifdef _MSC_VER // Find the index of first escaped
1206 unsigned long offset;
1207 _BitScanForward(&offset, r);
1208 length = offset;
1209#else
1210 length = static_cast<size_t>(__builtin_ffs(r) - 1);
1211#endif
1212 p += length;
1213 break;
1214 }
1215 }
1216
1217 is.src_ = is.dst_ = p;
1218 }
1219#elif defined(RAPIDJSON_NEON)
1220 // StringStream -> StackStream<char>
1221 static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
1222 const char* p = is.src_;
1223
1224 // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1225 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1226 while (p != nextAligned)
1227 if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1228 is.src_ = p;
1229 return;
1230 }
1231 else
1232 os.Put(*p++);
1233
1234 // The rest of string using SIMD
1235 const uint8x16_t s0 = vmovq_n_u8('"');
1236 const uint8x16_t s1 = vmovq_n_u8('\\');
1237 const uint8x16_t s2 = vmovq_n_u8('\b');
1238 const uint8x16_t s3 = vmovq_n_u8(32);
1239
1240 for (;; p += 16) {
1241 const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
1242 uint8x16_t x = vceqq_u8(s, s0);
1243 x = vorrq_u8(x, vceqq_u8(s, s1));
1244 x = vorrq_u8(x, vceqq_u8(s, s2));
1245 x = vorrq_u8(x, vcltq_u8(s, s3));
1246
1247 x = vrev64q_u8(x); // Rev in 64
1248 uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
1249 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
1250
1251 SizeType length = 0;
1252 bool escaped = false;
1253 if (low == 0) {
1254 if (high != 0) {
1255 unsigned lz = (unsigned)__builtin_clzll(high);;
1256 length = 8 + (lz >> 3);
1257 escaped = true;
1258 }
1259 } else {
1260 unsigned lz = (unsigned)__builtin_clzll(low);;
1261 length = lz >> 3;
1262 escaped = true;
1263 }
1264 if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
1265 if (length != 0) {
1266 char* q = reinterpret_cast<char*>(os.Push(length));
1267 for (size_t i = 0; i < length; i++)
1268 q[i] = p[i];
1269
1270 p += length;
1271 }
1272 break;
1273 }
1274 vst1q_u8(reinterpret_cast<uint8_t *>(os.Push(16)), s);
1275 }
1276
1277 is.src_ = p;
1278 }
1279
1280 // InsituStringStream -> InsituStringStream
1281 static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
1282 RAPIDJSON_ASSERT(&is == &os);
1283 (void)os;
1284
1285 if (is.src_ == is.dst_) {
1286 SkipUnescapedString(is);
1287 return;
1288 }
1289
1290 char* p = is.src_;
1291 char *q = is.dst_;
1292
1293 // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1294 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1295 while (p != nextAligned)
1296 if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1297 is.src_ = p;
1298 is.dst_ = q;
1299 return;
1300 }
1301 else
1302 *q++ = *p++;
1303
1304 // The rest of string using SIMD
1305 const uint8x16_t s0 = vmovq_n_u8('"');
1306 const uint8x16_t s1 = vmovq_n_u8('\\');
1307 const uint8x16_t s2 = vmovq_n_u8('\b');
1308 const uint8x16_t s3 = vmovq_n_u8(32);
1309
1310 for (;; p += 16, q += 16) {
1311 const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
1312 uint8x16_t x = vceqq_u8(s, s0);
1313 x = vorrq_u8(x, vceqq_u8(s, s1));
1314 x = vorrq_u8(x, vceqq_u8(s, s2));
1315 x = vorrq_u8(x, vcltq_u8(s, s3));
1316
1317 x = vrev64q_u8(x); // Rev in 64
1318 uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
1319 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
1320
1321 SizeType length = 0;
1322 bool escaped = false;
1323 if (low == 0) {
1324 if (high != 0) {
1325 unsigned lz = (unsigned)__builtin_clzll(high);
1326 length = 8 + (lz >> 3);
1327 escaped = true;
1328 }
1329 } else {
1330 unsigned lz = (unsigned)__builtin_clzll(low);
1331 length = lz >> 3;
1332 escaped = true;
1333 }
1334 if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
1335 for (const char* pend = p + length; p != pend; ) {
1336 *q++ = *p++;
1337 }
1338 break;
1339 }
1340 vst1q_u8(reinterpret_cast<uint8_t *>(q), s);
1341 }
1342
1343 is.src_ = p;
1344 is.dst_ = q;
1345 }
1346
1347 // When read/write pointers are the same for insitu stream, just skip unescaped characters
1348 static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
1349 RAPIDJSON_ASSERT(is.src_ == is.dst_);
1350 char* p = is.src_;
1351
1352 // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
1353 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
1354 for (; p != nextAligned; p++)
1355 if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
1356 is.src_ = is.dst_ = p;
1357 return;
1358 }
1359
1360 // The rest of string using SIMD
1361 const uint8x16_t s0 = vmovq_n_u8('"');
1362 const uint8x16_t s1 = vmovq_n_u8('\\');
1363 const uint8x16_t s2 = vmovq_n_u8('\b');
1364 const uint8x16_t s3 = vmovq_n_u8(32);
1365
1366 for (;; p += 16) {
1367 const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
1368 uint8x16_t x = vceqq_u8(s, s0);
1369 x = vorrq_u8(x, vceqq_u8(s, s1));
1370 x = vorrq_u8(x, vceqq_u8(s, s2));
1371 x = vorrq_u8(x, vcltq_u8(s, s3));
1372
1373 x = vrev64q_u8(x); // Rev in 64
1374 uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
1375 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
1376
1377 if (low == 0) {
1378 if (high != 0) {
1379 int lz = __builtin_clzll(high);
1380 p += 8 + (lz >> 3);
1381 break;
1382 }
1383 } else {
1384 int lz = __builtin_clzll(low);
1385 p += lz >> 3;
1386 break;
1387 }
1388 }
1389
1390 is.src_ = is.dst_ = p;
1391 }
1392#endif // RAPIDJSON_NEON
1393
1394 template<typename InputStream, bool backup, bool pushOnTake>
1395 class NumberStream;
1396
1397 template<typename InputStream>
1398 class NumberStream<InputStream, false, false> {
1399 public:
1400 typedef typename InputStream::Ch Ch;
1401
1402 NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
1403
1404 RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
1405 RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
1406 RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
1407 RAPIDJSON_FORCEINLINE void Push(char) {}
1408
1409 size_t Tell() { return is.Tell(); }
1410 size_t Length() { return 0; }
1411 const char* Pop() { return 0; }
1412
1413 protected:
1414 NumberStream& operator=(const NumberStream&);
1415
1416 InputStream& is;
1417 };
1418
1419 template<typename InputStream>
1420 class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
1421 typedef NumberStream<InputStream, false, false> Base;
1422 public:
1423 NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
1424
1425 RAPIDJSON_FORCEINLINE Ch TakePush() {
1426 stackStream.Put(static_cast<char>(Base::is.Peek()));
1427 return Base::is.Take();
1428 }
1429
1430 RAPIDJSON_FORCEINLINE void Push(char c) {
1431 stackStream.Put(c);
1432 }
1433
1434 size_t Length() { return stackStream.Length(); }
1435
1436 const char* Pop() {
1437 stackStream.Put('\0');
1438 return stackStream.Pop();
1439 }
1440
1441 private:
1442 StackStream<char> stackStream;
1443 };
1444
1445 template<typename InputStream>
1446 class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
1447 typedef NumberStream<InputStream, true, false> Base;
1448 public:
1449 NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
1450
1451 RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
1452 };
1453
1454 template<unsigned parseFlags, typename InputStream, typename Handler>
1455 void ParseNumber(InputStream& is, Handler& handler) {
1456 internal::StreamLocalCopy<InputStream> copy(is);
1457 NumberStream<InputStream,
1458 ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
1459 ((parseFlags & kParseInsituFlag) == 0) :
1460 ((parseFlags & kParseFullPrecisionFlag) != 0),
1461 (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
1462 (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
1463
1464 size_t startOffset = s.Tell();
1465 double d = 0.0;
1466 bool useNanOrInf = false;
1467
1468 // Parse minus
1469 bool minus = Consume(s, '-');
1470
1471 // Parse int: zero / ( digit1-9 *DIGIT )
1472 unsigned i = 0;
1473 uint64_t i64 = 0;
1474 bool use64bit = false;
1475 int significandDigit = 0;
1476 if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) {
1477 i = 0;
1478 s.TakePush();
1479 }
1480 else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) {
1481 i = static_cast<unsigned>(s.TakePush() - '0');
1482
1483 if (minus)
1484 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1485 if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648
1486 if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) {
1487 i64 = i;
1488 use64bit = true;
1489 break;
1490 }
1491 }
1492 i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
1493 significandDigit++;
1494 }
1495 else
1496 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1497 if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295
1498 if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {
1499 i64 = i;
1500 use64bit = true;
1501 break;
1502 }
1503 }
1504 i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
1505 significandDigit++;
1506 }
1507 }
1508 // Parse NaN or Infinity here
1509 else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
1510 if (Consume(s, 'N')) {
1511 if (Consume(s, 'a') && Consume(s, 'N')) {
1512 d = std::numeric_limits<double>::quiet_NaN();
1513 useNanOrInf = true;
1514 }
1515 }
1516 else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) {
1517 if (Consume(s, 'n') && Consume(s, 'f')) {
1518 d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
1519 useNanOrInf = true;
1520
1521 if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
1522 && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) {
1523 RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
1524 }
1525 }
1526 }
1527
1528 if (RAPIDJSON_UNLIKELY(!useNanOrInf)) {
1529 RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
1530 }
1531 }
1532 else
1533 RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
1534
1535 // Parse 64bit int
1536 bool useDouble = false;
1537 if (use64bit) {
1538 if (minus)
1539 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1540 if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
1541 if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
1542 d = static_cast<double>(i64);
1543 useDouble = true;
1544 break;
1545 }
1546 i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1547 significandDigit++;
1548 }
1549 else
1550 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1551 if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615
1552 if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {
1553 d = static_cast<double>(i64);
1554 useDouble = true;
1555 break;
1556 }
1557 i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1558 significandDigit++;
1559 }
1560 }
1561
1562 // Force double for big integer
1563 if (useDouble) {
1564 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1565 if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0
1566 RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
1567 d = d * 10 + (s.TakePush() - '0');
1568 }
1569 }
1570
1571 // Parse frac = decimal-point 1*DIGIT
1572 int expFrac = 0;
1573 size_t decimalPosition;
1574 if (Consume(s, '.')) {
1575 decimalPosition = s.Length();
1576
1577 if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
1578 RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
1579
1580 if (!useDouble) {
1581#if RAPIDJSON_64BIT
1582 // Use i64 to store significand in 64-bit architecture
1583 if (!use64bit)
1584 i64 = i;
1585
1586 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1587 if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
1588 break;
1589 else {
1590 i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1591 --expFrac;
1592 if (i64 != 0)
1593 significandDigit++;
1594 }
1595 }
1596
1597 d = static_cast<double>(i64);
1598#else
1599 // Use double to store significand in 32-bit architecture
1600 d = static_cast<double>(use64bit ? i64 : i);
1601#endif
1602 useDouble = true;
1603 }
1604
1605 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1606 if (significandDigit < 17) {
1607 d = d * 10.0 + (s.TakePush() - '0');
1608 --expFrac;
1609 if (RAPIDJSON_LIKELY(d > 0.0))
1610 significandDigit++;
1611 }
1612 else
1613 s.TakePush();
1614 }
1615 }
1616 else
1617 decimalPosition = s.Length(); // decimal position at the end of integer.
1618
1619 // Parse exp = e [ minus / plus ] 1*DIGIT
1620 int exp = 0;
1621 if (Consume(s, 'e') || Consume(s, 'E')) {
1622 if (!useDouble) {
1623 d = static_cast<double>(use64bit ? i64 : i);
1624 useDouble = true;
1625 }
1626
1627 bool expMinus = false;
1628 if (Consume(s, '+'))
1629 ;
1630 else if (Consume(s, '-'))
1631 expMinus = true;
1632
1633 if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1634 exp = static_cast<int>(s.Take() - '0');
1635 if (expMinus) {
1636 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1637 exp = exp * 10 + static_cast<int>(s.Take() - '0');
1638 if (exp >= 214748364) { // Issue #313: prevent overflow exponent
1639 while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent
1640 s.Take();
1641 }
1642 }
1643 }
1644 else { // positive exp
1645 int maxExp = 308 - expFrac;
1646 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1647 exp = exp * 10 + static_cast<int>(s.Take() - '0');
1648 if (RAPIDJSON_UNLIKELY(exp > maxExp))
1649 RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
1650 }
1651 }
1652 }
1653 else
1654 RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
1655
1656 if (expMinus)
1657 exp = -exp;
1658 }
1659
1660 // Finish parsing, call event according to the type of number.
1661 bool cont = true;
1662
1663 if (parseFlags & kParseNumbersAsStringsFlag) {
1664 if (parseFlags & kParseInsituFlag) {
1665 s.Pop(); // Pop stack no matter if it will be used or not.
1666 typename InputStream::Ch* head = is.PutBegin();
1667 const size_t length = s.Tell() - startOffset;
1668 RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
1669 // unable to insert the \0 character here, it will erase the comma after this number
1670 const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
1671 cont = handler.RawNumber(str, SizeType(length), false);
1672 }
1673 else {
1674 SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
1675 StringStream srcStream(s.Pop());
1676 StackStream<typename TargetEncoding::Ch> dstStream(stack_);
1677 while (numCharsToCopy--) {
1678 Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);
1679 }
1680 dstStream.Put('\0');
1681 const typename TargetEncoding::Ch* str = dstStream.Pop();
1682 const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;
1683 cont = handler.RawNumber(str, SizeType(length), true);
1684 }
1685 }
1686 else {
1687 size_t length = s.Length();
1688 const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
1689
1690 if (useDouble) {
1691 int p = exp + expFrac;
1692 if (parseFlags & kParseFullPrecisionFlag)
1693 d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
1694 else
1695 d = internal::StrtodNormalPrecision(d, p);
1696
1697 cont = handler.Double(minus ? -d : d);
1698 }
1699 else if (useNanOrInf) {
1700 cont = handler.Double(d);
1701 }
1702 else {
1703 if (use64bit) {
1704 if (minus)
1705 cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
1706 else
1707 cont = handler.Uint64(i64);
1708 }
1709 else {
1710 if (minus)
1711 cont = handler.Int(static_cast<int32_t>(~i + 1));
1712 else
1713 cont = handler.Uint(i);
1714 }
1715 }
1716 }
1717 if (RAPIDJSON_UNLIKELY(!cont))
1718 RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset);
1719 }
1720
1721 // Parse any JSON value
1722 template<unsigned parseFlags, typename InputStream, typename Handler>
1723 void ParseValue(InputStream& is, Handler& handler) {
1724 switch (is.Peek()) {
1725 case 'n': ParseNull <parseFlags>(is, handler); break;
1726 case 't': ParseTrue <parseFlags>(is, handler); break;
1727 case 'f': ParseFalse <parseFlags>(is, handler); break;
1728 case '"': ParseString<parseFlags>(is, handler); break;
1729 case '{': ParseObject<parseFlags>(is, handler); break;
1730 case '[': ParseArray <parseFlags>(is, handler); break;
1731 default :
1732 ParseNumber<parseFlags>(is, handler);
1733 break;
1734
1735 }
1736 }
1737
1738 // Iterative Parsing
1739
1740 // States
1741 enum IterativeParsingState {
1742 IterativeParsingFinishState = 0, // sink states at top
1743 IterativeParsingErrorState, // sink states at top
1744 IterativeParsingStartState,
1745
1746 // Object states
1747 IterativeParsingObjectInitialState,
1748 IterativeParsingMemberKeyState,
1749 IterativeParsingMemberValueState,
1750 IterativeParsingObjectFinishState,
1751
1752 // Array states
1753 IterativeParsingArrayInitialState,
1754 IterativeParsingElementState,
1755 IterativeParsingArrayFinishState,
1756
1757 // Single value state
1758 IterativeParsingValueState,
1759
1760 // Delimiter states (at bottom)
1761 IterativeParsingElementDelimiterState,
1762 IterativeParsingMemberDelimiterState,
1763 IterativeParsingKeyValueDelimiterState,
1764
1765 cIterativeParsingStateCount
1766 };
1767
1768 // Tokens
1769 enum Token {
1770 LeftBracketToken = 0,
1771 RightBracketToken,
1772
1773 LeftCurlyBracketToken,
1774 RightCurlyBracketToken,
1775
1776 CommaToken,
1777 ColonToken,
1778
1779 StringToken,
1780 FalseToken,
1781 TrueToken,
1782 NullToken,
1783 NumberToken,
1784
1785 kTokenCount
1786 };
1787
1788 RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
1789
1790//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
1791#define N NumberToken
1792#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
1793 // Maps from ASCII to Token
1794 static const unsigned char tokenMap[256] = {
1795 N16, // 00~0F
1796 N16, // 10~1F
1797 N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
1798 N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
1799 N16, // 40~4F
1800 N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
1801 N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
1802 N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
1803 N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
1804 };
1805#undef N
1806#undef N16
1807//!@endcond
1808
1809 if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
1810 return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
1811 else
1812 return NumberToken;
1813 }
1814
1815 RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
1816 // current state x one lookahead token -> new state
1817 static const char G[cIterativeParsingStateCount][kTokenCount] = {
1818 // Finish(sink state)
1819 {
1820 IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1821 IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1822 IterativeParsingErrorState
1823 },
1824 // Error(sink state)
1825 {
1826 IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1827 IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1828 IterativeParsingErrorState
1829 },
1830 // Start
1831 {
1832 IterativeParsingArrayInitialState, // Left bracket
1833 IterativeParsingErrorState, // Right bracket
1834 IterativeParsingObjectInitialState, // Left curly bracket
1835 IterativeParsingErrorState, // Right curly bracket
1836 IterativeParsingErrorState, // Comma
1837 IterativeParsingErrorState, // Colon
1838 IterativeParsingValueState, // String
1839 IterativeParsingValueState, // False
1840 IterativeParsingValueState, // True
1841 IterativeParsingValueState, // Null
1842 IterativeParsingValueState // Number
1843 },
1844 // ObjectInitial
1845 {
1846 IterativeParsingErrorState, // Left bracket
1847 IterativeParsingErrorState, // Right bracket
1848 IterativeParsingErrorState, // Left curly bracket
1849 IterativeParsingObjectFinishState, // Right curly bracket
1850 IterativeParsingErrorState, // Comma
1851 IterativeParsingErrorState, // Colon
1852 IterativeParsingMemberKeyState, // String
1853 IterativeParsingErrorState, // False
1854 IterativeParsingErrorState, // True
1855 IterativeParsingErrorState, // Null
1856 IterativeParsingErrorState // Number
1857 },
1858 // MemberKey
1859 {
1860 IterativeParsingErrorState, // Left bracket
1861 IterativeParsingErrorState, // Right bracket
1862 IterativeParsingErrorState, // Left curly bracket
1863 IterativeParsingErrorState, // Right curly bracket
1864 IterativeParsingErrorState, // Comma
1865 IterativeParsingKeyValueDelimiterState, // Colon
1866 IterativeParsingErrorState, // String
1867 IterativeParsingErrorState, // False
1868 IterativeParsingErrorState, // True
1869 IterativeParsingErrorState, // Null
1870 IterativeParsingErrorState // Number
1871 },
1872 // MemberValue
1873 {
1874 IterativeParsingErrorState, // Left bracket
1875 IterativeParsingErrorState, // Right bracket
1876 IterativeParsingErrorState, // Left curly bracket
1877 IterativeParsingObjectFinishState, // Right curly bracket
1878 IterativeParsingMemberDelimiterState, // Comma
1879 IterativeParsingErrorState, // Colon
1880 IterativeParsingErrorState, // String
1881 IterativeParsingErrorState, // False
1882 IterativeParsingErrorState, // True
1883 IterativeParsingErrorState, // Null
1884 IterativeParsingErrorState // Number
1885 },
1886 // ObjectFinish(sink state)
1887 {
1888 IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1889 IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1890 IterativeParsingErrorState
1891 },
1892 // ArrayInitial
1893 {
1894 IterativeParsingArrayInitialState, // Left bracket(push Element state)
1895 IterativeParsingArrayFinishState, // Right bracket
1896 IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
1897 IterativeParsingErrorState, // Right curly bracket
1898 IterativeParsingErrorState, // Comma
1899 IterativeParsingErrorState, // Colon
1900 IterativeParsingElementState, // String
1901 IterativeParsingElementState, // False
1902 IterativeParsingElementState, // True
1903 IterativeParsingElementState, // Null
1904 IterativeParsingElementState // Number
1905 },
1906 // Element
1907 {
1908 IterativeParsingErrorState, // Left bracket
1909 IterativeParsingArrayFinishState, // Right bracket
1910 IterativeParsingErrorState, // Left curly bracket
1911 IterativeParsingErrorState, // Right curly bracket
1912 IterativeParsingElementDelimiterState, // Comma
1913 IterativeParsingErrorState, // Colon
1914 IterativeParsingErrorState, // String
1915 IterativeParsingErrorState, // False
1916 IterativeParsingErrorState, // True
1917 IterativeParsingErrorState, // Null
1918 IterativeParsingErrorState // Number
1919 },
1920 // ArrayFinish(sink state)
1921 {
1922 IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1923 IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1924 IterativeParsingErrorState
1925 },
1926 // Single Value (sink state)
1927 {
1928 IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1929 IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1930 IterativeParsingErrorState
1931 },
1932 // ElementDelimiter
1933 {
1934 IterativeParsingArrayInitialState, // Left bracket(push Element state)
1935 IterativeParsingArrayFinishState, // Right bracket
1936 IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
1937 IterativeParsingErrorState, // Right curly bracket
1938 IterativeParsingErrorState, // Comma
1939 IterativeParsingErrorState, // Colon
1940 IterativeParsingElementState, // String
1941 IterativeParsingElementState, // False
1942 IterativeParsingElementState, // True
1943 IterativeParsingElementState, // Null
1944 IterativeParsingElementState // Number
1945 },
1946 // MemberDelimiter
1947 {
1948 IterativeParsingErrorState, // Left bracket
1949 IterativeParsingErrorState, // Right bracket
1950 IterativeParsingErrorState, // Left curly bracket
1951 IterativeParsingObjectFinishState, // Right curly bracket
1952 IterativeParsingErrorState, // Comma
1953 IterativeParsingErrorState, // Colon
1954 IterativeParsingMemberKeyState, // String
1955 IterativeParsingErrorState, // False
1956 IterativeParsingErrorState, // True
1957 IterativeParsingErrorState, // Null
1958 IterativeParsingErrorState // Number
1959 },
1960 // KeyValueDelimiter
1961 {
1962 IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
1963 IterativeParsingErrorState, // Right bracket
1964 IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
1965 IterativeParsingErrorState, // Right curly bracket
1966 IterativeParsingErrorState, // Comma
1967 IterativeParsingErrorState, // Colon
1968 IterativeParsingMemberValueState, // String
1969 IterativeParsingMemberValueState, // False
1970 IterativeParsingMemberValueState, // True
1971 IterativeParsingMemberValueState, // Null
1972 IterativeParsingMemberValueState // Number
1973 },
1974 }; // End of G
1975
1976 return static_cast<IterativeParsingState>(G[state][token]);
1977 }
1978
1979 // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
1980 // May return a new state on state pop.
1981 template <unsigned parseFlags, typename InputStream, typename Handler>
1982 RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
1983 (void)token;
1984
1985 switch (dst) {
1986 case IterativeParsingErrorState:
1987 return dst;
1988
1989 case IterativeParsingObjectInitialState:
1990 case IterativeParsingArrayInitialState:
1991 {
1992 // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
1993 // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
1994 IterativeParsingState n = src;
1995 if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
1996 n = IterativeParsingElementState;
1997 else if (src == IterativeParsingKeyValueDelimiterState)
1998 n = IterativeParsingMemberValueState;
1999 // Push current state.
2000 *stack_.template Push<SizeType>(1) = n;
2001 // Initialize and push the member/element count.
2002 *stack_.template Push<SizeType>(1) = 0;
2003 // Call handler
2004 bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
2005 // On handler short circuits the parsing.
2006 if (!hr) {
2007 RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
2008 return IterativeParsingErrorState;
2009 }
2010 else {
2011 is.Take();
2012 return dst;
2013 }
2014 }
2015
2016 case IterativeParsingMemberKeyState:
2017 ParseString<parseFlags>(is, handler, true);
2018 if (HasParseError())
2019 return IterativeParsingErrorState;
2020 else
2021 return dst;
2022
2023 case IterativeParsingKeyValueDelimiterState:
2024 RAPIDJSON_ASSERT(token == ColonToken);
2025 is.Take();
2026 return dst;
2027
2028 case IterativeParsingMemberValueState:
2029 // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2030 ParseValue<parseFlags>(is, handler);
2031 if (HasParseError()) {
2032 return IterativeParsingErrorState;
2033 }
2034 return dst;
2035
2036 case IterativeParsingElementState:
2037 // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2038 ParseValue<parseFlags>(is, handler);
2039 if (HasParseError()) {
2040 return IterativeParsingErrorState;
2041 }
2042 return dst;
2043
2044 case IterativeParsingMemberDelimiterState:
2045 case IterativeParsingElementDelimiterState:
2046 is.Take();
2047 // Update member/element count.
2048 *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
2049 return dst;
2050
2051 case IterativeParsingObjectFinishState:
2052 {
2053 // Transit from delimiter is only allowed when trailing commas are enabled
2054 if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {
2055 RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell());
2056 return IterativeParsingErrorState;
2057 }
2058 // Get member count.
2059 SizeType c = *stack_.template Pop<SizeType>(1);
2060 // If the object is not empty, count the last member.
2061 if (src == IterativeParsingMemberValueState)
2062 ++c;
2063 // Restore the state.
2064 IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
2065 // Transit to Finish state if this is the topmost scope.
2066 if (n == IterativeParsingStartState)
2067 n = IterativeParsingFinishState;
2068 // Call handler
2069 bool hr = handler.EndObject(c);
2070 // On handler short circuits the parsing.
2071 if (!hr) {
2072 RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
2073 return IterativeParsingErrorState;
2074 }
2075 else {
2076 is.Take();
2077 return n;
2078 }
2079 }
2080
2081 case IterativeParsingArrayFinishState:
2082 {
2083 // Transit from delimiter is only allowed when trailing commas are enabled
2084 if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) {
2085 RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell());
2086 return IterativeParsingErrorState;
2087 }
2088 // Get element count.
2089 SizeType c = *stack_.template Pop<SizeType>(1);
2090 // If the array is not empty, count the last element.
2091 if (src == IterativeParsingElementState)
2092 ++c;
2093 // Restore the state.
2094 IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
2095 // Transit to Finish state if this is the topmost scope.
2096 if (n == IterativeParsingStartState)
2097 n = IterativeParsingFinishState;
2098 // Call handler
2099 bool hr = handler.EndArray(c);
2100 // On handler short circuits the parsing.
2101 if (!hr) {
2102 RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
2103 return IterativeParsingErrorState;
2104 }
2105 else {
2106 is.Take();
2107 return n;
2108 }
2109 }
2110
2111 default:
2112 // This branch is for IterativeParsingValueState actually.
2113 // Use `default:` rather than
2114 // `case IterativeParsingValueState:` is for code coverage.
2115
2116 // The IterativeParsingStartState is not enumerated in this switch-case.
2117 // It is impossible for that case. And it can be caught by following assertion.
2118
2119 // The IterativeParsingFinishState is not enumerated in this switch-case either.
2120 // It is a "derivative" state which cannot triggered from Predict() directly.
2121 // Therefore it cannot happen here. And it can be caught by following assertion.
2122 RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
2123
2124 // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2125 ParseValue<parseFlags>(is, handler);
2126 if (HasParseError()) {
2127 return IterativeParsingErrorState;
2128 }
2129 return IterativeParsingFinishState;
2130 }
2131 }
2132
2133 template <typename InputStream>
2134 void HandleError(IterativeParsingState src, InputStream& is) {
2135 if (HasParseError()) {
2136 // Error flag has been set.
2137 return;
2138 }
2139
2140 switch (src) {
2141 case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
2142 case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
2143 case IterativeParsingObjectInitialState:
2144 case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return;
2145 case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return;
2146 case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return;
2147 case IterativeParsingKeyValueDelimiterState:
2148 case IterativeParsingArrayInitialState:
2149 case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;
2150 default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
2151 }
2152 }
2153
2154 RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) {
2155 return s >= IterativeParsingElementDelimiterState;
2156 }
2157
2158 RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) {
2159 return s <= IterativeParsingErrorState;
2160 }
2161
2162 template <unsigned parseFlags, typename InputStream, typename Handler>
2163 ParseResult IterativeParse(InputStream& is, Handler& handler) {
2164 parseResult_.Clear();
2165 ClearStackOnExit scope(*this);
2166 IterativeParsingState state = IterativeParsingStartState;
2167
2168 SkipWhitespaceAndComments<parseFlags>(is);
2169 RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
2170 while (is.Peek() != '\0') {
2171 Token t = Tokenize(is.Peek());
2172 IterativeParsingState n = Predict(state, t);
2173 IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
2174
2175 if (d == IterativeParsingErrorState) {
2176 HandleError(state, is);
2177 break;
2178 }
2179
2180 state = d;
2181
2182 // Do not further consume streams if a root JSON has been parsed.
2183 if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
2184 break;
2185
2186 SkipWhitespaceAndComments<parseFlags>(is);
2187 RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
2188 }
2189
2190 // Handle the end of file.
2191 if (state != IterativeParsingFinishState)
2192 HandleError(state, is);
2193
2194 return parseResult_;
2195 }
2196
2197 static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string.
2198 internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing.
2199 ParseResult parseResult_;
2200 IterativeParsingState state_;
2201}; // class GenericReader
2202
2203//! Reader with UTF8 encoding and default allocator.
2204typedef GenericReader<UTF8<>, UTF8<> > Reader;
2205
2206RAPIDJSON_NAMESPACE_END
2207
2208#ifdef __clang__
2209RAPIDJSON_DIAG_POP
2210#endif
2211
2212
2213#ifdef __GNUC__
2214RAPIDJSON_DIAG_POP
2215#endif
2216
2217#ifdef _MSC_VER
2218RAPIDJSON_DIAG_POP
2219#endif
2220
2221#endif // RAPIDJSON_READER_H_
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
Definition reader.h:539
ParseErrorCode GetParseErrorCode() const
Get the ParseErrorCode of last parsing.
Definition reader.h:684
SourceEncoding::Ch Ch
SourceEncoding character type
Definition reader.h:541
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text (with kParseDefaultFlags)
Definition reader.h:599
GenericReader(StackAllocator *stackAllocator=0, size_t stackCapacity=kDefaultStackCapacity)
Constructor.
Definition reader.h:547
RAPIDJSON_FORCEINLINE bool IterativeParseComplete()
Check if token-by-token parsing JSON text is complete
Definition reader.h:676
void IterativeParseInit()
Initialize JSON text token-by-token parsing
Definition reader.h:606
size_t GetErrorOffset() const
Get the position of last parsing error in input, 0 otherwise.
Definition reader.h:687
bool IterativeParseNext(InputStream &is, Handler &handler)
Parse one token from JSON text
Definition reader.h:619
bool HasParseError() const
Whether a parse error has occured in the last parsing.
Definition reader.h:681
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text.
Definition reader.h:558
A Stream Wrapper
Definition stream.h:119
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:468
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition rapidjson.h:481
#define RAPIDJSON_PARSE_DEFAULT_FLAGS
User-defined kParseDefaultFlags definition.
Definition reader.h:141
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition rapidjson.h:411
ParseErrorCode
Error code of parsing.
Definition error.h:64
#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset)
Macro to indicate a parse error.
Definition reader.h:101
#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:67
@ kParseErrorDocumentRootNotSingular
The document root must not follow by other values.
Definition error.h:68
@ kParseErrorStringInvalidEncoding
Invalid encoding in string.
Definition error.h:82
Result of parsing (wraps ParseErrorCode)
Definition error.h:106
GenericStringStream< UTF8< char > > StringStream
String stream with UTF8 encoding.
Definition fwd.h:49
unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition rapidjson.h:389
void SkipWhitespace(InputStream &is)
Skip the JSON white spaces in a stream.
Definition reader.h:266
ParseFlag
Combination of parseFlags
Definition reader.h:147
@ kParseInsituFlag
In-situ(destructive) parsing.
Definition reader.h:149
@ kParseNumbersAsStringsFlag
Parse all numbers (ints/doubles) as strings.
Definition reader.h:155
@ kParseValidateEncodingFlag
Validate encoding of JSON strings.
Definition reader.h:150
@ kParseDefaultFlags
Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
Definition reader.h:158
@ kParseIterativeFlag
Iterative(constant complexity in terms of function call stack size) parsing.
Definition reader.h:151
@ kParseNanAndInfFlag
Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
Definition reader.h:157
@ kParseCommentsFlag
Allow one-line (//) and multi-line (/‍**/) comments.
Definition reader.h:154
@ kParseFullPrecisionFlag
Parse number in full precision (but slower).
Definition reader.h:153
@ kParseNoFlags
No flags are set.
Definition reader.h:148
@ kParseStopWhenDoneFlag
After parsing a complete JSON root from stream, stop further processing the rest of stream....
Definition reader.h:152
@ kParseTrailingCommasFlag
Allow trailing commas at the end of objects and arrays.
Definition reader.h:156
GenericReader< UTF8< char >, UTF8< char >, CrtAllocator > Reader
Reader with UTF8 encoding and default allocator.
Definition fwd.h:90
#define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
Definition rapidjson.h:294
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