Coverage Report

Created: 2026-02-03 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/valijson/thirdparty/rapidjson/include/rapidjson/reader.h
Line
Count
Source
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
13.5M
    RAPIDJSON_MULTILINEMACRO_BEGIN \
62
13.5M
    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
63
13.5M
    RAPIDJSON_MULTILINEMACRO_END
64
#endif
65
#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
66
1.32M
    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.36k
    RAPIDJSON_MULTILINEMACRO_BEGIN \
102
1.36k
    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
103
1.36k
    SetParseError(parseErrorCode, offset); \
104
1.36k
    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
1.82k
    RAPIDJSON_MULTILINEMACRO_BEGIN \
121
1.82k
    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
122
1.82k
    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
123
1.82k
    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
14.4M
    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
12.2M
void SkipWhitespace(InputStream& is) {
267
12.2M
    internal::StreamLocalCopy<InputStream> copy(is);
268
12.2M
    InputStream& s(copy.s);
269
270
12.2M
    typename InputStream::Ch c;
271
20.5M
    while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t')
272
8.30M
        s.Take();
273
12.2M
}
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
13.0k
        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
13.0k
    ParseResult Parse(InputStream& is, Handler& handler) {
560
13.0k
        if (parseFlags & kParseIterativeFlag)
561
13.0k
            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
15.8M
    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.36k
    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
13.0k
    void ClearStack() { stack_.Clear(); }
699
700
    // clear stack on any exit from ParseStream, e.g. due to exception
701
    struct ClearStackOnExit {
702
13.0k
        explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
703
13.0k
        ~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
12.2M
    void SkipWhitespaceAndComments(InputStream& is) {
712
12.2M
        SkipWhitespace(is);
713
714
12.2M
        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
12.2M
    }
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
5.37k
    void ParseNull(InputStream& is, Handler& handler) {
857
5.37k
        RAPIDJSON_ASSERT(is.Peek() == 'n');
858
5.37k
        is.Take();
859
860
5.37k
        if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) {
861
5.33k
            if (RAPIDJSON_UNLIKELY(!handler.Null()))
862
5.33k
                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
863
5.33k
        }
864
40
        else
865
5.37k
            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
866
5.37k
    }
867
868
    template<unsigned parseFlags, typename InputStream, typename Handler>
869
44.4k
    void ParseTrue(InputStream& is, Handler& handler) {
870
44.4k
        RAPIDJSON_ASSERT(is.Peek() == 't');
871
44.4k
        is.Take();
872
873
44.4k
        if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) {
874
44.4k
            if (RAPIDJSON_UNLIKELY(!handler.Bool(true)))
875
44.4k
                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
876
44.4k
        }
877
45
        else
878
44.4k
            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
879
44.4k
    }
880
881
    template<unsigned parseFlags, typename InputStream, typename Handler>
882
13.6k
    void ParseFalse(InputStream& is, Handler& handler) {
883
13.6k
        RAPIDJSON_ASSERT(is.Peek() == 'f');
884
13.6k
        is.Take();
885
886
13.6k
        if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) {
887
13.6k
            if (RAPIDJSON_UNLIKELY(!handler.Bool(false)))
888
13.6k
                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
889
13.6k
        }
890
46
        else
891
13.6k
            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
892
13.6k
    }
893
894
    template<typename InputStream>
895
4.00M
    RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
896
4.00M
        if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
897
252k
            is.Take();
898
252k
            return true;
899
252k
        }
900
3.75M
        else
901
3.75M
            return false;
902
4.00M
    }
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
209k
    RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
896
209k
        if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
897
209k
            is.Take();
898
209k
            return true;
899
209k
        }
900
153
        else
901
153
            return false;
902
209k
    }
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
3.79M
    RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
896
3.79M
        if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
897
42.5k
            is.Take();
898
42.5k
            return true;
899
42.5k
        }
900
3.75M
        else
901
3.75M
            return false;
902
3.79M
    }
903
904
    // Helper function to parse four hexadecimal digits in \uXXXX in ParseString().
905
    template<typename InputStream>
906
43.9k
    unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
907
43.9k
        unsigned codepoint = 0;
908
219k
        for (int i = 0; i < 4; i++) {
909
175k
            Ch c = is.Peek();
910
175k
            codepoint <<= 4;
911
175k
            codepoint += static_cast<unsigned>(c);
912
175k
            if (c >= '0' && c <= '9')
913
139k
                codepoint -= '0';
914
36.1k
            else if (c >= 'A' && c <= 'F')
915
5.64k
                codepoint -= 'A' - 10;
916
30.4k
            else if (c >= 'a' && c <= 'f')
917
30.4k
                codepoint -= 'a' - 10;
918
60
            else {
919
60
                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset);
920
60
                RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
921
60
            }
922
175k
            is.Take();
923
175k
        }
924
43.9k
        return codepoint;
925
43.9k
    }
926
927
    template <typename CharType>
