Coverage Report

Created: 2024-11-01 06:28

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