Coverage Report

Created: 2025-11-21 06:45

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