928
    class StackStream {
929
    public:
930
        typedef CharType Ch;
931
932
1.27M
        StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
933
208M
        RAPIDJSON_FORCEINLINE void Put(Ch c) {
934
208M
            *stack_.template Push<Ch>() = c;
935
208M
            ++length_;
936
208M
        }
937
938
        RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
939
            length_ += count;
940
            return stack_.template Push<Ch>(count);
941
        }
942
943
1.27M
        size_t Length() const { return length_; }
944
945
1.27M
        Ch* Pop() {
946
1.27M
            return stack_.template Pop<Ch>(length_);
947
1.27M
        }
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
1.27M
    void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
960
1.27M
        internal::StreamLocalCopy<InputStream> copy(is);
961
1.27M
        InputStream& s(copy.s);
962
963
1.27M
        RAPIDJSON_ASSERT(s.Peek() == '\"');
964
1.27M
        s.Take();  // Skip '\"'
965
966
1.27M
        bool success = false;
967
1.27M
        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
1.27M
        else {
977
1.27M
            StackStream<typename TargetEncoding::Ch> stackStream(stack_);
978
1.27M
            ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
979
1.27M
            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
980
1.27M
            SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
981
1.27M
            const typename TargetEncoding::Ch* const str = stackStream.Pop();
982
1.27M
            success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
983
1.27M
        }
984
1.27M
        if (RAPIDJSON_UNLIKELY(!success))
985
1.27M
            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
986
1.27M
    }
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
1.27M
    RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
992
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
993
15.3M
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
994
1.27M
        static const char escape[256] = {
995
1.27M
            Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/',
996
1.27M
            Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
997
1.27M
            0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
998
1.27M
            0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
999
1.27M
            Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
1000
1.27M
        };
1001
1.27M
#undef Z16
1002
//!@endcond
1003
1004
207M
        for (;;) {
1005
            // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
1006
207M
            if (!(parseFlags & kParseValidateEncodingFlag))
1007
207M
                ScanCopyUnescapedString(is, os);
1008
1009
207M
            Ch c = is.Peek();
1010
207M
            if (RAPIDJSON_UNLIKELY(c == '\\')) {    // Escape
1011
510k
                size_t escapeOffset = is.Tell();    // For invalid escaping, report the initial '\\' as error offset
1012
510k
                is.Take();
1013
510k
                Ch e = is.Peek();
1014
510k
                if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
1015
469k
                    is.Take();
1016
469k
                    os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
1017
469k
                }
1018
41.0k
                else if ((parseFlags & kParseEscapedApostropheFlag) && RAPIDJSON_LIKELY(e == '\'')) { // Allow escaped apostrophe
1019
0
                    is.Take();
1020
0
                    os.Put('\'');
1021
0
                }
1022
41.0k
                else if (RAPIDJSON_LIKELY(e == 'u')) {    // Unicode
1023
41.0k
                    is.Take();
1024
41.0k
                    unsigned codepoint = ParseHex4(is, escapeOffset);
1025
41.0k
                    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1026
40.9k
                    if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDFFF)) {
1027
                        // high surrogate, check if followed by valid low surrogate
1028
3.01k
                        if (RAPIDJSON_LIKELY(codepoint <= 0xDBFF)) {
1029
                            // Handle UTF-16 surrogate pair
1030
3.00k
                            if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
1031
3.00k
                                RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
1032
2.98k
                            unsigned codepoint2 = ParseHex4(is, escapeOffset);
1033
2.98k
                            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1034
2.97k
                            if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
1035
2.97k
                                RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
1036
2.95k
                            codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
1037
2.95k
                        }
1038
                        // single low surrogate
1039
13
                        else
1040
13
                        {
1041
13
                            RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
1042
13
                        }
1043
3.01k
                    }
1044
40.8k
                    TEncoding::Encode(os, codepoint);
1045
40.8k
                }
1046
35
                else
1047
41.0k
                    RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset);
1048
510k
            }
1049
207M
            else if (RAPIDJSON_UNLIKELY(c == '"')) {    // Closing double quote
1050
1.27M
                is.Take();
1051
1.27M
                os.Put('\0');   // null-terminate the string
1052
1.27M
                return;
1053
1.27M
            }
1054
206M
            else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
1055
175
                if (c == '\0')
1056
175
                    RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());
1057
14
                else
1058
175
                    RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());
1059
175
            }
1060
206M
            else {
1061
206M
                size_t offset = is.Tell();
1062
206M
                if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
1063
206M
                    !Transcoder<SEncoding, TEncoding>::Validate(is, os) :
1064
206M
                    !Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
1065
206M
                    RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
1066
206M
            }
1067
207M
        }
1068
1.27M
    }
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
1.27M
    RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
992
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
993
1.27M
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
994
1.27M
        static const char escape[256] = {
995
1.27M
            Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/',
996
1.27M
            Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
997
1.27M
            0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
998
1.27M
            0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
999
1.27M
            Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
1000
1.27M
        };
1001
1.27M
#undef Z16
1002
//!@endcond
1003
1004
207M
        for (;;) {
1005
            // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
1006
207M
            if (!(parseFlags & kParseValidateEncodingFlag))
1007
207M
                ScanCopyUnescapedString(is, os);
1008
1009
207M
            Ch c = is.Peek();
1010
207M
            if (RAPIDJSON_UNLIKELY(c == '\\')) {    // Escape
1011
510k
                size_t escapeOffset = is.Tell();    // For invalid escaping, report the initial '\\' as error offset
1012
510k
                is.Take();
1013
510k
                Ch e = is.Peek();
1014
510k
                if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
1015
469k
                    is.Take();
1016
469k
                    os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
1017
469k
                }
1018
41.0k
                else if ((parseFlags & kParseEscapedApostropheFlag) && RAPIDJSON_LIKELY(e == '\'')) { // Allow escaped apostrophe
1019
0
                    is.Take();
1020
0
                    os.Put('\'');
1021
0
                }
1022
41.0k
                else if (RAPIDJSON_LIKELY(e == 'u')) {    // Unicode
1023
41.0k
                    is.Take();
1024
41.0k
                    unsigned codepoint = ParseHex4(is, escapeOffset);
1025
41.0k
                    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1026
40.9k
                    if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDFFF)) {
1027
                        // high surrogate, check if followed by valid low surrogate
1028
3.01k
                        if (RAPIDJSON_LIKELY(codepoint <= 0xDBFF)) {
1029
                            // Handle UTF-16 surrogate pair
1030
3.00k
                            if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
1031
3.00k
                                RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
1032
2.98k
                            unsigned codepoint2 = ParseHex4(is, escapeOffset);
1033
2.98k
                            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
1034
2.97k
                            if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
1035
2.97k
                                RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
1036
2.95k
                            codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
1037
2.95k
                        }
1038
                        // single low surrogate
1039
13
                        else
1040
13
                        {
1041
13
                            RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
1042
13
                        }
1043
3.01k
                    }
1044
40.8k
                    TEncoding::Encode(os, codepoint);
1045
40.8k
                }
1046
35
                else
1047
41.0k
                    RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset);
1048
510k
            }
1049
207M
            else if (RAPIDJSON_UNLIKELY(c == '"')) {    // Closing double quote
1050
1.27M
                is.Take();
1051
1.27M
                os.Put('\0');   // null-terminate the string
1052
1.27M
                return;
1053
1.27M
            }
1054
206M
            else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
1055
175
                if (c == '\0')
1056
175
                    RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());
1057
14
                else
1058
175
                    RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());
1059
175
            }
1060
206M
            else {
1061
206M
                size_t offset = is.Tell();
1062
206M
                if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
1063
206M
                    !Transcoder<SEncoding, TEncoding>::Validate(is, os) :
1064
206M
                    !Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
1065
206M
                    RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
1066
206M
            }
1067
207M
        }
1068
1.27M
    }
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
207M
    static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
1072
            // Do nothing for generic version
1073
207M
    }
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
207M
    static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
1072
            // Do nothing for generic version
1073
207M
    }
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
946k
        NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader;  }
1416
1417
12.4M
        RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
1418
3.24M
        RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
1419
52.8k
        RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
1420
        RAPIDJSON_FORCEINLINE void Push(char) {}
1421
1422
946k
        size_t Tell() { return is.Tell(); }
1423
1.89M
        size_t Length() { return 0; }
1424
946k
        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
946k
    void ParseNumber(InputStream& is, Handler& handler) {
1469
946k
        typedef typename internal::SelectIf<internal::BoolType<(parseFlags & kParseNumbersAsStringsFlag) != 0>, typename TargetEncoding::Ch, char>::Type NumberCharacter;
1470
1471
946k
        internal::StreamLocalCopy<InputStream> copy(is);
1472
946k
        NumberStream<InputStream, NumberCharacter,
1473
946k
            ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
1474
946k
                ((parseFlags & kParseInsituFlag) == 0) :
1475
946k
                ((parseFlags & kParseFullPrecisionFlag) != 0),
1476
946k
            (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
1477
946k
                (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
1478
1479
946k
        size_t startOffset = s.Tell();
1480
946k
        double d = 0.0;
1481
946k
        bool useNanOrInf = false;
1482
1483
        // Parse minus
1484
946k
        bool minus = Consume(s, '-');
1485
1486
        // Parse int: zero / ( digit1-9 *DIGIT )
1487
946k
        unsigned i = 0;
1488
946k
        uint64_t i64 = 0;
1489
946k
        bool use64bit = false;
1490
946k
        int significandDigit = 0;
1491
946k
        if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) {
1492
35.8k
            i = 0;
1493
35.8k
            s.TakePush();
1494
35.8k
        }
1495
911k
        else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) {
1496
910k
            i = static_cast<unsigned>(s.TakePush() - '0');
1497
1498
910k
            if (minus)
1499
135k
                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1500
116k
                    if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648
1501
10.4k
                        if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) {
1502
9.49k
                            i64 = i;
1503
9.49k
                            use64bit = true;
1504
9.49k
                            break;
1505
9.49k
                        }
1506
10.4k
                    }
1507
107k
                    i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
1508
107k
                    significandDigit++;
1509
107k
                }
1510
882k
            else
1511
2.58M
                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1512
1.78M
                    if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295
1513
121k
                        if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {
1514
81.0k
                            i64 = i;
1515
81.0k
                            use64bit = true;
1516
81.0k
                            break;
1517
81.0k
                        }
1518
121k
                    }
1519
1.70M
                    i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
1520
1.70M
                    significandDigit++;
1521
1.70M
                }
1522
910k
        }
1523
        // Parse NaN or Infinity here
1524
74
        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
74
        else
1548
74
            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
1549
1550
        // Parse 64bit int
1551
946k
        bool useDouble = false;
1552
946k
        if (use64bit) {
1553
90.5k
            if (minus)
1554
65.4k
                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1555
58.8k
                     if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
1556
3.46k
                        if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
1557
2.88k
                            d = static_cast<double>(i64);
1558
2.88k
                            useDouble = true;
1559
2.88k
                            break;
1560
2.88k
                        }
1561
55.9k
                    i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1562
55.9k
                    significandDigit++;
1563
55.9k
                }
1564
81.0k
            else
1565
395k
                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1566
322k
                    if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615
1567
7.69k
                        if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {
1568
7.37k
                            d = static_cast<double>(i64);
1569
7.37k
                            useDouble = true;
1570
7.37k
                            break;
1571
7.37k
                        }
1572
314k
                    i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1573
314k
                    significandDigit++;
1574
314k
                }
1575
90.5k
        }
1576
1577
        // Force double for big integer
1578
946k
        if (useDouble) {
1579
79.9k
            while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1580
69.7k
                d = d * 10 + (s.TakePush() - '0');
1581
69.7k
            }
1582
10.2k
        }
1583
1584
        // Parse frac = decimal-point 1*DIGIT
1585
946k
        int expFrac = 0;
1586
946k
        size_t decimalPosition;
1587
946k
        if (Consume(s, '.')) {
1588
6.72k
            decimalPosition = s.Length();
1589
1590
6.72k
            if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
1591
6.72k
                RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
1592
1593
6.71k
            if (!useDouble) {
1594
6.32k
#if RAPIDJSON_64BIT
1595
                // Use i64 to store significand in 64-bit architecture
1596
6.32k
                if (!use64bit)
1597
5.45k
                    i64 = i;
1598
1599
42.3k
                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1600
36.9k
                    if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
1601
946
                        break;
1602
35.9k
                    else {
1603
35.9k
                        i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
1604
35.9k
                        --expFrac;
1605
35.9k
                        if (i64 != 0)
1606
21.9k
                            significandDigit++;
1607
35.9k
                    }
1608
36.9k
                }
1609
1610
6.32k
                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
6.32k
                useDouble = true;
1616
6.32k
            }
1617
1618
14.9k
            while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1619
8.20k
                if (significandDigit < 17) {
1620
1.05k
                    d = d * 10.0 + (s.TakePush() - '0');
1621
1.05k
                    --expFrac;
1622
1.05k
                    if (RAPIDJSON_LIKELY(d > 0.0))
1623
1.05k
                        significandDigit++;
1624
1.05k
                }
1625
7.15k
                else
1626
7.15k
                    s.TakePush();
1627
8.20k
            }
1628
6.71k
        }
1629
940k
        else
1630
940k
            decimalPosition = s.Length(); // decimal position at the end of integer.
1631
1632
        // Parse exp = e [ minus / plus ] 1*DIGIT
1633
946k
        int exp = 0;
1634
946k
        if (Consume(s, 'e') || Consume(s, 'E')) {
1635
4.84k
            if (!useDouble) {
1636
4.05k
                d = static_cast<double>(use64bit ? i64 : i);
1637
4.05k
                useDouble = true;
1638
4.05k
            }
1639
1640
4.84k
            bool expMinus = false;
1641
4.84k
            if (Consume(s, '+'))
1642
124
                ;
1643
4.71k
            else if (Consume(s, '-'))
1644
1.46k
                expMinus = true;
1645
1646
4.84k
            if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1647
4.79k
                exp = static_cast<int>(s.Take() - '0');
1648
4.79k
                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
1.46k
                    RAPIDJSON_ASSERT(expFrac <= 0);
1656
1.46k
                    int maxExp = (expFrac + 2147483639) / 10;
1657
1658
5.14k
                    while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1659
3.68k
                        exp = exp * 10 + static_cast<int>(s.Take() - '0');
1660
3.68k
                        if (RAPIDJSON_UNLIKELY(exp > maxExp)) {
1661
947
                            while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9'))  // Consume the rest of exponent
1662
758
                                s.Take();
1663
189
                        }
1664
3.68k
                    }
1665
1.46k
                }
1666
3.33k
                else {  // positive exp
1667
3.33k
                    int maxExp = 308 - expFrac;
1668
4.41k
                    while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
1669
1.08k
                        exp = exp * 10 + static_cast<int>(s.Take() - '0');
1670
1.08k
                        if (RAPIDJSON_UNLIKELY(exp > maxExp))
1671
1.08k
                            RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
1672
1.08k
                    }
1673
3.33k
                }
1674
4.79k
            }
1675
46
            else
1676
4.84k
                RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
1677
1678
4.78k
            if (expMinus)
1679
1.46k
                exp = -exp;
1680
4.78k
        }
1681
1682
        // Finish parsing, call event according to the type of number.
1683
946k
        bool cont = true;
1684
1685
946k
        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
946k
        else {
1709
946k
           size_t length = s.Length();
1710
946k
           const NumberCharacter* decimal = s.Pop();  // Pop stack no matter if it will be used or not.
1711
1712
946k
           if (useDouble) {
1713
20.5k
               int p = exp + expFrac;
1714
20.5k
               if (parseFlags & kParseFullPrecisionFlag)
1715
0
                   d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
1716
20.5k
               else
1717
20.5k
                   d = internal::StrtodNormalPrecision(d, p);
1718
1719
               // Use > max, instead of == inf, to fix bogus warning -Wfloat-equal
1720
20.5k
               if (d > (std::numeric_limits<double>::max)()) {
1721
                   // Overflow
1722
                   // TODO: internal::StrtodX should report overflow (or underflow)
1723
2
                   RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
1724
2
               }
1725
1726
20.5k
               cont = handler.Double(minus ? -d : d);
1727
20.5k
           }
1728
926k
           else if (useNanOrInf) {
1729
0
               cont = handler.Double(d);
1730
0
           }
1731
926k
           else {
1732
926k
               if (use64bit) {
1733
79.0k
                   if (minus)
1734
5.99k
                       cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
1735
73.0k
                   else
1736
73.0k
                       cont = handler.Uint64(i64);
1737
79.0k
               }
1738
847k
               else {
1739
847k
                   if (minus)
1740
17.8k
                       cont = handler.Int(static_cast<int32_t>(~i + 1));
1741
829k
                   else
1742
829k
                       cont = handler.Uint(i);
1743
847k
               }
1744
926k
           }
1745
946k
        }
1746
946k
        if (RAPIDJSON_UNLIKELY(!cont))
1747
946k
            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset);
1748
946k
    }
1749
1750
    // Parse any JSON value
1751
    template<unsigned parseFlags, typename InputStream, typename Handler>
1752
1.35M
    void ParseValue(InputStream& is, Handler& handler) {
1753
1.35M
        switch (is.Peek()) {
1754
5.37k
            case 'n': ParseNull  <parseFlags>(is, handler); break;
1755
44.4k
            case 't': ParseTrue  <parseFlags>(is, handler); break;
1756
13.6k
            case 'f': ParseFalse <parseFlags>(is, handler); break;
1757
343k
            case '"': ParseString<parseFlags>(is, handler); break;
1758
0
            case '{': ParseObject<parseFlags>(is, handler); break;
1759
0
            case '[': ParseArray <parseFlags>(is, handler); break;
1760
946k
            default :
1761
946k
                      ParseNumber<parseFlags>(is, handler);
1762
946k
                      break;
1763
1764
1.35M
        }
1765
1.35M
    }
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
12.2M
    RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) const {
1818
1819
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
1820
3.01G
#define N NumberToken
1821
134M
#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
12.2M
        static const unsigned char tokenMap[256] = {
1824
12.2M
            N16, // 00~0F
1825
12.2M
            N16, // 10~1F
1826
12.2M
            N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
1827
12.2M
            N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
1828
12.2M
            N16, // 40~4F
1829
12.2M
            N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
1830
12.2M
            N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
1831
12.2M
            N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
1832
12.2M
            N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
1833
12.2M
        };
1834
12.2M
#undef N
1835
12.2M
#undef N16
1836
//!@endcond
1837
1838
12.2M
        if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
1839
12.2M
            return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
1840
0
        else
1841
0
            return NumberToken;
1842
12.2M
    }
1843
1844
12.2M
    RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) const {
1845
        // current state x one lookahead token -> new state
1846
12.2M
        static const char G[cIterativeParsingStateCount][kTokenCount] = {
1847
            // Finish(sink state)
1848
12.2M
            {
1849
12.2M
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1850
12.2M
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1851
12.2M
                IterativeParsingErrorState
1852
12.2M
            },
1853
            // Error(sink state)
1854
12.2M
            {
1855
12.2M
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1856
12.2M
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1857
12.2M
                IterativeParsingErrorState
1858
12.2M
            },
1859
            // Start
1860
12.2M
            {
1861
12.2M
                IterativeParsingArrayInitialState,  // Left bracket
1862
12.2M
                IterativeParsingErrorState,         // Right bracket
1863
12.2M
                IterativeParsingObjectInitialState, // Left curly bracket
1864
12.2M
                IterativeParsingErrorState,         // Right curly bracket
1865
12.2M
                IterativeParsingErrorState,         // Comma
1866
12.2M
                IterativeParsingErrorState,         // Colon
1867
12.2M
                IterativeParsingValueState,         // String
1868
12.2M
                IterativeParsingValueState,         // False
1869
12.2M
                IterativeParsingValueState,         // True
1870
12.2M
                IterativeParsingValueState,         // Null
1871
12.2M
                IterativeParsingValueState          // Number
1872
12.2M
            },
1873
            // ObjectInitial
1874
12.2M
            {
1875
12.2M
                IterativeParsingErrorState,         // Left bracket
1876
12.2M
                IterativeParsingErrorState,         // Right bracket
1877
12.2M
                IterativeParsingErrorState,         // Left curly bracket
1878
12.2M
                IterativeParsingObjectFinishState,  // Right curly bracket
1879
12.2M
                IterativeParsingErrorState,         // Comma
1880
12.2M
                IterativeParsingErrorState,         // Colon
1881
12.2M
                IterativeParsingMemberKeyState,     // String
1882
12.2M
                IterativeParsingErrorState,         // False
1883
12.2M
                IterativeParsingErrorState,         // True
1884
12.2M
                IterativeParsingErrorState,         // Null
1885
12.2M
                IterativeParsingErrorState          // Number
1886
12.2M
            },
1887
            // MemberKey
1888
12.2M
            {
1889
12.2M
                IterativeParsingErrorState,             // Left bracket
1890
12.2M
                IterativeParsingErrorState,             // Right bracket
1891
12.2M
                IterativeParsingErrorState,             // Left curly bracket
1892
12.2M
                IterativeParsingErrorState,             // Right curly bracket
1893
12.2M
                IterativeParsingErrorState,             // Comma
1894
12.2M
                IterativeParsingKeyValueDelimiterState, // Colon
1895
12.2M
                IterativeParsingErrorState,             // String
1896
12.2M
                IterativeParsingErrorState,             // False
1897
12.2M
                IterativeParsingErrorState,             // True
1898
12.2M
                IterativeParsingErrorState,             // Null
1899
12.2M
                IterativeParsingErrorState              // Number
1900
12.2M
            },
1901
            // MemberValue
1902
12.2M
            {
1903
12.2M
                IterativeParsingErrorState,             // Left bracket
1904
12.2M
                IterativeParsingErrorState,             // Right bracket
1905
12.2M
                IterativeParsingErrorState,             // Left curly bracket
1906
12.2M
                IterativeParsingObjectFinishState,      // Right curly bracket
1907
12.2M
                IterativeParsingMemberDelimiterState,   // Comma
1908
12.2M
                IterativeParsingErrorState,             // Colon
1909
12.2M
                IterativeParsingErrorState,             // String
1910
12.2M
                IterativeParsingErrorState,             // False
1911
12.2M
                IterativeParsingErrorState,             // True
1912
12.2M
                IterativeParsingErrorState,             // Null
1913
12.2M
                IterativeParsingErrorState              // Number
1914
12.2M
            },
1915
            // ObjectFinish(sink state)
1916
12.2M
            {
1917
12.2M
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1918
12.2M
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1919
12.2M
                IterativeParsingErrorState
1920
12.2M
            },
1921
            // ArrayInitial
1922
12.2M
            {
1923
12.2M
                IterativeParsingArrayInitialState,      // Left bracket(push Element state)
1924
12.2M
                IterativeParsingArrayFinishState,       // Right bracket
1925
12.2M
                IterativeParsingObjectInitialState,     // Left curly bracket(push Element state)
1926
12.2M
                IterativeParsingErrorState,             // Right curly bracket
1927
12.2M
                IterativeParsingErrorState,             // Comma
1928
12.2M
                IterativeParsingErrorState,             // Colon
1929
12.2M
                IterativeParsingElementState,           // String
1930
12.2M
                IterativeParsingElementState,           // False
1931
12.2M
                IterativeParsingElementState,           // True
1932
12.2M
                IterativeParsingElementState,           // Null
1933
12.2M
                IterativeParsingElementState            // Number
1934
12.2M
            },
1935
            // Element
1936
12.2M
            {
1937
12.2M
                IterativeParsingErrorState,             // Left bracket
1938
12.2M
                IterativeParsingArrayFinishState,       // Right bracket
1939
12.2M
                IterativeParsingErrorState,             // Left curly bracket
1940
12.2M
                IterativeParsingErrorState,             // Right curly bracket
1941
12.2M
                IterativeParsingElementDelimiterState,  // Comma
1942
12.2M
                IterativeParsingErrorState,             // Colon
1943
12.2M
                IterativeParsingErrorState,             // String
1944
12.2M
                IterativeParsingErrorState,             // False
1945
12.2M
                IterativeParsingErrorState,             // True
1946
12.2M
                IterativeParsingErrorState,             // Null
1947
12.2M
                IterativeParsingErrorState              // Number
1948
12.2M
            },
1949
            // ArrayFinish(sink state)
1950
12.2M
            {
1951
12.2M
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1952
12.2M
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1953
12.2M
                IterativeParsingErrorState
1954
12.2M
            },
1955
            // Single Value (sink state)
1956
12.2M
            {
1957
12.2M
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1958
12.2M
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
1959
12.2M
                IterativeParsingErrorState
1960
12.2M
            },
1961
            // ElementDelimiter
1962
12.2M
            {
1963
12.2M
                IterativeParsingArrayInitialState,      // Left bracket(push Element state)
1964
12.2M
                IterativeParsingArrayFinishState,       // Right bracket
1965
12.2M
                IterativeParsingObjectInitialState,     // Left curly bracket(push Element state)
1966
12.2M
                IterativeParsingErrorState,             // Right curly bracket
1967
12.2M
                IterativeParsingErrorState,             // Comma
1968
12.2M
                IterativeParsingErrorState,             // Colon
1969
12.2M
                IterativeParsingElementState,           // String
1970
12.2M
                IterativeParsingElementState,           // False
1971
12.2M
                IterativeParsingElementState,           // True
1972
12.2M
                IterativeParsingElementState,           // Null
1973
12.2M
                IterativeParsingElementState            // Number
1974
12.2M
            },
1975
            // MemberDelimiter
1976
12.2M
            {
1977
12.2M
                IterativeParsingErrorState,         // Left bracket
1978
12.2M
                IterativeParsingErrorState,         // Right bracket
1979
12.2M
                IterativeParsingErrorState,         // Left curly bracket
1980
12.2M
                IterativeParsingObjectFinishState,  // Right curly bracket
1981
12.2M
                IterativeParsingErrorState,         // Comma
1982
12.2M
                IterativeParsingErrorState,         // Colon
1983
12.2M
                IterativeParsingMemberKeyState,     // String
1984
12.2M
                IterativeParsingErrorState,         // False
1985
12.2M
                IterativeParsingErrorState,         // True
1986
12.2M
                IterativeParsingErrorState,         // Null
1987
12.2M
                IterativeParsingErrorState          // Number
1988
12.2M
            },
1989
            // KeyValueDelimiter
1990
12.2M
            {
1991
12.2M
                IterativeParsingArrayInitialState,      // Left bracket(push MemberValue state)
1992
12.2M
                IterativeParsingErrorState,             // Right bracket
1993
12.2M
                IterativeParsingObjectInitialState,     // Left curly bracket(push MemberValue state)
1994
12.2M
                IterativeParsingErrorState,             // Right curly bracket
1995
12.2M
                IterativeParsingErrorState,             // Comma
1996
12.2M
                IterativeParsingErrorState,             // Colon
1997
12.2M
                IterativeParsingMemberValueState,       // String
1998
12.2M
                IterativeParsingMemberValueState,       // False
1999
12.2M
                IterativeParsingMemberValueState,       // True
2000
12.2M
                IterativeParsingMemberValueState,       // Null
2001
12.2M
                IterativeParsingMemberValueState        // Number
2002
12.2M
            },
2003
12.2M
        }; // End of G
2004
2005
12.2M
        return static_cast<IterativeParsingState>(G[state][token]);
2006
12.2M
    }
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
12.2M
    RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
2012
12.2M
        (void)token;
2013
2014
12.2M
        switch (dst) {
2015
400
        case IterativeParsingErrorState:
2016
400
            return dst;
2017
2018
661k
        case IterativeParsingObjectInitialState:
2019
6.60M
        case IterativeParsingArrayInitialState:
2020
6.60M
        {
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.60M
            IterativeParsingState n = src;
2024
6.60M
            if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
2025
5.99M
                n = IterativeParsingElementState;
2026
603k
            else if (src == IterativeParsingKeyValueDelimiterState)
2027
591k
                n = IterativeParsingMemberValueState;
2028
            // Push current state.
2029
6.60M
            *stack_.template Push<SizeType>(1) = n;
2030
            // Initialize and push the member/element count.
2031
6.60M
            *stack_.template Push<SizeType>(1) = 0;
2032
            // Call handler
2033
6.60M
            bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
2034
            // On handler short circuits the parsing.
2035
6.60M
            if (!hr) {
2036
0
                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
2037
0
                return IterativeParsingErrorState;
2038
0
            }
2039
6.60M
            else {
2040
6.60M
                is.Take();
2041
6.60M
                return dst;
2042
6.60M
            }
2043
6.60M
        }
2044
2045
936k
        case IterativeParsingMemberKeyState:
2046
936k
            ParseString<parseFlags>(is, handler, true);
2047
936k
            if (HasParseError())
2048
34
                return IterativeParsingErrorState;
2049
935k
            else
2050
935k
                return dst;
2051
2052
935k
        case IterativeParsingKeyValueDelimiterState:
2053
935k
            RAPIDJSON_ASSERT(token == ColonToken);
2054
935k
            is.Take();
2055
935k
            return dst;
2056
2057
344k
        case IterativeParsingMemberValueState:
2058
            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2059
344k
            ParseValue<parseFlags>(is, handler);
2060
344k
            if (HasParseError()) {
2061
25
                return IterativeParsingErrorState;
2062
25
            }
2063
344k
            return dst;
2064
2065
1.00M
        case IterativeParsingElementState:
2066
            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2067
1.00M
            ParseValue<parseFlags>(is, handler);
2068
1.00M
            if (HasParseError()) {
2069
141
                return IterativeParsingErrorState;
2070
141
            }
2071
1.00M
            return dst;
2072
2073
456k
        case IterativeParsingMemberDelimiterState:
2074
1.58M
        case IterativeParsingElementDelimiterState:
2075
1.58M
            is.Take();
2076
            // Update member/element count.
2077
1.58M
            *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
2078
1.58M
            return dst;
2079
2080
657k
        case IterativeParsingObjectFinishState:
2081
657k
        {
2082
            // Transit from delimiter is only allowed when trailing commas are enabled
2083
657k
            if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {
2084
2
                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell());
2085
2
                return IterativeParsingErrorState;
2086
2
            }
2087
            // Get member count.
2088
657k
            SizeType c = *stack_.template Pop<SizeType>(1);
2089
            // If the object is not empty, count the last member.
2090
657k
            if (src == IterativeParsingMemberValueState)
2091
476k
                ++c;
2092
            // Restore the state.
2093
657k
            IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
2094
            // Transit to Finish state if this is the topmost scope.
2095
657k
            if (n == IterativeParsingStartState)
2096
13
                n = IterativeParsingFinishState;
2097
            // Call handler
2098
657k
            bool hr = handler.EndObject(c);
2099
            // On handler short circuits the parsing.
2100
657k
            if (!hr) {
2101
0
                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
2102
0
                return IterativeParsingErrorState;
2103
0
            }
2104
657k
            else {
2105
657k
                is.Take();
2106
657k
                return n;
2107
657k
            }
2108
657k
        }
2109
2110
167k
        case IterativeParsingArrayFinishState:
2111
167k
        {
2112
            // Transit from delimiter is only allowed when trailing commas are enabled
2113
167k
            if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) {
2114
1
                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell());
2115
1
                return IterativeParsingErrorState;
2116
1
            }
2117
            // Get element count.
2118
167k
            SizeType c = *stack_.template Pop<SizeType>(1);
2119
            // If the array is not empty, count the last element.
2120
167k
            if (src == IterativeParsingElementState)
2121
107k
                ++c;
2122
            // Restore the state.
2123
167k
            IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
2124
            // Transit to Finish state if this is the topmost scope.
2125
167k
            if (n == IterativeParsingStartState)
2126
11.1k
                n = IterativeParsingFinishState;
2127
            // Call handler
2128
167k
            bool hr = handler.EndArray(c);
2129
            // On handler short circuits the parsing.
2130
167k
            if (!hr) {
2131
0
                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
2132
0
                return IterativeParsingErrorState;
2133
0
            }
2134
167k
            else {
2135
167k
                is.Take();
2136
167k
                return n;
2137
167k
            }
2138
167k
        }
2139
2140
1.10k
        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.10k
            RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
2152
2153
            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
2154
1.10k
            ParseValue<parseFlags>(is, handler);
2155
1.10k
            if (HasParseError()) {
2156
402
                return IterativeParsingErrorState;
2157
402
            }
2158
698
            return IterativeParsingFinishState;
2159
12.2M
        }
2160
12.2M
    }
2161
2162
    template <typename InputStream>
2163
2.16k
    void HandleError(IterativeParsingState src, InputStream& is) {
2164
2.16k
        if (HasParseError()) {
2165
            // Error flag has been set.
2166
1.41k
            return;
2167
1.41k
        }
2168
2169
755
        switch (src) {
2170
41
        case IterativeParsingStartState:            RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
2171
198
        case IterativeParsingFinishState:           RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
2172
17
        case IterativeParsingObjectInitialState:
2173
31
        case IterativeParsingMemberDelimiterState:  RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return;
2174
15
        case IterativeParsingMemberKeyState:        RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return;
2175
31
        case IterativeParsingMemberValueState:      RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return;
2176
9
        case IterativeParsingKeyValueDelimiterState:
2177
75
        case IterativeParsingArrayInitialState:
2178
94
        case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;
2179
345
        default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
2180
755
        }
2181
755
    }
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
13.0k
    ParseResult IterativeParse(InputStream& is, Handler& handler) {
2193
13.0k
        parseResult_.Clear();
2194
13.0k
        ClearStackOnExit scope(*this);
2195
13.0k
        IterativeParsingState state = IterativeParsingStartState;
2196
2197
13.0k
        SkipWhitespaceAndComments<parseFlags>(is);
2198
13.0k
        RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
2199
12.2M
        while (is.Peek() != '\0') {
2200
12.2M
            Token t = Tokenize(is.Peek());
2201
12.2M
            IterativeParsingState n = Predict(state, t);
2202
12.2M
            IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
2203
2204
12.2M
            if (d == IterativeParsingErrorState) {
2205
1.00k
                HandleError(state, is);
2206
1.00k
                break;
2207
1.00k
            }
2208
2209
12.2M
            state = d;
2210
2211
            // Do not further consume streams if a root JSON has been parsed.
2212
12.2M
            if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
2213
0
                break;
2214
2215
12.2M
            SkipWhitespaceAndComments<parseFlags>(is);
2216
12.2M
            RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
2217
12.2M
        }
2218
2219
        // Handle the end of file.
2220
13.0k
        if (state != IterativeParsingFinishState)
2221
1.16k
            HandleError(state, is);
2222
2223
13.0k
        return parseResult_;
2224
13.0k
    }
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_