git repos / blockattack-game

blame: source/code/Libs/include/cereal/external/rapidjson/reader.h

normal view · raw

6c5f2c01 sago007 2017-03-15 17:56 1
// Tencent is pleased to support the open source community by making RapidJSON available.
6c5f2c01 sago007 2017-03-15 17:56 2
//
6c5f2c01 sago007 2017-03-15 17:56 3
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
6c5f2c01 sago007 2017-03-15 17:56 4
//
6c5f2c01 sago007 2017-03-15 17:56 5
// Licensed under the MIT License (the "License"); you may not use this file except
6c5f2c01 sago007 2017-03-15 17:56 6
// in compliance with the License. You may obtain a copy of the License at
6c5f2c01 sago007 2017-03-15 17:56 7
//
6c5f2c01 sago007 2017-03-15 17:56 8
// http://opensource.org/licenses/MIT
6c5f2c01 sago007 2017-03-15 17:56 9
//
6c5f2c01 sago007 2017-03-15 17:56 10
// Unless required by applicable law or agreed to in writing, software distributed
6c5f2c01 sago007 2017-03-15 17:56 11
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
6c5f2c01 sago007 2017-03-15 17:56 12
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
6c5f2c01 sago007 2017-03-15 17:56 13
// specific language governing permissions and limitations under the License.
6c5f2c01 sago007 2017-03-15 17:56 14
6c5f2c01 sago007 2017-03-15 17:56 15
#ifndef CEREAL_RAPIDJSON_READER_H_
6c5f2c01 sago007 2017-03-15 17:56 16
#define CEREAL_RAPIDJSON_READER_H_
6c5f2c01 sago007 2017-03-15 17:56 17
6c5f2c01 sago007 2017-03-15 17:56 18
/*! \file reader.h */
6c5f2c01 sago007 2017-03-15 17:56 19
6c5f2c01 sago007 2017-03-15 17:56 20
#include "allocators.h"
6c5f2c01 sago007 2017-03-15 17:56 21
#include "stream.h"
6c5f2c01 sago007 2017-03-15 17:56 22
#include "encodedstream.h"
6c5f2c01 sago007 2017-03-15 17:56 23
#include "internal/meta.h"
7a956470 sago007 2016-02-14 17:09 24
#include "internal/stack.h"
6c5f2c01 sago007 2017-03-15 17:56 25
#include "internal/strtod.h"
6c5f2c01 sago007 2017-03-15 17:56 26
#include <limits>
7a956470 sago007 2016-02-14 17:09 27
6c5f2c01 sago007 2017-03-15 17:56 28
#if defined(CEREAL_RAPIDJSON_SIMD) && defined(_MSC_VER)
6c5f2c01 sago007 2017-03-15 17:56 29
#include <intrin.h>
6c5f2c01 sago007 2017-03-15 17:56 30
#pragma intrinsic(_BitScanForward)
6c5f2c01 sago007 2017-03-15 17:56 31
#endif
6c5f2c01 sago007 2017-03-15 17:56 32
#ifdef CEREAL_RAPIDJSON_SSE42
7a956470 sago007 2016-02-14 17:09 33
#include <nmmintrin.h>
6c5f2c01 sago007 2017-03-15 17:56 34
#elif defined(CEREAL_RAPIDJSON_SSE2)
7a956470 sago007 2016-02-14 17:09 35
#include <emmintrin.h>
7a956470 sago007 2016-02-14 17:09 36
#endif
7a956470 sago007 2016-02-14 17:09 37
7a956470 sago007 2016-02-14 17:09 38
#ifdef _MSC_VER
6c5f2c01 sago007 2017-03-15 17:56 39
CEREAL_RAPIDJSON_DIAG_PUSH
6c5f2c01 sago007 2017-03-15 17:56 40
CEREAL_RAPIDJSON_DIAG_OFF(4127)  // conditional expression is constant
6c5f2c01 sago007 2017-03-15 17:56 41
CEREAL_RAPIDJSON_DIAG_OFF(4702)  // unreachable code
6c5f2c01 sago007 2017-03-15 17:56 42
#endif
6c5f2c01 sago007 2017-03-15 17:56 43
6c5f2c01 sago007 2017-03-15 17:56 44
#ifdef __clang__
6c5f2c01 sago007 2017-03-15 17:56 45
CEREAL_RAPIDJSON_DIAG_PUSH
6c5f2c01 sago007 2017-03-15 17:56 46
CEREAL_RAPIDJSON_DIAG_OFF(old-style-cast)
6c5f2c01 sago007 2017-03-15 17:56 47
CEREAL_RAPIDJSON_DIAG_OFF(padded)
6c5f2c01 sago007 2017-03-15 17:56 48
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
7a956470 sago007 2016-02-14 17:09 49
#endif
7a956470 sago007 2016-02-14 17:09 50
6c5f2c01 sago007 2017-03-15 17:56 51
#ifdef __GNUC__
6c5f2c01 sago007 2017-03-15 17:56 52
CEREAL_RAPIDJSON_DIAG_PUSH
6c5f2c01 sago007 2017-03-15 17:56 53
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
7a956470 sago007 2016-02-14 17:09 54
#endif
6c5f2c01 sago007 2017-03-15 17:56 55
6c5f2c01 sago007 2017-03-15 17:56 56
//!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN
6c5f2c01 sago007 2017-03-15 17:56 57
#define CEREAL_RAPIDJSON_NOTHING /* deliberately empty */
6c5f2c01 sago007 2017-03-15 17:56 58
#ifndef CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN
6c5f2c01 sago007 2017-03-15 17:56 59
#define CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
6c5f2c01 sago007 2017-03-15 17:56 60
    CEREAL_RAPIDJSON_MULTILINEMACRO_BEGIN \
6c5f2c01 sago007 2017-03-15 17:56 61
    if (CEREAL_RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
6c5f2c01 sago007 2017-03-15 17:56 62
    CEREAL_RAPIDJSON_MULTILINEMACRO_END
6c5f2c01 sago007 2017-03-15 17:56 63
#endif
6c5f2c01 sago007 2017-03-15 17:56 64
#define CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
6c5f2c01 sago007 2017-03-15 17:56 65
    CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN(CEREAL_RAPIDJSON_NOTHING)
6c5f2c01 sago007 2017-03-15 17:56 66
//!@endcond
6c5f2c01 sago007 2017-03-15 17:56 67
6c5f2c01 sago007 2017-03-15 17:56 68
/*! \def CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN
6c5f2c01 sago007 2017-03-15 17:56 69
    \ingroup CEREAL_RAPIDJSON_ERRORS
6c5f2c01 sago007 2017-03-15 17:56 70
    \brief Macro to indicate a parse error.
6c5f2c01 sago007 2017-03-15 17:56 71
    \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
6c5f2c01 sago007 2017-03-15 17:56 72
    \param offset  position of the error in JSON input (\c size_t)
6c5f2c01 sago007 2017-03-15 17:56 73
6c5f2c01 sago007 2017-03-15 17:56 74
    This macros can be used as a customization point for the internal
6c5f2c01 sago007 2017-03-15 17:56 75
    error handling mechanism of RapidJSON.
6c5f2c01 sago007 2017-03-15 17:56 76
6c5f2c01 sago007 2017-03-15 17:56 77
    A common usage model is to throw an exception instead of requiring the
6c5f2c01 sago007 2017-03-15 17:56 78
    caller to explicitly check the \ref rapidjson::GenericReader::Parse's
6c5f2c01 sago007 2017-03-15 17:56 79
    return value:
6c5f2c01 sago007 2017-03-15 17:56 80
6c5f2c01 sago007 2017-03-15 17:56 81
    \code
6c5f2c01 sago007 2017-03-15 17:56 82
    #define CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \
6c5f2c01 sago007 2017-03-15 17:56 83
       throw ParseException(parseErrorCode, #parseErrorCode, offset)
6c5f2c01 sago007 2017-03-15 17:56 84
6c5f2c01 sago007 2017-03-15 17:56 85
    #include <stdexcept>               // std::runtime_error
6c5f2c01 sago007 2017-03-15 17:56 86
    #include "rapidjson/error/error.h" // rapidjson::ParseResult
6c5f2c01 sago007 2017-03-15 17:56 87
6c5f2c01 sago007 2017-03-15 17:56 88
    struct ParseException : std::runtime_error, rapidjson::ParseResult {
6c5f2c01 sago007 2017-03-15 17:56 89
      ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset)
6c5f2c01 sago007 2017-03-15 17:56 90
        : std::runtime_error(msg), ParseResult(code, offset) {}
6c5f2c01 sago007 2017-03-15 17:56 91
    };
6c5f2c01 sago007 2017-03-15 17:56 92
6c5f2c01 sago007 2017-03-15 17:56 93
    #include "rapidjson/reader.h"
6c5f2c01 sago007 2017-03-15 17:56 94
    \endcode
6c5f2c01 sago007 2017-03-15 17:56 95
6c5f2c01 sago007 2017-03-15 17:56 96
    \see CEREAL_RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse
6c5f2c01 sago007 2017-03-15 17:56 97
 */
6c5f2c01 sago007 2017-03-15 17:56 98
#ifndef CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN
6c5f2c01 sago007 2017-03-15 17:56 99
#define CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \
6c5f2c01 sago007 2017-03-15 17:56 100
    CEREAL_RAPIDJSON_MULTILINEMACRO_BEGIN \
6c5f2c01 sago007 2017-03-15 17:56 101
    CEREAL_RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
6c5f2c01 sago007 2017-03-15 17:56 102
    SetParseError(parseErrorCode, offset); \
6c5f2c01 sago007 2017-03-15 17:56 103
    CEREAL_RAPIDJSON_MULTILINEMACRO_END
6c5f2c01 sago007 2017-03-15 17:56 104
#endif
6c5f2c01 sago007 2017-03-15 17:56 105
6c5f2c01 sago007 2017-03-15 17:56 106
/*! \def CEREAL_RAPIDJSON_PARSE_ERROR
6c5f2c01 sago007 2017-03-15 17:56 107
    \ingroup CEREAL_RAPIDJSON_ERRORS
6c5f2c01 sago007 2017-03-15 17:56 108
    \brief (Internal) macro to indicate and handle a parse error.
6c5f2c01 sago007 2017-03-15 17:56 109
    \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
6c5f2c01 sago007 2017-03-15 17:56 110
    \param offset  position of the error in JSON input (\c size_t)
6c5f2c01 sago007 2017-03-15 17:56 111
6c5f2c01 sago007 2017-03-15 17:56 112
    Invokes CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing.
6c5f2c01 sago007 2017-03-15 17:56 113
6c5f2c01 sago007 2017-03-15 17:56 114
    \see CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN
6c5f2c01 sago007 2017-03-15 17:56 115
    \hideinitializer
6c5f2c01 sago007 2017-03-15 17:56 116
 */
6c5f2c01 sago007 2017-03-15 17:56 117
#ifndef CEREAL_RAPIDJSON_PARSE_ERROR
6c5f2c01 sago007 2017-03-15 17:56 118
#define CEREAL_RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \
6c5f2c01 sago007 2017-03-15 17:56 119
    CEREAL_RAPIDJSON_MULTILINEMACRO_BEGIN \
6c5f2c01 sago007 2017-03-15 17:56 120
    CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
6c5f2c01 sago007 2017-03-15 17:56 121
    CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
6c5f2c01 sago007 2017-03-15 17:56 122
    CEREAL_RAPIDJSON_MULTILINEMACRO_END
6c5f2c01 sago007 2017-03-15 17:56 123
#endif
6c5f2c01 sago007 2017-03-15 17:56 124
6c5f2c01 sago007 2017-03-15 17:56 125
#include "error/error.h" // ParseErrorCode, ParseResult
6c5f2c01 sago007 2017-03-15 17:56 126
6c5f2c01 sago007 2017-03-15 17:56 127
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
7a956470 sago007 2016-02-14 17:09 128
7a956470 sago007 2016-02-14 17:09 129
///////////////////////////////////////////////////////////////////////////////
7a956470 sago007 2016-02-14 17:09 130
// ParseFlag
7a956470 sago007 2016-02-14 17:09 131
6c5f2c01 sago007 2017-03-15 17:56 132
/*! \def CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS
6c5f2c01 sago007 2017-03-15 17:56 133
    \ingroup CEREAL_RAPIDJSON_CONFIG
6c5f2c01 sago007 2017-03-15 17:56 134
    \brief User-defined kParseDefaultFlags definition.
6c5f2c01 sago007 2017-03-15 17:56 135
6c5f2c01 sago007 2017-03-15 17:56 136
    User can define this as any \c ParseFlag combinations.
6c5f2c01 sago007 2017-03-15 17:56 137
*/
6c5f2c01 sago007 2017-03-15 17:56 138
#ifndef CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS
6c5f2c01 sago007 2017-03-15 17:56 139
#define CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
6c5f2c01 sago007 2017-03-15 17:56 140
#endif
6c5f2c01 sago007 2017-03-15 17:56 141
7a956470 sago007 2016-02-14 17:09 142
//! Combination of parseFlags
6c5f2c01 sago007 2017-03-15 17:56 143
/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
6c5f2c01 sago007 2017-03-15 17:56 144
 */
7a956470 sago007 2016-02-14 17:09 145
enum ParseFlag {
6c5f2c01 sago007 2017-03-15 17:56 146
    kParseNoFlags = 0,              //!< No flags are set.
6c5f2c01 sago007 2017-03-15 17:56 147
    kParseInsituFlag = 1,           //!< In-situ(destructive) parsing.
6c5f2c01 sago007 2017-03-15 17:56 148
    kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
6c5f2c01 sago007 2017-03-15 17:56 149
    kParseIterativeFlag = 4,        //!< Iterative(constant complexity in terms of function call stack size) parsing.
6c5f2c01 sago007 2017-03-15 17:56 150
    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.
6c5f2c01 sago007 2017-03-15 17:56 151
    kParseFullPrecisionFlag = 16,   //!< Parse number in full precision (but slower).
6c5f2c01 sago007 2017-03-15 17:56 152
    kParseCommentsFlag = 32,        //!< Allow one-line (//) and multi-line (/**/) comments.
6c5f2c01 sago007 2017-03-15 17:56 153
    kParseNumbersAsStringsFlag = 64,    //!< Parse all numbers (ints/doubles) as strings.
6c5f2c01 sago007 2017-03-15 17:56 154
    kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays.
6c5f2c01 sago007 2017-03-15 17:56 155
    kParseNanAndInfFlag = 256,      //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
6c5f2c01 sago007 2017-03-15 17:56 156
    kParseDefaultFlags = CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS  //!< Default parse flags. Can be customized by defining CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS
7a956470 sago007 2016-02-14 17:09 157
};
7a956470 sago007 2016-02-14 17:09 158
7a956470 sago007 2016-02-14 17:09 159
///////////////////////////////////////////////////////////////////////////////
7a956470 sago007 2016-02-14 17:09 160
// Handler
7a956470 sago007 2016-02-14 17:09 161
6c5f2c01 sago007 2017-03-15 17:56 162
/*! \class rapidjson::Handler
6c5f2c01 sago007 2017-03-15 17:56 163
    \brief Concept for receiving events from GenericReader upon parsing.
6c5f2c01 sago007 2017-03-15 17:56 164
    The functions return true if no error occurs. If they return false,
6c5f2c01 sago007 2017-03-15 17:56 165
    the event publisher should terminate the process.
7a956470 sago007 2016-02-14 17:09 166
\code
7a956470 sago007 2016-02-14 17:09 167
concept Handler {
6c5f2c01 sago007 2017-03-15 17:56 168
    typename Ch;
6c5f2c01 sago007 2017-03-15 17:56 169
6c5f2c01 sago007 2017-03-15 17:56 170
    bool Null();
6c5f2c01 sago007 2017-03-15 17:56 171
    bool Bool(bool b);
6c5f2c01 sago007 2017-03-15 17:56 172
    bool Int(int i);
6c5f2c01 sago007 2017-03-15 17:56 173
    bool Uint(unsigned i);
6c5f2c01 sago007 2017-03-15 17:56 174
    bool Int64(int64_t i);
6c5f2c01 sago007 2017-03-15 17:56 175
    bool Uint64(uint64_t i);
6c5f2c01 sago007 2017-03-15 17:56 176
    bool Double(double d);
6c5f2c01 sago007 2017-03-15 17:56 177
    /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
6c5f2c01 sago007 2017-03-15 17:56 178
    bool RawNumber(const Ch* str, SizeType length, bool copy);
6c5f2c01 sago007 2017-03-15 17:56 179
    bool String(const Ch* str, SizeType length, bool copy);
6c5f2c01 sago007 2017-03-15 17:56 180
    bool StartObject();
6c5f2c01 sago007 2017-03-15 17:56 181
    bool Key(const Ch* str, SizeType length, bool copy);
6c5f2c01 sago007 2017-03-15 17:56 182
    bool EndObject(SizeType memberCount);
6c5f2c01 sago007 2017-03-15 17:56 183
    bool StartArray();
6c5f2c01 sago007 2017-03-15 17:56 184
    bool EndArray(SizeType elementCount);
7a956470 sago007 2016-02-14 17:09 185
};
7a956470 sago007 2016-02-14 17:09 186
\endcode
7a956470 sago007 2016-02-14 17:09 187
*/
7a956470 sago007 2016-02-14 17:09 188
///////////////////////////////////////////////////////////////////////////////
7a956470 sago007 2016-02-14 17:09 189
// BaseReaderHandler
7a956470 sago007 2016-02-14 17:09 190
7a956470 sago007 2016-02-14 17:09 191
//! Default implementation of Handler.
7a956470 sago007 2016-02-14 17:09 192
/*! This can be used as base class of any reader handler.
6c5f2c01 sago007 2017-03-15 17:56 193
    \note implements Handler concept
7a956470 sago007 2016-02-14 17:09 194
*/
6c5f2c01 sago007 2017-03-15 17:56 195
template<typename Encoding = UTF8<>, typename Derived = void>
7a956470 sago007 2016-02-14 17:09 196
struct BaseReaderHandler {
6c5f2c01 sago007 2017-03-15 17:56 197
    typedef typename Encoding::Ch Ch;
6c5f2c01 sago007 2017-03-15 17:56 198
6c5f2c01 sago007 2017-03-15 17:56 199
    typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;
6c5f2c01 sago007 2017-03-15 17:56 200
6c5f2c01 sago007 2017-03-15 17:56 201
    bool Default() { return true; }
6c5f2c01 sago007 2017-03-15 17:56 202
    bool Null() { return static_cast<Override&>(*this).Default(); }
6c5f2c01 sago007 2017-03-15 17:56 203
    bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
6c5f2c01 sago007 2017-03-15 17:56 204
    bool Int(int) { return static_cast<Override&>(*this).Default(); }
6c5f2c01 sago007 2017-03-15 17:56 205
    bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }
6c5f2c01 sago007 2017-03-15 17:56 206
    bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); }
6c5f2c01 sago007 2017-03-15 17:56 207
    bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); }
6c5f2c01 sago007 2017-03-15 17:56 208
    bool Double(double) { return static_cast<Override&>(*this).Default(); }
6c5f2c01 sago007 2017-03-15 17:56 209
    /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
6c5f2c01 sago007 2017-03-15 17:56 210
    bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
6c5f2c01 sago007 2017-03-15 17:56 211
    bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); }
6c5f2c01 sago007 2017-03-15 17:56 212
    bool StartObject() { return static_cast<Override&>(*this).Default(); }
6c5f2c01 sago007 2017-03-15 17:56 213
    bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
6c5f2c01 sago007 2017-03-15 17:56 214
    bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }
6c5f2c01 sago007 2017-03-15 17:56 215
    bool StartArray() { return static_cast<Override&>(*this).Default(); }
6c5f2c01 sago007 2017-03-15 17:56 216
    bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
6c5f2c01 sago007 2017-03-15 17:56 217
};
6c5f2c01 sago007 2017-03-15 17:56 218
6c5f2c01 sago007 2017-03-15 17:56 219
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 220
// StreamLocalCopy
6c5f2c01 sago007 2017-03-15 17:56 221
6c5f2c01 sago007 2017-03-15 17:56 222
namespace internal {
6c5f2c01 sago007 2017-03-15 17:56 223
6c5f2c01 sago007 2017-03-15 17:56 224
template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
6c5f2c01 sago007 2017-03-15 17:56 225
class StreamLocalCopy;
6c5f2c01 sago007 2017-03-15 17:56 226
6c5f2c01 sago007 2017-03-15 17:56 227
//! Do copy optimization.
6c5f2c01 sago007 2017-03-15 17:56 228
template<typename Stream>
6c5f2c01 sago007 2017-03-15 17:56 229
class StreamLocalCopy<Stream, 1> {
6c5f2c01 sago007 2017-03-15 17:56 230
public:
6c5f2c01 sago007 2017-03-15 17:56 231
    StreamLocalCopy(Stream& original) : s(original), original_(original) {}
6c5f2c01 sago007 2017-03-15 17:56 232
    ~StreamLocalCopy() { original_ = s; }
6c5f2c01 sago007 2017-03-15 17:56 233
6c5f2c01 sago007 2017-03-15 17:56 234
    Stream s;
6c5f2c01 sago007 2017-03-15 17:56 235
6c5f2c01 sago007 2017-03-15 17:56 236
private:
6c5f2c01 sago007 2017-03-15 17:56 237
    StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
6c5f2c01 sago007 2017-03-15 17:56 238
6c5f2c01 sago007 2017-03-15 17:56 239
    Stream& original_;
7a956470 sago007 2016-02-14 17:09 240
};
7a956470 sago007 2016-02-14 17:09 241
6c5f2c01 sago007 2017-03-15 17:56 242
//! Keep reference.
6c5f2c01 sago007 2017-03-15 17:56 243
template<typename Stream>
6c5f2c01 sago007 2017-03-15 17:56 244
class StreamLocalCopy<Stream, 0> {
6c5f2c01 sago007 2017-03-15 17:56 245
public:
6c5f2c01 sago007 2017-03-15 17:56 246
    StreamLocalCopy(Stream& original) : s(original) {}
6c5f2c01 sago007 2017-03-15 17:56 247
6c5f2c01 sago007 2017-03-15 17:56 248
    Stream& s;
6c5f2c01 sago007 2017-03-15 17:56 249
6c5f2c01 sago007 2017-03-15 17:56 250
private:
6c5f2c01 sago007 2017-03-15 17:56 251
    StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
6c5f2c01 sago007 2017-03-15 17:56 252
};
6c5f2c01 sago007 2017-03-15 17:56 253
6c5f2c01 sago007 2017-03-15 17:56 254
} // namespace internal
6c5f2c01 sago007 2017-03-15 17:56 255
7a956470 sago007 2016-02-14 17:09 256
///////////////////////////////////////////////////////////////////////////////
7a956470 sago007 2016-02-14 17:09 257
// SkipWhitespace
7a956470 sago007 2016-02-14 17:09 258
7a956470 sago007 2016-02-14 17:09 259
//! Skip the JSON white spaces in a stream.
6c5f2c01 sago007 2017-03-15 17:56 260
/*! \param is A input stream for skipping white spaces.
6c5f2c01 sago007 2017-03-15 17:56 261
    \note This function has SSE2/SSE4.2 specialization.
7a956470 sago007 2016-02-14 17:09 262
*/
6c5f2c01 sago007 2017-03-15 17:56 263
template<typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 264
void SkipWhitespace(InputStream& is) {
6c5f2c01 sago007 2017-03-15 17:56 265
    internal::StreamLocalCopy<InputStream> copy(is);
6c5f2c01 sago007 2017-03-15 17:56 266
    InputStream& s(copy.s);
6c5f2c01 sago007 2017-03-15 17:56 267
6c5f2c01 sago007 2017-03-15 17:56 268
    typename InputStream::Ch c;
6c5f2c01 sago007 2017-03-15 17:56 269
    while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t')
6c5f2c01 sago007 2017-03-15 17:56 270
        s.Take();
7a956470 sago007 2016-02-14 17:09 271
}
7a956470 sago007 2016-02-14 17:09 272
6c5f2c01 sago007 2017-03-15 17:56 273
inline const char* SkipWhitespace(const char* p, const char* end) {
6c5f2c01 sago007 2017-03-15 17:56 274
    while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
6c5f2c01 sago007 2017-03-15 17:56 275
        ++p;
6c5f2c01 sago007 2017-03-15 17:56 276
    return p;
6c5f2c01 sago007 2017-03-15 17:56 277
}
6c5f2c01 sago007 2017-03-15 17:56 278
6c5f2c01 sago007 2017-03-15 17:56 279
#ifdef CEREAL_RAPIDJSON_SSE42
7a956470 sago007 2016-02-14 17:09 280
//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
7a956470 sago007 2016-02-14 17:09 281
inline const char *SkipWhitespace_SIMD(const char* p) {
6c5f2c01 sago007 2017-03-15 17:56 282
    // Fast return for single non-whitespace
6c5f2c01 sago007 2017-03-15 17:56 283
    if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
6c5f2c01 sago007 2017-03-15 17:56 284
        ++p;
6c5f2c01 sago007 2017-03-15 17:56 285
    else
6c5f2c01 sago007 2017-03-15 17:56 286
        return p;
6c5f2c01 sago007 2017-03-15 17:56 287
6c5f2c01 sago007 2017-03-15 17:56 288
    // 16-byte align to the next boundary
6c5f2c01 sago007 2017-03-15 17:56 289
    const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
6c5f2c01 sago007 2017-03-15 17:56 290
    while (p != nextAligned)
6c5f2c01 sago007 2017-03-15 17:56 291
        if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
6c5f2c01 sago007 2017-03-15 17:56 292
            ++p;
6c5f2c01 sago007 2017-03-15 17:56 293
        else
6c5f2c01 sago007 2017-03-15 17:56 294
            return p;
6c5f2c01 sago007 2017-03-15 17:56 295
6c5f2c01 sago007 2017-03-15 17:56 296
    // The rest of string using SIMD
6c5f2c01 sago007 2017-03-15 17:56 297
    static const char whitespace[16] = " \n\r\t";
6c5f2c01 sago007 2017-03-15 17:56 298
    const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
6c5f2c01 sago007 2017-03-15 17:56 299
6c5f2c01 sago007 2017-03-15 17:56 300
    for (;; p += 16) {
6c5f2c01 sago007 2017-03-15 17:56 301
        const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
6c5f2c01 sago007 2017-03-15 17:56 302
        const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
6c5f2c01 sago007 2017-03-15 17:56 303
        if (r != 0) {   // some of characters is non-whitespace
6c5f2c01 sago007 2017-03-15 17:56 304
#ifdef _MSC_VER         // Find the index of first non-whitespace
6c5f2c01 sago007 2017-03-15 17:56 305
            unsigned long offset;
6c5f2c01 sago007 2017-03-15 17:56 306
            _BitScanForward(&offset, r);
6c5f2c01 sago007 2017-03-15 17:56 307
            return p + offset;
7a956470 sago007 2016-02-14 17:09 308
#else
6c5f2c01 sago007 2017-03-15 17:56 309
            return p + __builtin_ffs(r) - 1;
7a956470 sago007 2016-02-14 17:09 310
#endif
6c5f2c01 sago007 2017-03-15 17:56 311
        }
6c5f2c01 sago007 2017-03-15 17:56 312
    }
7a956470 sago007 2016-02-14 17:09 313
}
7a956470 sago007 2016-02-14 17:09 314
6c5f2c01 sago007 2017-03-15 17:56 315
inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
6c5f2c01 sago007 2017-03-15 17:56 316
    // Fast return for single non-whitespace
6c5f2c01 sago007 2017-03-15 17:56 317
    if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
6c5f2c01 sago007 2017-03-15 17:56 318
        ++p;
6c5f2c01 sago007 2017-03-15 17:56 319
    else
6c5f2c01 sago007 2017-03-15 17:56 320
        return p;
6c5f2c01 sago007 2017-03-15 17:56 321
6c5f2c01 sago007 2017-03-15 17:56 322
    // The middle of string using SIMD
6c5f2c01 sago007 2017-03-15 17:56 323
    static const char whitespace[16] = " \n\r\t";
6c5f2c01 sago007 2017-03-15 17:56 324
    const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
6c5f2c01 sago007 2017-03-15 17:56 325
6c5f2c01 sago007 2017-03-15 17:56 326
    for (; p <= end - 16; p += 16) {
6c5f2c01 sago007 2017-03-15 17:56 327
        const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
6c5f2c01 sago007 2017-03-15 17:56 328
        const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
6c5f2c01 sago007 2017-03-15 17:56 329
        if (r != 0) {   // some of characters is non-whitespace
6c5f2c01 sago007 2017-03-15 17:56 330
#ifdef _MSC_VER         // Find the index of first non-whitespace
6c5f2c01 sago007 2017-03-15 17:56 331
            unsigned long offset;
6c5f2c01 sago007 2017-03-15 17:56 332
            _BitScanForward(&offset, r);
6c5f2c01 sago007 2017-03-15 17:56 333
            return p + offset;
6c5f2c01 sago007 2017-03-15 17:56 334
#else
6c5f2c01 sago007 2017-03-15 17:56 335
            return p + __builtin_ffs(r) - 1;
6c5f2c01 sago007 2017-03-15 17:56 336
#endif
6c5f2c01 sago007 2017-03-15 17:56 337
        }
6c5f2c01 sago007 2017-03-15 17:56 338
    }
6c5f2c01 sago007 2017-03-15 17:56 339
6c5f2c01 sago007 2017-03-15 17:56 340
    return SkipWhitespace(p, end);
6c5f2c01 sago007 2017-03-15 17:56 341
}
6c5f2c01 sago007 2017-03-15 17:56 342
6c5f2c01 sago007 2017-03-15 17:56 343
#elif defined(CEREAL_RAPIDJSON_SSE2)
7a956470 sago007 2016-02-14 17:09 344
7a956470 sago007 2016-02-14 17:09 345
//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
7a956470 sago007 2016-02-14 17:09 346
inline const char *SkipWhitespace_SIMD(const char* p) {
6c5f2c01 sago007 2017-03-15 17:56 347
    // Fast return for single non-whitespace
6c5f2c01 sago007 2017-03-15 17:56 348
    if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
6c5f2c01 sago007 2017-03-15 17:56 349
        ++p;
6c5f2c01 sago007 2017-03-15 17:56 350
    else
6c5f2c01 sago007 2017-03-15 17:56 351
        return p;
6c5f2c01 sago007 2017-03-15 17:56 352
6c5f2c01 sago007 2017-03-15 17:56 353
    // 16-byte align to the next boundary
6c5f2c01 sago007 2017-03-15 17:56 354
    const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
6c5f2c01 sago007 2017-03-15 17:56 355
    while (p != nextAligned)
6c5f2c01 sago007 2017-03-15 17:56 356
        if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
6c5f2c01 sago007 2017-03-15 17:56 357
            ++p;
6c5f2c01 sago007 2017-03-15 17:56 358
        else
6c5f2c01 sago007 2017-03-15 17:56 359
            return p;
6c5f2c01 sago007 2017-03-15 17:56 360
6c5f2c01 sago007 2017-03-15 17:56 361
    // The rest of string
6c5f2c01 sago007 2017-03-15 17:56 362
    #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
6c5f2c01 sago007 2017-03-15 17:56 363
    static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
6c5f2c01 sago007 2017-03-15 17:56 364
    #undef C16
6c5f2c01 sago007 2017-03-15 17:56 365
6c5f2c01 sago007 2017-03-15 17:56 366
    const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
6c5f2c01 sago007 2017-03-15 17:56 367
    const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
6c5f2c01 sago007 2017-03-15 17:56 368
    const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
6c5f2c01 sago007 2017-03-15 17:56 369
    const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
6c5f2c01 sago007 2017-03-15 17:56 370
6c5f2c01 sago007 2017-03-15 17:56 371
    for (;; p += 16) {
6c5f2c01 sago007 2017-03-15 17:56 372
        const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
6c5f2c01 sago007 2017-03-15 17:56 373
        __m128i x = _mm_cmpeq_epi8(s, w0);
6c5f2c01 sago007 2017-03-15 17:56 374
        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
6c5f2c01 sago007 2017-03-15 17:56 375
        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
6c5f2c01 sago007 2017-03-15 17:56 376
        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
6c5f2c01 sago007 2017-03-15 17:56 377
        unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
6c5f2c01 sago007 2017-03-15 17:56 378
        if (r != 0) {   // some of characters may be non-whitespace
6c5f2c01 sago007 2017-03-15 17:56 379
#ifdef _MSC_VER         // Find the index of first non-whitespace
6c5f2c01 sago007 2017-03-15 17:56 380
            unsigned long offset;
6c5f2c01 sago007 2017-03-15 17:56 381
            _BitScanForward(&offset, r);
6c5f2c01 sago007 2017-03-15 17:56 382
            return p + offset;
6c5f2c01 sago007 2017-03-15 17:56 383
#else
6c5f2c01 sago007 2017-03-15 17:56 384
            return p + __builtin_ffs(r) - 1;
6c5f2c01 sago007 2017-03-15 17:56 385
#endif
6c5f2c01 sago007 2017-03-15 17:56 386
        }
6c5f2c01 sago007 2017-03-15 17:56 387
    }
6c5f2c01 sago007 2017-03-15 17:56 388
}
6c5f2c01 sago007 2017-03-15 17:56 389
6c5f2c01 sago007 2017-03-15 17:56 390
inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
6c5f2c01 sago007 2017-03-15 17:56 391
    // Fast return for single non-whitespace
6c5f2c01 sago007 2017-03-15 17:56 392
    if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
6c5f2c01 sago007 2017-03-15 17:56 393
        ++p;
6c5f2c01 sago007 2017-03-15 17:56 394
    else
6c5f2c01 sago007 2017-03-15 17:56 395
        return p;
6c5f2c01 sago007 2017-03-15 17:56 396
6c5f2c01 sago007 2017-03-15 17:56 397
    // The rest of string
6c5f2c01 sago007 2017-03-15 17:56 398
    #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
6c5f2c01 sago007 2017-03-15 17:56 399
    static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
6c5f2c01 sago007 2017-03-15 17:56 400
    #undef C16
6c5f2c01 sago007 2017-03-15 17:56 401
6c5f2c01 sago007 2017-03-15 17:56 402
    const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
6c5f2c01 sago007 2017-03-15 17:56 403
    const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
6c5f2c01 sago007 2017-03-15 17:56 404
    const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
6c5f2c01 sago007 2017-03-15 17:56 405
    const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
6c5f2c01 sago007 2017-03-15 17:56 406
6c5f2c01 sago007 2017-03-15 17:56 407
    for (; p <= end - 16; p += 16) {
6c5f2c01 sago007 2017-03-15 17:56 408
        const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
6c5f2c01 sago007 2017-03-15 17:56 409
        __m128i x = _mm_cmpeq_epi8(s, w0);
6c5f2c01 sago007 2017-03-15 17:56 410
        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
6c5f2c01 sago007 2017-03-15 17:56 411
        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
6c5f2c01 sago007 2017-03-15 17:56 412
        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
6c5f2c01 sago007 2017-03-15 17:56 413
        unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
6c5f2c01 sago007 2017-03-15 17:56 414
        if (r != 0) {   // some of characters may be non-whitespace
6c5f2c01 sago007 2017-03-15 17:56 415
#ifdef _MSC_VER         // Find the index of first non-whitespace
6c5f2c01 sago007 2017-03-15 17:56 416
            unsigned long offset;
6c5f2c01 sago007 2017-03-15 17:56 417
            _BitScanForward(&offset, r);
6c5f2c01 sago007 2017-03-15 17:56 418
            return p + offset;
7a956470 sago007 2016-02-14 17:09 419
#else
6c5f2c01 sago007 2017-03-15 17:56 420
            return p + __builtin_ffs(r) - 1;
7a956470 sago007 2016-02-14 17:09 421
#endif
6c5f2c01 sago007 2017-03-15 17:56 422
        }
6c5f2c01 sago007 2017-03-15 17:56 423
    }
6c5f2c01 sago007 2017-03-15 17:56 424
6c5f2c01 sago007 2017-03-15 17:56 425
    return SkipWhitespace(p, end);
7a956470 sago007 2016-02-14 17:09 426
}
7a956470 sago007 2016-02-14 17:09 427
6c5f2c01 sago007 2017-03-15 17:56 428
#endif // CEREAL_RAPIDJSON_SSE2
7a956470 sago007 2016-02-14 17:09 429
6c5f2c01 sago007 2017-03-15 17:56 430
#ifdef CEREAL_RAPIDJSON_SIMD
7a956470 sago007 2016-02-14 17:09 431
//! Template function specialization for InsituStringStream
6c5f2c01 sago007 2017-03-15 17:56 432
template<> inline void SkipWhitespace(InsituStringStream& is) {
6c5f2c01 sago007 2017-03-15 17:56 433
    is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
7a956470 sago007 2016-02-14 17:09 434
}
7a956470 sago007 2016-02-14 17:09 435
7a956470 sago007 2016-02-14 17:09 436
//! Template function specialization for StringStream
6c5f2c01 sago007 2017-03-15 17:56 437
template<> inline void SkipWhitespace(StringStream& is) {
6c5f2c01 sago007 2017-03-15 17:56 438
    is.src_ = SkipWhitespace_SIMD(is.src_);
6c5f2c01 sago007 2017-03-15 17:56 439
}
6c5f2c01 sago007 2017-03-15 17:56 440
6c5f2c01 sago007 2017-03-15 17:56 441
template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
6c5f2c01 sago007 2017-03-15 17:56 442
    is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
7a956470 sago007 2016-02-14 17:09 443
}
6c5f2c01 sago007 2017-03-15 17:56 444
#endif // CEREAL_RAPIDJSON_SIMD
7a956470 sago007 2016-02-14 17:09 445
7a956470 sago007 2016-02-14 17:09 446
///////////////////////////////////////////////////////////////////////////////
7a956470 sago007 2016-02-14 17:09 447
// GenericReader
7a956470 sago007 2016-02-14 17:09 448
6c5f2c01 sago007 2017-03-15 17:56 449
//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator.
7a956470 sago007 2016-02-14 17:09 450
/*! GenericReader parses JSON text from a stream, and send events synchronously to an
7a956470 sago007 2016-02-14 17:09 451
    object implementing Handler concept.
7a956470 sago007 2016-02-14 17:09 452
7a956470 sago007 2016-02-14 17:09 453
    It needs to allocate a stack for storing a single decoded string during
7a956470 sago007 2016-02-14 17:09 454
    non-destructive parsing.
7a956470 sago007 2016-02-14 17:09 455
7a956470 sago007 2016-02-14 17:09 456
    For in-situ parsing, the decoded string is directly written to the source
7a956470 sago007 2016-02-14 17:09 457
    text string, no temporary buffer is required.
7a956470 sago007 2016-02-14 17:09 458
7a956470 sago007 2016-02-14 17:09 459
    A GenericReader object can be reused for parsing multiple JSON text.
7a956470 sago007 2016-02-14 17:09 460
6c5f2c01 sago007 2017-03-15 17:56 461
    \tparam SourceEncoding Encoding of the input stream.
6c5f2c01 sago007 2017-03-15 17:56 462
    \tparam TargetEncoding Encoding of the parse output.
6c5f2c01 sago007 2017-03-15 17:56 463
    \tparam StackAllocator Allocator type for stack.
7a956470 sago007 2016-02-14 17:09 464
*/
6c5f2c01 sago007 2017-03-15 17:56 465
template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
7a956470 sago007 2016-02-14 17:09 466
class GenericReader {
7a956470 sago007 2016-02-14 17:09 467
public:
6c5f2c01 sago007 2017-03-15 17:56 468
    typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type
6c5f2c01 sago007 2017-03-15 17:56 469
6c5f2c01 sago007 2017-03-15 17:56 470
    //! Constructor.
6c5f2c01 sago007 2017-03-15 17:56 471
    /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
6c5f2c01 sago007 2017-03-15 17:56 472
        \param stackCapacity stack capacity in bytes for storing a single decoded string.  (Only use for non-destructive parsing)
6c5f2c01 sago007 2017-03-15 17:56 473
    */
6c5f2c01 sago007 2017-03-15 17:56 474
    GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
6c5f2c01 sago007 2017-03-15 17:56 475
6c5f2c01 sago007 2017-03-15 17:56 476
    //! Parse JSON text.
6c5f2c01 sago007 2017-03-15 17:56 477
    /*! \tparam parseFlags Combination of \ref ParseFlag.
6c5f2c01 sago007 2017-03-15 17:56 478
        \tparam InputStream Type of input stream, implementing Stream concept.
6c5f2c01 sago007 2017-03-15 17:56 479
        \tparam Handler Type of handler, implementing Handler concept.
6c5f2c01 sago007 2017-03-15 17:56 480
        \param is Input stream to be parsed.
6c5f2c01 sago007 2017-03-15 17:56 481
        \param handler The handler to receive events.
6c5f2c01 sago007 2017-03-15 17:56 482
        \return Whether the parsing is successful.
6c5f2c01 sago007 2017-03-15 17:56 483
    */
6c5f2c01 sago007 2017-03-15 17:56 484
    template <unsigned parseFlags, typename InputStream, typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 485
    ParseResult Parse(InputStream& is, Handler& handler) {
6c5f2c01 sago007 2017-03-15 17:56 486
        if (parseFlags & kParseIterativeFlag)
6c5f2c01 sago007 2017-03-15 17:56 487
            return IterativeParse<parseFlags>(is, handler);
6c5f2c01 sago007 2017-03-15 17:56 488
6c5f2c01 sago007 2017-03-15 17:56 489
        parseResult_.Clear();
6c5f2c01 sago007 2017-03-15 17:56 490
6c5f2c01 sago007 2017-03-15 17:56 491
        ClearStackOnExit scope(*this);
6c5f2c01 sago007 2017-03-15 17:56 492
6c5f2c01 sago007 2017-03-15 17:56 493
        SkipWhitespaceAndComments<parseFlags>(is);
6c5f2c01 sago007 2017-03-15 17:56 494
        CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
6c5f2c01 sago007 2017-03-15 17:56 495
6c5f2c01 sago007 2017-03-15 17:56 496
        if (CEREAL_RAPIDJSON_UNLIKELY(is.Peek() == '\0')) {
6c5f2c01 sago007 2017-03-15 17:56 497
            CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 498
            CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
6c5f2c01 sago007 2017-03-15 17:56 499
        }
6c5f2c01 sago007 2017-03-15 17:56 500
        else {
6c5f2c01 sago007 2017-03-15 17:56 501
            ParseValue<parseFlags>(is, handler);
6c5f2c01 sago007 2017-03-15 17:56 502
            CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
6c5f2c01 sago007 2017-03-15 17:56 503
6c5f2c01 sago007 2017-03-15 17:56 504
            if (!(parseFlags & kParseStopWhenDoneFlag)) {
6c5f2c01 sago007 2017-03-15 17:56 505
                SkipWhitespaceAndComments<parseFlags>(is);
6c5f2c01 sago007 2017-03-15 17:56 506
                CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
6c5f2c01 sago007 2017-03-15 17:56 507
6c5f2c01 sago007 2017-03-15 17:56 508
                if (CEREAL_RAPIDJSON_UNLIKELY(is.Peek() != '\0')) {
6c5f2c01 sago007 2017-03-15 17:56 509
                    CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 510
                    CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
6c5f2c01 sago007 2017-03-15 17:56 511
                }
6c5f2c01 sago007 2017-03-15 17:56 512
            }
6c5f2c01 sago007 2017-03-15 17:56 513
        }
6c5f2c01 sago007 2017-03-15 17:56 514
6c5f2c01 sago007 2017-03-15 17:56 515
        return parseResult_;
6c5f2c01 sago007 2017-03-15 17:56 516
    }
6c5f2c01 sago007 2017-03-15 17:56 517
6c5f2c01 sago007 2017-03-15 17:56 518
    //! Parse JSON text (with \ref kParseDefaultFlags)
6c5f2c01 sago007 2017-03-15 17:56 519
    /*! \tparam InputStream Type of input stream, implementing Stream concept
6c5f2c01 sago007 2017-03-15 17:56 520
        \tparam Handler Type of handler, implementing Handler concept.
6c5f2c01 sago007 2017-03-15 17:56 521
        \param is Input stream to be parsed.
6c5f2c01 sago007 2017-03-15 17:56 522
        \param handler The handler to receive events.
6c5f2c01 sago007 2017-03-15 17:56 523
        \return Whether the parsing is successful.
6c5f2c01 sago007 2017-03-15 17:56 524
    */
6c5f2c01 sago007 2017-03-15 17:56 525
    template <typename InputStream, typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 526
    ParseResult Parse(InputStream& is, Handler& handler) {
6c5f2c01 sago007 2017-03-15 17:56 527
        return Parse<kParseDefaultFlags>(is, handler);
6c5f2c01 sago007 2017-03-15 17:56 528
    }
6c5f2c01 sago007 2017-03-15 17:56 529
6c5f2c01 sago007 2017-03-15 17:56 530
    //! Whether a parse error has occured in the last parsing.
6c5f2c01 sago007 2017-03-15 17:56 531
    bool HasParseError() const { return parseResult_.IsError(); }
6c5f2c01 sago007 2017-03-15 17:56 532
6c5f2c01 sago007 2017-03-15 17:56 533
    //! Get the \ref ParseErrorCode of last parsing.
6c5f2c01 sago007 2017-03-15 17:56 534
    ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
6c5f2c01 sago007 2017-03-15 17:56 535
6c5f2c01 sago007 2017-03-15 17:56 536
    //! Get the position of last parsing error in input, 0 otherwise.
6c5f2c01 sago007 2017-03-15 17:56 537
    size_t GetErrorOffset() const { return parseResult_.Offset(); }
6c5f2c01 sago007 2017-03-15 17:56 538
6c5f2c01 sago007 2017-03-15 17:56 539
protected:
6c5f2c01 sago007 2017-03-15 17:56 540
    void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
7a956470 sago007 2016-02-14 17:09 541
6c5f2c01 sago007 2017-03-15 17:56 542
private:
6c5f2c01 sago007 2017-03-15 17:56 543
    // Prohibit copy constructor & assignment operator.
6c5f2c01 sago007 2017-03-15 17:56 544
    GenericReader(const GenericReader&);
6c5f2c01 sago007 2017-03-15 17:56 545
    GenericReader& operator=(const GenericReader&);
6c5f2c01 sago007 2017-03-15 17:56 546
6c5f2c01 sago007 2017-03-15 17:56 547
    void ClearStack() { stack_.Clear(); }
6c5f2c01 sago007 2017-03-15 17:56 548
6c5f2c01 sago007 2017-03-15 17:56 549
    // clear stack on any exit from ParseStream, e.g. due to exception
6c5f2c01 sago007 2017-03-15 17:56 550
    struct ClearStackOnExit {
6c5f2c01 sago007 2017-03-15 17:56 551
        explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
6c5f2c01 sago007 2017-03-15 17:56 552
        ~ClearStackOnExit() { r_.ClearStack(); }
6c5f2c01 sago007 2017-03-15 17:56 553
    private:
6c5f2c01 sago007 2017-03-15 17:56 554
        GenericReader& r_;
6c5f2c01 sago007 2017-03-15 17:56 555
        ClearStackOnExit(const ClearStackOnExit&);
6c5f2c01 sago007 2017-03-15 17:56 556
        ClearStackOnExit& operator=(const ClearStackOnExit&);
6c5f2c01 sago007 2017-03-15 17:56 557
    };
6c5f2c01 sago007 2017-03-15 17:56 558
6c5f2c01 sago007 2017-03-15 17:56 559
    template<unsigned parseFlags, typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 560
    void SkipWhitespaceAndComments(InputStream& is) {
6c5f2c01 sago007 2017-03-15 17:56 561
        SkipWhitespace(is);
6c5f2c01 sago007 2017-03-15 17:56 562
6c5f2c01 sago007 2017-03-15 17:56 563
        if (parseFlags & kParseCommentsFlag) {
6c5f2c01 sago007 2017-03-15 17:56 564
            while (CEREAL_RAPIDJSON_UNLIKELY(Consume(is, '/'))) {
6c5f2c01 sago007 2017-03-15 17:56 565
                if (Consume(is, '*')) {
6c5f2c01 sago007 2017-03-15 17:56 566
                    while (true) {
6c5f2c01 sago007 2017-03-15 17:56 567
                        if (CEREAL_RAPIDJSON_UNLIKELY(is.Peek() == '\0'))
6c5f2c01 sago007 2017-03-15 17:56 568
                            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 569
                        else if (Consume(is, '*')) {
6c5f2c01 sago007 2017-03-15 17:56 570
                            if (Consume(is, '/'))
6c5f2c01 sago007 2017-03-15 17:56 571
                                break;
6c5f2c01 sago007 2017-03-15 17:56 572
                        }
6c5f2c01 sago007 2017-03-15 17:56 573
                        else
6c5f2c01 sago007 2017-03-15 17:56 574
                            is.Take();
6c5f2c01 sago007 2017-03-15 17:56 575
                    }
6c5f2c01 sago007 2017-03-15 17:56 576
                }
6c5f2c01 sago007 2017-03-15 17:56 577
                else if (CEREAL_RAPIDJSON_LIKELY(Consume(is, '/')))
6c5f2c01 sago007 2017-03-15 17:56 578
                    while (is.Peek() != '\0' && is.Take() != '\n');
6c5f2c01 sago007 2017-03-15 17:56 579
                else
6c5f2c01 sago007 2017-03-15 17:56 580
                    CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 581
6c5f2c01 sago007 2017-03-15 17:56 582
                SkipWhitespace(is);
6c5f2c01 sago007 2017-03-15 17:56 583
            }
6c5f2c01 sago007 2017-03-15 17:56 584
        }
6c5f2c01 sago007 2017-03-15 17:56 585
    }
6c5f2c01 sago007 2017-03-15 17:56 586
6c5f2c01 sago007 2017-03-15 17:56 587
    // Parse object: { string : value, ... }
6c5f2c01 sago007 2017-03-15 17:56 588
    template<unsigned parseFlags, typename InputStream, typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 589
    void ParseObject(InputStream& is, Handler& handler) {
6c5f2c01 sago007 2017-03-15 17:56 590
        CEREAL_RAPIDJSON_ASSERT(is.Peek() == '{');
6c5f2c01 sago007 2017-03-15 17:56 591
        is.Take();  // Skip '{'
6c5f2c01 sago007 2017-03-15 17:56 592
6c5f2c01 sago007 2017-03-15 17:56 593
        if (CEREAL_RAPIDJSON_UNLIKELY(!handler.StartObject()))
6c5f2c01 sago007 2017-03-15 17:56 594
            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 595
6c5f2c01 sago007 2017-03-15 17:56 596
        SkipWhitespaceAndComments<parseFlags>(is);
6c5f2c01 sago007 2017-03-15 17:56 597
        CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 598
6c5f2c01 sago007 2017-03-15 17:56 599
        if (Consume(is, '}')) {
6c5f2c01 sago007 2017-03-15 17:56 600
            if (CEREAL_RAPIDJSON_UNLIKELY(!handler.EndObject(0)))  // empty object
6c5f2c01 sago007 2017-03-15 17:56 601
                CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 602
            return;
6c5f2c01 sago007 2017-03-15 17:56 603
        }
6c5f2c01 sago007 2017-03-15 17:56 604
6c5f2c01 sago007 2017-03-15 17:56 605
        for (SizeType memberCount = 0;;) {
6c5f2c01 sago007 2017-03-15 17:56 606
            if (CEREAL_RAPIDJSON_UNLIKELY(is.Peek() != '"'))
6c5f2c01 sago007 2017-03-15 17:56 607
                CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 608
6c5f2c01 sago007 2017-03-15 17:56 609
            ParseString<parseFlags>(is, handler, true);
6c5f2c01 sago007 2017-03-15 17:56 610
            CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 611
6c5f2c01 sago007 2017-03-15 17:56 612
            SkipWhitespaceAndComments<parseFlags>(is);
6c5f2c01 sago007 2017-03-15 17:56 613
            CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 614
6c5f2c01 sago007 2017-03-15 17:56 615
            if (CEREAL_RAPIDJSON_UNLIKELY(!Consume(is, ':')))
6c5f2c01 sago007 2017-03-15 17:56 616
                CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 617
6c5f2c01 sago007 2017-03-15 17:56 618
            SkipWhitespaceAndComments<parseFlags>(is);
6c5f2c01 sago007 2017-03-15 17:56 619
            CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 620
6c5f2c01 sago007 2017-03-15 17:56 621
            ParseValue<parseFlags>(is, handler);
6c5f2c01 sago007 2017-03-15 17:56 622
            CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 623
6c5f2c01 sago007 2017-03-15 17:56 624
            SkipWhitespaceAndComments<parseFlags>(is);
6c5f2c01 sago007 2017-03-15 17:56 625
            CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 626
6c5f2c01 sago007 2017-03-15 17:56 627
            ++memberCount;
6c5f2c01 sago007 2017-03-15 17:56 628
6c5f2c01 sago007 2017-03-15 17:56 629
            switch (is.Peek()) {
6c5f2c01 sago007 2017-03-15 17:56 630
                case ',':
6c5f2c01 sago007 2017-03-15 17:56 631
                    is.Take();
6c5f2c01 sago007 2017-03-15 17:56 632
                    SkipWhitespaceAndComments<parseFlags>(is);
6c5f2c01 sago007 2017-03-15 17:56 633
                    CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 634
                    break;
6c5f2c01 sago007 2017-03-15 17:56 635
                case '}':
6c5f2c01 sago007 2017-03-15 17:56 636
                    is.Take();
6c5f2c01 sago007 2017-03-15 17:56 637
                    if (CEREAL_RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
6c5f2c01 sago007 2017-03-15 17:56 638
                        CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 639
                    return;
6c5f2c01 sago007 2017-03-15 17:56 640
                default:
6c5f2c01 sago007 2017-03-15 17:56 641
                    CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy
6c5f2c01 sago007 2017-03-15 17:56 642
            }
6c5f2c01 sago007 2017-03-15 17:56 643
6c5f2c01 sago007 2017-03-15 17:56 644
            if (parseFlags & kParseTrailingCommasFlag) {
6c5f2c01 sago007 2017-03-15 17:56 645
                if (is.Peek() == '}') {
6c5f2c01 sago007 2017-03-15 17:56 646
                    if (CEREAL_RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
6c5f2c01 sago007 2017-03-15 17:56 647
                        CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 648
                    is.Take();
6c5f2c01 sago007 2017-03-15 17:56 649
                    return;
6c5f2c01 sago007 2017-03-15 17:56 650
                }
6c5f2c01 sago007 2017-03-15 17:56 651
            }
6c5f2c01 sago007 2017-03-15 17:56 652
        }
6c5f2c01 sago007 2017-03-15 17:56 653
    }
6c5f2c01 sago007 2017-03-15 17:56 654
6c5f2c01 sago007 2017-03-15 17:56 655
    // Parse array: [ value, ... ]
6c5f2c01 sago007 2017-03-15 17:56 656
    template<unsigned parseFlags, typename InputStream, typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 657
    void ParseArray(InputStream& is, Handler& handler) {
6c5f2c01 sago007 2017-03-15 17:56 658
        CEREAL_RAPIDJSON_ASSERT(is.Peek() == '[');
6c5f2c01 sago007 2017-03-15 17:56 659
        is.Take();  // Skip '['
6c5f2c01 sago007 2017-03-15 17:56 660
6c5f2c01 sago007 2017-03-15 17:56 661
        if (CEREAL_RAPIDJSON_UNLIKELY(!handler.StartArray()))
6c5f2c01 sago007 2017-03-15 17:56 662
            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 663
6c5f2c01 sago007 2017-03-15 17:56 664
        SkipWhitespaceAndComments<parseFlags>(is);
6c5f2c01 sago007 2017-03-15 17:56 665
        CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 666
6c5f2c01 sago007 2017-03-15 17:56 667
        if (Consume(is, ']')) {
6c5f2c01 sago007 2017-03-15 17:56 668
            if (CEREAL_RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array
6c5f2c01 sago007 2017-03-15 17:56 669
                CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 670
            return;
6c5f2c01 sago007 2017-03-15 17:56 671
        }
6c5f2c01 sago007 2017-03-15 17:56 672
6c5f2c01 sago007 2017-03-15 17:56 673
        for (SizeType elementCount = 0;;) {
6c5f2c01 sago007 2017-03-15 17:56 674
            ParseValue<parseFlags>(is, handler);
6c5f2c01 sago007 2017-03-15 17:56 675
            CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 676
6c5f2c01 sago007 2017-03-15 17:56 677
            ++elementCount;
6c5f2c01 sago007 2017-03-15 17:56 678
            SkipWhitespaceAndComments<parseFlags>(is);
6c5f2c01 sago007 2017-03-15 17:56 679
            CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 680
6c5f2c01 sago007 2017-03-15 17:56 681
            if (Consume(is, ',')) {
6c5f2c01 sago007 2017-03-15 17:56 682
                SkipWhitespaceAndComments<parseFlags>(is);
6c5f2c01 sago007 2017-03-15 17:56 683
                CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 684
            }
6c5f2c01 sago007 2017-03-15 17:56 685
            else if (Consume(is, ']')) {
6c5f2c01 sago007 2017-03-15 17:56 686
                if (CEREAL_RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
6c5f2c01 sago007 2017-03-15 17:56 687
                    CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 688
                return;
6c5f2c01 sago007 2017-03-15 17:56 689
            }
6c5f2c01 sago007 2017-03-15 17:56 690
            else
6c5f2c01 sago007 2017-03-15 17:56 691
                CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 692
6c5f2c01 sago007 2017-03-15 17:56 693
            if (parseFlags & kParseTrailingCommasFlag) {
6c5f2c01 sago007 2017-03-15 17:56 694
                if (is.Peek() == ']') {
6c5f2c01 sago007 2017-03-15 17:56 695
                    if (CEREAL_RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
6c5f2c01 sago007 2017-03-15 17:56 696
                        CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 697
                    is.Take();
6c5f2c01 sago007 2017-03-15 17:56 698
                    return;
6c5f2c01 sago007 2017-03-15 17:56 699
                }
6c5f2c01 sago007 2017-03-15 17:56 700
            }
6c5f2c01 sago007 2017-03-15 17:56 701
        }
6c5f2c01 sago007 2017-03-15 17:56 702
    }
6c5f2c01 sago007 2017-03-15 17:56 703
6c5f2c01 sago007 2017-03-15 17:56 704
    template<unsigned parseFlags, typename InputStream, typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 705
    void ParseNull(InputStream& is, Handler& handler) {
6c5f2c01 sago007 2017-03-15 17:56 706
        CEREAL_RAPIDJSON_ASSERT(is.Peek() == 'n');
6c5f2c01 sago007 2017-03-15 17:56 707
        is.Take();
6c5f2c01 sago007 2017-03-15 17:56 708
6c5f2c01 sago007 2017-03-15 17:56 709
        if (CEREAL_RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) {
6c5f2c01 sago007 2017-03-15 17:56 710
            if (CEREAL_RAPIDJSON_UNLIKELY(!handler.Null()))
6c5f2c01 sago007 2017-03-15 17:56 711
                CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 712
        }
6c5f2c01 sago007 2017-03-15 17:56 713
        else
6c5f2c01 sago007 2017-03-15 17:56 714
            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 715
    }
6c5f2c01 sago007 2017-03-15 17:56 716
6c5f2c01 sago007 2017-03-15 17:56 717
    template<unsigned parseFlags, typename InputStream, typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 718
    void ParseTrue(InputStream& is, Handler& handler) {
6c5f2c01 sago007 2017-03-15 17:56 719
        CEREAL_RAPIDJSON_ASSERT(is.Peek() == 't');
6c5f2c01 sago007 2017-03-15 17:56 720
        is.Take();
6c5f2c01 sago007 2017-03-15 17:56 721
6c5f2c01 sago007 2017-03-15 17:56 722
        if (CEREAL_RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) {
6c5f2c01 sago007 2017-03-15 17:56 723
            if (CEREAL_RAPIDJSON_UNLIKELY(!handler.Bool(true)))
6c5f2c01 sago007 2017-03-15 17:56 724
                CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 725
        }
6c5f2c01 sago007 2017-03-15 17:56 726
        else
6c5f2c01 sago007 2017-03-15 17:56 727
            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 728
    }
6c5f2c01 sago007 2017-03-15 17:56 729
6c5f2c01 sago007 2017-03-15 17:56 730
    template<unsigned parseFlags, typename InputStream, typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 731
    void ParseFalse(InputStream& is, Handler& handler) {
6c5f2c01 sago007 2017-03-15 17:56 732
        CEREAL_RAPIDJSON_ASSERT(is.Peek() == 'f');
6c5f2c01 sago007 2017-03-15 17:56 733
        is.Take();
6c5f2c01 sago007 2017-03-15 17:56 734
6c5f2c01 sago007 2017-03-15 17:56 735
        if (CEREAL_RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) {
6c5f2c01 sago007 2017-03-15 17:56 736
            if (CEREAL_RAPIDJSON_UNLIKELY(!handler.Bool(false)))
6c5f2c01 sago007 2017-03-15 17:56 737
                CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 738
        }
6c5f2c01 sago007 2017-03-15 17:56 739
        else
6c5f2c01 sago007 2017-03-15 17:56 740
            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 741
    }
6c5f2c01 sago007 2017-03-15 17:56 742
6c5f2c01 sago007 2017-03-15 17:56 743
    template<typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 744
    CEREAL_RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
6c5f2c01 sago007 2017-03-15 17:56 745
        if (CEREAL_RAPIDJSON_LIKELY(is.Peek() == expect)) {
6c5f2c01 sago007 2017-03-15 17:56 746
            is.Take();
6c5f2c01 sago007 2017-03-15 17:56 747
            return true;
6c5f2c01 sago007 2017-03-15 17:56 748
        }
6c5f2c01 sago007 2017-03-15 17:56 749
        else
6c5f2c01 sago007 2017-03-15 17:56 750
            return false;
6c5f2c01 sago007 2017-03-15 17:56 751
    }
6c5f2c01 sago007 2017-03-15 17:56 752
6c5f2c01 sago007 2017-03-15 17:56 753
    // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
6c5f2c01 sago007 2017-03-15 17:56 754
    template<typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 755
    unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
6c5f2c01 sago007 2017-03-15 17:56 756
        unsigned codepoint = 0;
6c5f2c01 sago007 2017-03-15 17:56 757
        for (int i = 0; i < 4; i++) {
6c5f2c01 sago007 2017-03-15 17:56 758
            Ch c = is.Peek();
6c5f2c01 sago007 2017-03-15 17:56 759
            codepoint <<= 4;
6c5f2c01 sago007 2017-03-15 17:56 760
            codepoint += static_cast<unsigned>(c);
6c5f2c01 sago007 2017-03-15 17:56 761
            if (c >= '0' && c <= '9')
6c5f2c01 sago007 2017-03-15 17:56 762
                codepoint -= '0';
6c5f2c01 sago007 2017-03-15 17:56 763
            else if (c >= 'A' && c <= 'F')
6c5f2c01 sago007 2017-03-15 17:56 764
                codepoint -= 'A' - 10;
6c5f2c01 sago007 2017-03-15 17:56 765
            else if (c >= 'a' && c <= 'f')
6c5f2c01 sago007 2017-03-15 17:56 766
                codepoint -= 'a' - 10;
6c5f2c01 sago007 2017-03-15 17:56 767
            else {
6c5f2c01 sago007 2017-03-15 17:56 768
                CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset);
6c5f2c01 sago007 2017-03-15 17:56 769
                CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
6c5f2c01 sago007 2017-03-15 17:56 770
            }
6c5f2c01 sago007 2017-03-15 17:56 771
            is.Take();
6c5f2c01 sago007 2017-03-15 17:56 772
        }
6c5f2c01 sago007 2017-03-15 17:56 773
        return codepoint;
6c5f2c01 sago007 2017-03-15 17:56 774
    }
6c5f2c01 sago007 2017-03-15 17:56 775
6c5f2c01 sago007 2017-03-15 17:56 776
    template <typename CharType>
6c5f2c01 sago007 2017-03-15 17:56 777
    class StackStream {
6c5f2c01 sago007 2017-03-15 17:56 778
    public:
6c5f2c01 sago007 2017-03-15 17:56 779
        typedef CharType Ch;
6c5f2c01 sago007 2017-03-15 17:56 780
6c5f2c01 sago007 2017-03-15 17:56 781
        StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
6c5f2c01 sago007 2017-03-15 17:56 782
        CEREAL_RAPIDJSON_FORCEINLINE void Put(Ch c) {
6c5f2c01 sago007 2017-03-15 17:56 783
            *stack_.template Push<Ch>() = c;
6c5f2c01 sago007 2017-03-15 17:56 784
            ++length_;
6c5f2c01 sago007 2017-03-15 17:56 785
        }
6c5f2c01 sago007 2017-03-15 17:56 786
6c5f2c01 sago007 2017-03-15 17:56 787
        CEREAL_RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
6c5f2c01 sago007 2017-03-15 17:56 788
            length_ += count;
6c5f2c01 sago007 2017-03-15 17:56 789
            return stack_.template Push<Ch>(count);
6c5f2c01 sago007 2017-03-15 17:56 790
        }
6c5f2c01 sago007 2017-03-15 17:56 791
6c5f2c01 sago007 2017-03-15 17:56 792
        size_t Length() const { return length_; }
6c5f2c01 sago007 2017-03-15 17:56 793
6c5f2c01 sago007 2017-03-15 17:56 794
        Ch* Pop() {
6c5f2c01 sago007 2017-03-15 17:56 795
            return stack_.template Pop<Ch>(length_);
6c5f2c01 sago007 2017-03-15 17:56 796
        }
6c5f2c01 sago007 2017-03-15 17:56 797
6c5f2c01 sago007 2017-03-15 17:56 798
    private:
6c5f2c01 sago007 2017-03-15 17:56 799
        StackStream(const StackStream&);
6c5f2c01 sago007 2017-03-15 17:56 800
        StackStream& operator=(const StackStream&);
6c5f2c01 sago007 2017-03-15 17:56 801
6c5f2c01 sago007 2017-03-15 17:56 802
        internal::Stack<StackAllocator>& stack_;
6c5f2c01 sago007 2017-03-15 17:56 803
        SizeType length_;
6c5f2c01 sago007 2017-03-15 17:56 804
    };
6c5f2c01 sago007 2017-03-15 17:56 805
6c5f2c01 sago007 2017-03-15 17:56 806
    // Parse string and generate String event. Different code paths for kParseInsituFlag.
6c5f2c01 sago007 2017-03-15 17:56 807
    template<unsigned parseFlags, typename InputStream, typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 808
    void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
6c5f2c01 sago007 2017-03-15 17:56 809
        internal::StreamLocalCopy<InputStream> copy(is);
6c5f2c01 sago007 2017-03-15 17:56 810
        InputStream& s(copy.s);
6c5f2c01 sago007 2017-03-15 17:56 811
6c5f2c01 sago007 2017-03-15 17:56 812
        CEREAL_RAPIDJSON_ASSERT(s.Peek() == '\"');
6c5f2c01 sago007 2017-03-15 17:56 813
        s.Take();  // Skip '\"'
6c5f2c01 sago007 2017-03-15 17:56 814
6c5f2c01 sago007 2017-03-15 17:56 815
        bool success = false;
6c5f2c01 sago007 2017-03-15 17:56 816
        if (parseFlags & kParseInsituFlag) {
6c5f2c01 sago007 2017-03-15 17:56 817
            typename InputStream::Ch *head = s.PutBegin();
6c5f2c01 sago007 2017-03-15 17:56 818
            ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
6c5f2c01 sago007 2017-03-15 17:56 819
            CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 820
            size_t length = s.PutEnd(head) - 1;
6c5f2c01 sago007 2017-03-15 17:56 821
            CEREAL_RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
6c5f2c01 sago007 2017-03-15 17:56 822
            const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
6c5f2c01 sago007 2017-03-15 17:56 823
            success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
6c5f2c01 sago007 2017-03-15 17:56 824
        }
6c5f2c01 sago007 2017-03-15 17:56 825
        else {
6c5f2c01 sago007 2017-03-15 17:56 826
            StackStream<typename TargetEncoding::Ch> stackStream(stack_);
6c5f2c01 sago007 2017-03-15 17:56 827
            ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
6c5f2c01 sago007 2017-03-15 17:56 828
            CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 829
            SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
6c5f2c01 sago007 2017-03-15 17:56 830
            const typename TargetEncoding::Ch* const str = stackStream.Pop();
6c5f2c01 sago007 2017-03-15 17:56 831
            success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
6c5f2c01 sago007 2017-03-15 17:56 832
        }
6c5f2c01 sago007 2017-03-15 17:56 833
        if (CEREAL_RAPIDJSON_UNLIKELY(!success))
6c5f2c01 sago007 2017-03-15 17:56 834
            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
6c5f2c01 sago007 2017-03-15 17:56 835
    }
6c5f2c01 sago007 2017-03-15 17:56 836
6c5f2c01 sago007 2017-03-15 17:56 837
    // Parse string to an output is
6c5f2c01 sago007 2017-03-15 17:56 838
    // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
6c5f2c01 sago007 2017-03-15 17:56 839
    template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
6c5f2c01 sago007 2017-03-15 17:56 840
    CEREAL_RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
6c5f2c01 sago007 2017-03-15 17:56 841
//!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN
6c5f2c01 sago007 2017-03-15 17:56 842
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
6c5f2c01 sago007 2017-03-15 17:56 843
        static const char escape[256] = {
6c5f2c01 sago007 2017-03-15 17:56 844
            Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
6c5f2c01 sago007 2017-03-15 17:56 845
            Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
6c5f2c01 sago007 2017-03-15 17:56 846
            0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
6c5f2c01 sago007 2017-03-15 17:56 847
            0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6c5f2c01 sago007 2017-03-15 17:56 848
            Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
6c5f2c01 sago007 2017-03-15 17:56 849
        };
6c5f2c01 sago007 2017-03-15 17:56 850
#undef Z16
6c5f2c01 sago007 2017-03-15 17:56 851
//!@endcond
6c5f2c01 sago007 2017-03-15 17:56 852
6c5f2c01 sago007 2017-03-15 17:56 853
        for (;;) {
6c5f2c01 sago007 2017-03-15 17:56 854
            // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
6c5f2c01 sago007 2017-03-15 17:56 855
            if (!(parseFlags & kParseValidateEncodingFlag))
6c5f2c01 sago007 2017-03-15 17:56 856
                ScanCopyUnescapedString(is, os);
6c5f2c01 sago007 2017-03-15 17:56 857
6c5f2c01 sago007 2017-03-15 17:56 858
            Ch c = is.Peek();
6c5f2c01 sago007 2017-03-15 17:56 859
            if (CEREAL_RAPIDJSON_UNLIKELY(c == '\\')) {    // Escape
6c5f2c01 sago007 2017-03-15 17:56 860
                size_t escapeOffset = is.Tell();    // For invalid escaping, report the inital '\\' as error offset
6c5f2c01 sago007 2017-03-15 17:56 861
                is.Take();
6c5f2c01 sago007 2017-03-15 17:56 862
                Ch e = is.Peek();
6c5f2c01 sago007 2017-03-15 17:56 863
                if ((sizeof(Ch) == 1 || unsigned(e) < 256) && CEREAL_RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
6c5f2c01 sago007 2017-03-15 17:56 864
                    is.Take();
6c5f2c01 sago007 2017-03-15 17:56 865
                    os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
6c5f2c01 sago007 2017-03-15 17:56 866
                }
6c5f2c01 sago007 2017-03-15 17:56 867
                else if (CEREAL_RAPIDJSON_LIKELY(e == 'u')) {    // Unicode
6c5f2c01 sago007 2017-03-15 17:56 868
                    is.Take();
6c5f2c01 sago007 2017-03-15 17:56 869
                    unsigned codepoint = ParseHex4(is, escapeOffset);
6c5f2c01 sago007 2017-03-15 17:56 870
                    CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 871
                    if (CEREAL_RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) {
6c5f2c01 sago007 2017-03-15 17:56 872
                        // Handle UTF-16 surrogate pair
6c5f2c01 sago007 2017-03-15 17:56 873
                        if (CEREAL_RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
6c5f2c01 sago007 2017-03-15 17:56 874
                            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
6c5f2c01 sago007 2017-03-15 17:56 875
                        unsigned codepoint2 = ParseHex4(is, escapeOffset);
6c5f2c01 sago007 2017-03-15 17:56 876
                        CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
6c5f2c01 sago007 2017-03-15 17:56 877
                        if (CEREAL_RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
6c5f2c01 sago007 2017-03-15 17:56 878
                            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
6c5f2c01 sago007 2017-03-15 17:56 879
                        codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
6c5f2c01 sago007 2017-03-15 17:56 880
                    }
6c5f2c01 sago007 2017-03-15 17:56 881
                    TEncoding::Encode(os, codepoint);
6c5f2c01 sago007 2017-03-15 17:56 882
                }
6c5f2c01 sago007 2017-03-15 17:56 883
                else
6c5f2c01 sago007 2017-03-15 17:56 884
                    CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset);
6c5f2c01 sago007 2017-03-15 17:56 885
            }
6c5f2c01 sago007 2017-03-15 17:56 886
            else if (CEREAL_RAPIDJSON_UNLIKELY(c == '"')) {    // Closing double quote
6c5f2c01 sago007 2017-03-15 17:56 887
                is.Take();
6c5f2c01 sago007 2017-03-15 17:56 888
                os.Put('\0');   // null-terminate the string
6c5f2c01 sago007 2017-03-15 17:56 889
                return;
6c5f2c01 sago007 2017-03-15 17:56 890
            }
6c5f2c01 sago007 2017-03-15 17:56 891
            else if (CEREAL_RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
6c5f2c01 sago007 2017-03-15 17:56 892
                if (c == '\0')
6c5f2c01 sago007 2017-03-15 17:56 893
                    CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 894
                else
6c5f2c01 sago007 2017-03-15 17:56 895
                    CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 896
            }
6c5f2c01 sago007 2017-03-15 17:56 897
            else {
6c5f2c01 sago007 2017-03-15 17:56 898
                size_t offset = is.Tell();
6c5f2c01 sago007 2017-03-15 17:56 899
                if (CEREAL_RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
6c5f2c01 sago007 2017-03-15 17:56 900
                    !Transcoder<SEncoding, TEncoding>::Validate(is, os) :
6c5f2c01 sago007 2017-03-15 17:56 901
                    !Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
6c5f2c01 sago007 2017-03-15 17:56 902
                    CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
6c5f2c01 sago007 2017-03-15 17:56 903
            }
6c5f2c01 sago007 2017-03-15 17:56 904
        }
6c5f2c01 sago007 2017-03-15 17:56 905
    }
6c5f2c01 sago007 2017-03-15 17:56 906
6c5f2c01 sago007 2017-03-15 17:56 907
    template<typename InputStream, typename OutputStream>
6c5f2c01 sago007 2017-03-15 17:56 908
    static CEREAL_RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
6c5f2c01 sago007 2017-03-15 17:56 909
            // Do nothing for generic version
6c5f2c01 sago007 2017-03-15 17:56 910
    }
6c5f2c01 sago007 2017-03-15 17:56 911
6c5f2c01 sago007 2017-03-15 17:56 912
#if defined(CEREAL_RAPIDJSON_SSE2) || defined(CEREAL_RAPIDJSON_SSE42)
6c5f2c01 sago007 2017-03-15 17:56 913
    // StringStream -> StackStream<char>
6c5f2c01 sago007 2017-03-15 17:56 914
    static CEREAL_RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
6c5f2c01 sago007 2017-03-15 17:56 915
        const char* p = is.src_;
6c5f2c01 sago007 2017-03-15 17:56 916
6c5f2c01 sago007 2017-03-15 17:56 917
        // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
6c5f2c01 sago007 2017-03-15 17:56 918
        const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
6c5f2c01 sago007 2017-03-15 17:56 919
        while (p != nextAligned)
6c5f2c01 sago007 2017-03-15 17:56 920
            if (CEREAL_RAPIDJSON_UNLIKELY(*p == '\"') || CEREAL_RAPIDJSON_UNLIKELY(*p == '\\') || CEREAL_RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
6c5f2c01 sago007 2017-03-15 17:56 921
                is.src_ = p;
6c5f2c01 sago007 2017-03-15 17:56 922
                return;
6c5f2c01 sago007 2017-03-15 17:56 923
            }
6c5f2c01 sago007 2017-03-15 17:56 924
            else
6c5f2c01 sago007 2017-03-15 17:56 925
                os.Put(*p++);
6c5f2c01 sago007 2017-03-15 17:56 926
6c5f2c01 sago007 2017-03-15 17:56 927
        // The rest of string using SIMD
6c5f2c01 sago007 2017-03-15 17:56 928
        static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
6c5f2c01 sago007 2017-03-15 17:56 929
        static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
6c5f2c01 sago007 2017-03-15 17:56 930
        static const char space[16]  = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
6c5f2c01 sago007 2017-03-15 17:56 931
        const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
6c5f2c01 sago007 2017-03-15 17:56 932
        const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
6c5f2c01 sago007 2017-03-15 17:56 933
        const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
6c5f2c01 sago007 2017-03-15 17:56 934
6c5f2c01 sago007 2017-03-15 17:56 935
        for (;; p += 16) {
6c5f2c01 sago007 2017-03-15 17:56 936
            const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
6c5f2c01 sago007 2017-03-15 17:56 937
            const __m128i t1 = _mm_cmpeq_epi8(s, dq);
6c5f2c01 sago007 2017-03-15 17:56 938
            const __m128i t2 = _mm_cmpeq_epi8(s, bs);
6c5f2c01 sago007 2017-03-15 17:56 939
            const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
6c5f2c01 sago007 2017-03-15 17:56 940
            const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
6c5f2c01 sago007 2017-03-15 17:56 941
            unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
6c5f2c01 sago007 2017-03-15 17:56 942
            if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped
6c5f2c01 sago007 2017-03-15 17:56 943
                SizeType length;
6c5f2c01 sago007 2017-03-15 17:56 944
    #ifdef _MSC_VER         // Find the index of first escaped
6c5f2c01 sago007 2017-03-15 17:56 945
                unsigned long offset;
6c5f2c01 sago007 2017-03-15 17:56 946
                _BitScanForward(&offset, r);
6c5f2c01 sago007 2017-03-15 17:56 947
                length = offset;
6c5f2c01 sago007 2017-03-15 17:56 948
    #else
6c5f2c01 sago007 2017-03-15 17:56 949
                length = static_cast<SizeType>(__builtin_ffs(r) - 1);
6c5f2c01 sago007 2017-03-15 17:56 950
    #endif
6c5f2c01 sago007 2017-03-15 17:56 951
                char* q = reinterpret_cast<char*>(os.Push(length));
6c5f2c01 sago007 2017-03-15 17:56 952
                for (size_t i = 0; i < length; i++)
6c5f2c01 sago007 2017-03-15 17:56 953
                    q[i] = p[i];
6c5f2c01 sago007 2017-03-15 17:56 954
6c5f2c01 sago007 2017-03-15 17:56 955
                p += length;
6c5f2c01 sago007 2017-03-15 17:56 956
                break;
6c5f2c01 sago007 2017-03-15 17:56 957
            }
6c5f2c01 sago007 2017-03-15 17:56 958
            _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
6c5f2c01 sago007 2017-03-15 17:56 959
        }
6c5f2c01 sago007 2017-03-15 17:56 960
6c5f2c01 sago007 2017-03-15 17:56 961
        is.src_ = p;
6c5f2c01 sago007 2017-03-15 17:56 962
    }
6c5f2c01 sago007 2017-03-15 17:56 963
6c5f2c01 sago007 2017-03-15 17:56 964
    // InsituStringStream -> InsituStringStream
6c5f2c01 sago007 2017-03-15 17:56 965
    static CEREAL_RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
6c5f2c01 sago007 2017-03-15 17:56 966
        CEREAL_RAPIDJSON_ASSERT(&is == &os);
6c5f2c01 sago007 2017-03-15 17:56 967
        (void)os;
6c5f2c01 sago007 2017-03-15 17:56 968
6c5f2c01 sago007 2017-03-15 17:56 969
        if (is.src_ == is.dst_) {
6c5f2c01 sago007 2017-03-15 17:56 970
            SkipUnescapedString(is);
6c5f2c01 sago007 2017-03-15 17:56 971
            return;
6c5f2c01 sago007 2017-03-15 17:56 972
        }
6c5f2c01 sago007 2017-03-15 17:56 973
6c5f2c01 sago007 2017-03-15 17:56 974
        char* p = is.src_;
6c5f2c01 sago007 2017-03-15 17:56 975
        char *q = is.dst_;
6c5f2c01 sago007 2017-03-15 17:56 976
6c5f2c01 sago007 2017-03-15 17:56 977
        // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
6c5f2c01 sago007 2017-03-15 17:56 978
        const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
6c5f2c01 sago007 2017-03-15 17:56 979
        while (p != nextAligned)
6c5f2c01 sago007 2017-03-15 17:56 980
            if (CEREAL_RAPIDJSON_UNLIKELY(*p == '\"') || CEREAL_RAPIDJSON_UNLIKELY(*p == '\\') || CEREAL_RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
6c5f2c01 sago007 2017-03-15 17:56 981
                is.src_ = p;
6c5f2c01 sago007 2017-03-15 17:56 982
                is.dst_ = q;
6c5f2c01 sago007 2017-03-15 17:56 983
                return;
6c5f2c01 sago007 2017-03-15 17:56 984
            }
6c5f2c01 sago007 2017-03-15 17:56 985
            else
6c5f2c01 sago007 2017-03-15 17:56 986
                *q++ = *p++;
6c5f2c01 sago007 2017-03-15 17:56 987
6c5f2c01 sago007 2017-03-15 17:56 988
        // The rest of string using SIMD
6c5f2c01 sago007 2017-03-15 17:56 989
        static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
6c5f2c01 sago007 2017-03-15 17:56 990
        static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
6c5f2c01 sago007 2017-03-15 17:56 991
        static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
6c5f2c01 sago007 2017-03-15 17:56 992
        const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
6c5f2c01 sago007 2017-03-15 17:56 993
        const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
6c5f2c01 sago007 2017-03-15 17:56 994
        const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
6c5f2c01 sago007 2017-03-15 17:56 995
6c5f2c01 sago007 2017-03-15 17:56 996
        for (;; p += 16, q += 16) {
6c5f2c01 sago007 2017-03-15 17:56 997
            const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
6c5f2c01 sago007 2017-03-15 17:56 998
            const __m128i t1 = _mm_cmpeq_epi8(s, dq);
6c5f2c01 sago007 2017-03-15 17:56 999
            const __m128i t2 = _mm_cmpeq_epi8(s, bs);
6c5f2c01 sago007 2017-03-15 17:56 1000
            const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
6c5f2c01 sago007 2017-03-15 17:56 1001
            const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
6c5f2c01 sago007 2017-03-15 17:56 1002
            unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
6c5f2c01 sago007 2017-03-15 17:56 1003
            if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped
6c5f2c01 sago007 2017-03-15 17:56 1004
                size_t length;
6c5f2c01 sago007 2017-03-15 17:56 1005
#ifdef _MSC_VER         // Find the index of first escaped
6c5f2c01 sago007 2017-03-15 17:56 1006
                unsigned long offset;
6c5f2c01 sago007 2017-03-15 17:56 1007
                _BitScanForward(&offset, r);
6c5f2c01 sago007 2017-03-15 17:56 1008
                length = offset;
6c5f2c01 sago007 2017-03-15 17:56 1009
#else
6c5f2c01 sago007 2017-03-15 17:56 1010
                length = static_cast<size_t>(__builtin_ffs(r) - 1);
7a956470 sago007 2016-02-14 17:09 1011
#endif
6c5f2c01 sago007 2017-03-15 17:56 1012
                for (const char* pend = p + length; p != pend; )
6c5f2c01 sago007 2017-03-15 17:56 1013
                    *q++ = *p++;
6c5f2c01 sago007 2017-03-15 17:56 1014
                break;
6c5f2c01 sago007 2017-03-15 17:56 1015
            }
6c5f2c01 sago007 2017-03-15 17:56 1016
            _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s);
6c5f2c01 sago007 2017-03-15 17:56 1017
        }
6c5f2c01 sago007 2017-03-15 17:56 1018
6c5f2c01 sago007 2017-03-15 17:56 1019
        is.src_ = p;
6c5f2c01 sago007 2017-03-15 17:56 1020
        is.dst_ = q;
6c5f2c01 sago007 2017-03-15 17:56 1021
    }
6c5f2c01 sago007 2017-03-15 17:56 1022
6c5f2c01 sago007 2017-03-15 17:56 1023
    // When read/write pointers are the same for insitu stream, just skip unescaped characters
6c5f2c01 sago007 2017-03-15 17:56 1024
    static CEREAL_RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
6c5f2c01 sago007 2017-03-15 17:56 1025
        CEREAL_RAPIDJSON_ASSERT(is.src_ == is.dst_);
6c5f2c01 sago007 2017-03-15 17:56 1026
        char* p = is.src_;
6c5f2c01 sago007 2017-03-15 17:56 1027
6c5f2c01 sago007 2017-03-15 17:56 1028
        // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
6c5f2c01 sago007 2017-03-15 17:56 1029
        const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
6c5f2c01 sago007 2017-03-15 17:56 1030
        for (; p != nextAligned; p++)
6c5f2c01 sago007 2017-03-15 17:56 1031
            if (CEREAL_RAPIDJSON_UNLIKELY(*p == '\"') || CEREAL_RAPIDJSON_UNLIKELY(*p == '\\') || CEREAL_RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
6c5f2c01 sago007 2017-03-15 17:56 1032
                is.src_ = is.dst_ = p;
6c5f2c01 sago007 2017-03-15 17:56 1033
                return;
6c5f2c01 sago007 2017-03-15 17:56 1034
            }
6c5f2c01 sago007 2017-03-15 17:56 1035
6c5f2c01 sago007 2017-03-15 17:56 1036
        // The rest of string using SIMD
6c5f2c01 sago007 2017-03-15 17:56 1037
        static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
6c5f2c01 sago007 2017-03-15 17:56 1038
        static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
6c5f2c01 sago007 2017-03-15 17:56 1039
        static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
6c5f2c01 sago007 2017-03-15 17:56 1040
        const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
6c5f2c01 sago007 2017-03-15 17:56 1041
        const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
6c5f2c01 sago007 2017-03-15 17:56 1042
        const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
6c5f2c01 sago007 2017-03-15 17:56 1043
6c5f2c01 sago007 2017-03-15 17:56 1044
        for (;; p += 16) {
6c5f2c01 sago007 2017-03-15 17:56 1045
            const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
6c5f2c01 sago007 2017-03-15 17:56 1046
            const __m128i t1 = _mm_cmpeq_epi8(s, dq);
6c5f2c01 sago007 2017-03-15 17:56 1047
            const __m128i t2 = _mm_cmpeq_epi8(s, bs);
6c5f2c01 sago007 2017-03-15 17:56 1048
            const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
6c5f2c01 sago007 2017-03-15 17:56 1049
            const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
6c5f2c01 sago007 2017-03-15 17:56 1050
            unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
6c5f2c01 sago007 2017-03-15 17:56 1051
            if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped
6c5f2c01 sago007 2017-03-15 17:56 1052
                size_t length;
6c5f2c01 sago007 2017-03-15 17:56 1053
#ifdef _MSC_VER         // Find the index of first escaped
6c5f2c01 sago007 2017-03-15 17:56 1054
                unsigned long offset;
6c5f2c01 sago007 2017-03-15 17:56 1055
                _BitScanForward(&offset, r);
6c5f2c01 sago007 2017-03-15 17:56 1056
                length = offset;
6c5f2c01 sago007 2017-03-15 17:56 1057
#else
6c5f2c01 sago007 2017-03-15 17:56 1058
                length = static_cast<size_t>(__builtin_ffs(r) - 1);
7a956470 sago007 2016-02-14 17:09 1059
#endif
6c5f2c01 sago007 2017-03-15 17:56 1060
                p += length;
6c5f2c01 sago007 2017-03-15 17:56 1061
                break;
6c5f2c01 sago007 2017-03-15 17:56 1062
            }
6c5f2c01 sago007 2017-03-15 17:56 1063
        }
7a956470 sago007 2016-02-14 17:09 1064
6c5f2c01 sago007 2017-03-15 17:56 1065
        is.src_ = is.dst_ = p;
6c5f2c01 sago007 2017-03-15 17:56 1066
    }
6c5f2c01 sago007 2017-03-15 17:56 1067
#endif
7a956470 sago007 2016-02-14 17:09 1068
6c5f2c01 sago007 2017-03-15 17:56 1069
    template<typename InputStream, bool backup, bool pushOnTake>
6c5f2c01 sago007 2017-03-15 17:56 1070
    class NumberStream;
6c5f2c01 sago007 2017-03-15 17:56 1071
6c5f2c01 sago007 2017-03-15 17:56 1072
    template<typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 1073
    class NumberStream<InputStream, false, false> {
6c5f2c01 sago007 2017-03-15 17:56 1074
    public:
6c5f2c01 sago007 2017-03-15 17:56 1075
        typedef typename InputStream::Ch Ch;
6c5f2c01 sago007 2017-03-15 17:56 1076
6c5f2c01 sago007 2017-03-15 17:56 1077
        NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader;  }
6c5f2c01 sago007 2017-03-15 17:56 1078
        ~NumberStream() {}
6c5f2c01 sago007 2017-03-15 17:56 1079
6c5f2c01 sago007 2017-03-15 17:56 1080
        CEREAL_RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
6c5f2c01 sago007 2017-03-15 17:56 1081
        CEREAL_RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
6c5f2c01 sago007 2017-03-15 17:56 1082
        CEREAL_RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
6c5f2c01 sago007 2017-03-15 17:56 1083
		  CEREAL_RAPIDJSON_FORCEINLINE void Push(char) {}
6c5f2c01 sago007 2017-03-15 17:56 1084
6c5f2c01 sago007 2017-03-15 17:56 1085
        size_t Tell() { return is.Tell(); }
6c5f2c01 sago007 2017-03-15 17:56 1086
        size_t Length() { return 0; }
6c5f2c01 sago007 2017-03-15 17:56 1087
        const char* Pop() { return 0; }
6c5f2c01 sago007 2017-03-15 17:56 1088
6c5f2c01 sago007 2017-03-15 17:56 1089
    protected:
6c5f2c01 sago007 2017-03-15 17:56 1090
        NumberStream& operator=(const NumberStream&);
6c5f2c01 sago007 2017-03-15 17:56 1091
6c5f2c01 sago007 2017-03-15 17:56 1092
        InputStream& is;
6c5f2c01 sago007 2017-03-15 17:56 1093
    };
6c5f2c01 sago007 2017-03-15 17:56 1094
6c5f2c01 sago007 2017-03-15 17:56 1095
    template<typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 1096
    class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
6c5f2c01 sago007 2017-03-15 17:56 1097
        typedef NumberStream<InputStream, false, false> Base;
6c5f2c01 sago007 2017-03-15 17:56 1098
    public:
6c5f2c01 sago007 2017-03-15 17:56 1099
        NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s), stackStream(reader.stack_) {}
6c5f2c01 sago007 2017-03-15 17:56 1100
        ~NumberStream() {}
6c5f2c01 sago007 2017-03-15 17:56 1101
6c5f2c01 sago007 2017-03-15 17:56 1102
        CEREAL_RAPIDJSON_FORCEINLINE Ch TakePush() {
6c5f2c01 sago007 2017-03-15 17:56 1103
            stackStream.Put(static_cast<char>(Base::is.Peek()));
6c5f2c01 sago007 2017-03-15 17:56 1104
            return Base::is.Take();
6c5f2c01 sago007 2017-03-15 17:56 1105
        }
6c5f2c01 sago007 2017-03-15 17:56 1106
6c5f2c01 sago007 2017-03-15 17:56 1107
        CEREAL_RAPIDJSON_FORCEINLINE void Push(char c) {
6c5f2c01 sago007 2017-03-15 17:56 1108
            stackStream.Put(c);
6c5f2c01 sago007 2017-03-15 17:56 1109
        }
6c5f2c01 sago007 2017-03-15 17:56 1110
6c5f2c01 sago007 2017-03-15 17:56 1111
        size_t Length() { return stackStream.Length(); }
6c5f2c01 sago007 2017-03-15 17:56 1112
6c5f2c01 sago007 2017-03-15 17:56 1113
        const char* Pop() {
6c5f2c01 sago007 2017-03-15 17:56 1114
            stackStream.Put('\0');
6c5f2c01 sago007 2017-03-15 17:56 1115
            return stackStream.Pop();
6c5f2c01 sago007 2017-03-15 17:56 1116
        }
6c5f2c01 sago007 2017-03-15 17:56 1117
6c5f2c01 sago007 2017-03-15 17:56 1118
    private:
6c5f2c01 sago007 2017-03-15 17:56 1119
        StackStream<char> stackStream;
6c5f2c01 sago007 2017-03-15 17:56 1120
    };
6c5f2c01 sago007 2017-03-15 17:56 1121
6c5f2c01 sago007 2017-03-15 17:56 1122
    template<typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 1123
    class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
6c5f2c01 sago007 2017-03-15 17:56 1124
        typedef NumberStream<InputStream, true, false> Base;
6c5f2c01 sago007 2017-03-15 17:56 1125
    public:
6c5f2c01 sago007 2017-03-15 17:56 1126
        NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
6c5f2c01 sago007 2017-03-15 17:56 1127
        ~NumberStream() {}
6c5f2c01 sago007 2017-03-15 17:56 1128
6c5f2c01 sago007 2017-03-15 17:56 1129
        CEREAL_RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
6c5f2c01 sago007 2017-03-15 17:56 1130
    };
6c5f2c01 sago007 2017-03-15 17:56 1131
6c5f2c01 sago007 2017-03-15 17:56 1132
    template<unsigned parseFlags, typename InputStream, typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 1133
    void ParseNumber(InputStream& is, Handler& handler) {
6c5f2c01 sago007 2017-03-15 17:56 1134
        internal::StreamLocalCopy<InputStream> copy(is);
6c5f2c01 sago007 2017-03-15 17:56 1135
        NumberStream<InputStream,
6c5f2c01 sago007 2017-03-15 17:56 1136
            ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
6c5f2c01 sago007 2017-03-15 17:56 1137
                ((parseFlags & kParseInsituFlag) == 0) :
6c5f2c01 sago007 2017-03-15 17:56 1138
                ((parseFlags & kParseFullPrecisionFlag) != 0),
6c5f2c01 sago007 2017-03-15 17:56 1139
            (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
6c5f2c01 sago007 2017-03-15 17:56 1140
                (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
6c5f2c01 sago007 2017-03-15 17:56 1141
6c5f2c01 sago007 2017-03-15 17:56 1142
        size_t startOffset = s.Tell();
6c5f2c01 sago007 2017-03-15 17:56 1143
        double d = 0.0;
6c5f2c01 sago007 2017-03-15 17:56 1144
        bool useNanOrInf = false;
6c5f2c01 sago007 2017-03-15 17:56 1145
6c5f2c01 sago007 2017-03-15 17:56 1146
        // Parse minus
6c5f2c01 sago007 2017-03-15 17:56 1147
        bool minus = Consume(s, '-');
6c5f2c01 sago007 2017-03-15 17:56 1148
6c5f2c01 sago007 2017-03-15 17:56 1149
        // Parse int: zero / ( digit1-9 *DIGIT )
6c5f2c01 sago007 2017-03-15 17:56 1150
        unsigned i = 0;
6c5f2c01 sago007 2017-03-15 17:56 1151
        uint64_t i64 = 0;
6c5f2c01 sago007 2017-03-15 17:56 1152
        bool use64bit = false;
6c5f2c01 sago007 2017-03-15 17:56 1153
        int significandDigit = 0;
6c5f2c01 sago007 2017-03-15 17:56 1154
        if (CEREAL_RAPIDJSON_UNLIKELY(s.Peek() == '0')) {
6c5f2c01 sago007 2017-03-15 17:56 1155
            i = 0;
6c5f2c01 sago007 2017-03-15 17:56 1156
            s.TakePush();
6c5f2c01 sago007 2017-03-15 17:56 1157
        }
6c5f2c01 sago007 2017-03-15 17:56 1158
        else if (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) {
6c5f2c01 sago007 2017-03-15 17:56 1159
            i = static_cast<unsigned>(s.TakePush() - '0');
6c5f2c01 sago007 2017-03-15 17:56 1160
6c5f2c01 sago007 2017-03-15 17:56 1161
            if (minus)
6c5f2c01 sago007 2017-03-15 17:56 1162
                while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
6c5f2c01 sago007 2017-03-15 17:56 1163
                    if (CEREAL_RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648
6c5f2c01 sago007 2017-03-15 17:56 1164
                        if (CEREAL_RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) {
6c5f2c01 sago007 2017-03-15 17:56 1165
                            i64 = i;
6c5f2c01 sago007 2017-03-15 17:56 1166
                            use64bit = true;
6c5f2c01 sago007 2017-03-15 17:56 1167
                            break;
6c5f2c01 sago007 2017-03-15 17:56 1168
                        }
6c5f2c01 sago007 2017-03-15 17:56 1169
                    }
6c5f2c01 sago007 2017-03-15 17:56 1170
                    i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
6c5f2c01 sago007 2017-03-15 17:56 1171
                    significandDigit++;
6c5f2c01 sago007 2017-03-15 17:56 1172
                }
6c5f2c01 sago007 2017-03-15 17:56 1173
            else
6c5f2c01 sago007 2017-03-15 17:56 1174
                while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
6c5f2c01 sago007 2017-03-15 17:56 1175
                    if (CEREAL_RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295
6c5f2c01 sago007 2017-03-15 17:56 1176
                        if (CEREAL_RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {
6c5f2c01 sago007 2017-03-15 17:56 1177
                            i64 = i;
6c5f2c01 sago007 2017-03-15 17:56 1178
                            use64bit = true;
6c5f2c01 sago007 2017-03-15 17:56 1179
                            break;
6c5f2c01 sago007 2017-03-15 17:56 1180
                        }
6c5f2c01 sago007 2017-03-15 17:56 1181
                    }
6c5f2c01 sago007 2017-03-15 17:56 1182
                    i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
6c5f2c01 sago007 2017-03-15 17:56 1183
                    significandDigit++;
6c5f2c01 sago007 2017-03-15 17:56 1184
                }
6c5f2c01 sago007 2017-03-15 17:56 1185
        }
6c5f2c01 sago007 2017-03-15 17:56 1186
        // Parse NaN or Infinity here
6c5f2c01 sago007 2017-03-15 17:56 1187
        else if ((parseFlags & kParseNanAndInfFlag) && CEREAL_RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
6c5f2c01 sago007 2017-03-15 17:56 1188
            useNanOrInf = true;
6c5f2c01 sago007 2017-03-15 17:56 1189
            if (CEREAL_RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) {
6c5f2c01 sago007 2017-03-15 17:56 1190
                d = std::numeric_limits<double>::quiet_NaN();
6c5f2c01 sago007 2017-03-15 17:56 1191
            }
6c5f2c01 sago007 2017-03-15 17:56 1192
            else if (CEREAL_RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) {
6c5f2c01 sago007 2017-03-15 17:56 1193
                d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
6c5f2c01 sago007 2017-03-15 17:56 1194
                if (CEREAL_RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
6c5f2c01 sago007 2017-03-15 17:56 1195
                                                            && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y'))))
6c5f2c01 sago007 2017-03-15 17:56 1196
                    CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
6c5f2c01 sago007 2017-03-15 17:56 1197
            }
6c5f2c01 sago007 2017-03-15 17:56 1198
            else
6c5f2c01 sago007 2017-03-15 17:56 1199
                CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
6c5f2c01 sago007 2017-03-15 17:56 1200
        }
6c5f2c01 sago007 2017-03-15 17:56 1201
        else
6c5f2c01 sago007 2017-03-15 17:56 1202
            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
6c5f2c01 sago007 2017-03-15 17:56 1203
6c5f2c01 sago007 2017-03-15 17:56 1204
        // Parse 64bit int
6c5f2c01 sago007 2017-03-15 17:56 1205
        bool useDouble = false;
6c5f2c01 sago007 2017-03-15 17:56 1206
        if (use64bit) {
6c5f2c01 sago007 2017-03-15 17:56 1207
            if (minus)
6c5f2c01 sago007 2017-03-15 17:56 1208
                while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
6c5f2c01 sago007 2017-03-15 17:56 1209
                     if (CEREAL_RAPIDJSON_UNLIKELY(i64 >= CEREAL_RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
6c5f2c01 sago007 2017-03-15 17:56 1210
                        if (CEREAL_RAPIDJSON_LIKELY(i64 != CEREAL_RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
6c5f2c01 sago007 2017-03-15 17:56 1211
                            d = static_cast<double>(i64);
6c5f2c01 sago007 2017-03-15 17:56 1212
                            useDouble = true;
6c5f2c01 sago007 2017-03-15 17:56 1213
                            break;
6c5f2c01 sago007 2017-03-15 17:56 1214
                        }
6c5f2c01 sago007 2017-03-15 17:56 1215
                    i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
6c5f2c01 sago007 2017-03-15 17:56 1216
                    significandDigit++;
6c5f2c01 sago007 2017-03-15 17:56 1217
                }
6c5f2c01 sago007 2017-03-15 17:56 1218
            else
6c5f2c01 sago007 2017-03-15 17:56 1219
                while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
6c5f2c01 sago007 2017-03-15 17:56 1220
                    if (CEREAL_RAPIDJSON_UNLIKELY(i64 >= CEREAL_RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615
6c5f2c01 sago007 2017-03-15 17:56 1221
                        if (CEREAL_RAPIDJSON_LIKELY(i64 != CEREAL_RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {
6c5f2c01 sago007 2017-03-15 17:56 1222
                            d = static_cast<double>(i64);
6c5f2c01 sago007 2017-03-15 17:56 1223
                            useDouble = true;
6c5f2c01 sago007 2017-03-15 17:56 1224
                            break;
6c5f2c01 sago007 2017-03-15 17:56 1225
                        }
6c5f2c01 sago007 2017-03-15 17:56 1226
                    i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
6c5f2c01 sago007 2017-03-15 17:56 1227
                    significandDigit++;
6c5f2c01 sago007 2017-03-15 17:56 1228
                }
6c5f2c01 sago007 2017-03-15 17:56 1229
        }
6c5f2c01 sago007 2017-03-15 17:56 1230
6c5f2c01 sago007 2017-03-15 17:56 1231
        // Force double for big integer
6c5f2c01 sago007 2017-03-15 17:56 1232
        if (useDouble) {
6c5f2c01 sago007 2017-03-15 17:56 1233
            while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
6c5f2c01 sago007 2017-03-15 17:56 1234
                if (CEREAL_RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0
6c5f2c01 sago007 2017-03-15 17:56 1235
                    CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
6c5f2c01 sago007 2017-03-15 17:56 1236
                d = d * 10 + (s.TakePush() - '0');
6c5f2c01 sago007 2017-03-15 17:56 1237
            }
6c5f2c01 sago007 2017-03-15 17:56 1238
        }
6c5f2c01 sago007 2017-03-15 17:56 1239
6c5f2c01 sago007 2017-03-15 17:56 1240
        // Parse frac = decimal-point 1*DIGIT
6c5f2c01 sago007 2017-03-15 17:56 1241
        int expFrac = 0;
6c5f2c01 sago007 2017-03-15 17:56 1242
        size_t decimalPosition;
6c5f2c01 sago007 2017-03-15 17:56 1243
        if (Consume(s, '.')) {
6c5f2c01 sago007 2017-03-15 17:56 1244
            decimalPosition = s.Length();
6c5f2c01 sago007 2017-03-15 17:56 1245
6c5f2c01 sago007 2017-03-15 17:56 1246
            if (CEREAL_RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
6c5f2c01 sago007 2017-03-15 17:56 1247
                CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
6c5f2c01 sago007 2017-03-15 17:56 1248
6c5f2c01 sago007 2017-03-15 17:56 1249
            if (!useDouble) {
6c5f2c01 sago007 2017-03-15 17:56 1250
#if CEREAL_RAPIDJSON_64BIT
6c5f2c01 sago007 2017-03-15 17:56 1251
                // Use i64 to store significand in 64-bit architecture
6c5f2c01 sago007 2017-03-15 17:56 1252
                if (!use64bit)
6c5f2c01 sago007 2017-03-15 17:56 1253
                    i64 = i;
6c5f2c01 sago007 2017-03-15 17:56 1254
6c5f2c01 sago007 2017-03-15 17:56 1255
                while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
6c5f2c01 sago007 2017-03-15 17:56 1256
                    if (i64 > CEREAL_RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
6c5f2c01 sago007 2017-03-15 17:56 1257
                        break;
6c5f2c01 sago007 2017-03-15 17:56 1258
                    else {
6c5f2c01 sago007 2017-03-15 17:56 1259
                        i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
6c5f2c01 sago007 2017-03-15 17:56 1260
                        --expFrac;
6c5f2c01 sago007 2017-03-15 17:56 1261
                        if (i64 != 0)
6c5f2c01 sago007 2017-03-15 17:56 1262
                            significandDigit++;
6c5f2c01 sago007 2017-03-15 17:56 1263
                    }
6c5f2c01 sago007 2017-03-15 17:56 1264
                }
6c5f2c01 sago007 2017-03-15 17:56 1265
6c5f2c01 sago007 2017-03-15 17:56 1266
                d = static_cast<double>(i64);
7a956470 sago007 2016-02-14 17:09 1267
#else
6c5f2c01 sago007 2017-03-15 17:56 1268
                // Use double to store significand in 32-bit architecture
6c5f2c01 sago007 2017-03-15 17:56 1269
                d = static_cast<double>(use64bit ? i64 : i);
7a956470 sago007 2016-02-14 17:09 1270
#endif
6c5f2c01 sago007 2017-03-15 17:56 1271
                useDouble = true;
6c5f2c01 sago007 2017-03-15 17:56 1272
            }
6c5f2c01 sago007 2017-03-15 17:56 1273
6c5f2c01 sago007 2017-03-15 17:56 1274
            while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
6c5f2c01 sago007 2017-03-15 17:56 1275
                if (significandDigit < 17) {
6c5f2c01 sago007 2017-03-15 17:56 1276
                    d = d * 10.0 + (s.TakePush() - '0');
6c5f2c01 sago007 2017-03-15 17:56 1277
                    --expFrac;
6c5f2c01 sago007 2017-03-15 17:56 1278
                    if (CEREAL_RAPIDJSON_LIKELY(d > 0.0))
6c5f2c01 sago007 2017-03-15 17:56 1279
                        significandDigit++;
6c5f2c01 sago007 2017-03-15 17:56 1280
                }
6c5f2c01 sago007 2017-03-15 17:56 1281
                else
6c5f2c01 sago007 2017-03-15 17:56 1282
                    s.TakePush();
6c5f2c01 sago007 2017-03-15 17:56 1283
            }
6c5f2c01 sago007 2017-03-15 17:56 1284
        }
6c5f2c01 sago007 2017-03-15 17:56 1285
        else
6c5f2c01 sago007 2017-03-15 17:56 1286
            decimalPosition = s.Length(); // decimal position at the end of integer.
6c5f2c01 sago007 2017-03-15 17:56 1287
6c5f2c01 sago007 2017-03-15 17:56 1288
        // Parse exp = e [ minus / plus ] 1*DIGIT
6c5f2c01 sago007 2017-03-15 17:56 1289
        int exp = 0;
6c5f2c01 sago007 2017-03-15 17:56 1290
        if (Consume(s, 'e') || Consume(s, 'E')) {
6c5f2c01 sago007 2017-03-15 17:56 1291
            if (!useDouble) {
6c5f2c01 sago007 2017-03-15 17:56 1292
                d = static_cast<double>(use64bit ? i64 : i);
6c5f2c01 sago007 2017-03-15 17:56 1293
                useDouble = true;
6c5f2c01 sago007 2017-03-15 17:56 1294
            }
6c5f2c01 sago007 2017-03-15 17:56 1295
6c5f2c01 sago007 2017-03-15 17:56 1296
            bool expMinus = false;
6c5f2c01 sago007 2017-03-15 17:56 1297
            if (Consume(s, '+'))
6c5f2c01 sago007 2017-03-15 17:56 1298
                ;
6c5f2c01 sago007 2017-03-15 17:56 1299
            else if (Consume(s, '-'))
6c5f2c01 sago007 2017-03-15 17:56 1300
                expMinus = true;
6c5f2c01 sago007 2017-03-15 17:56 1301
6c5f2c01 sago007 2017-03-15 17:56 1302
            if (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
6c5f2c01 sago007 2017-03-15 17:56 1303
                exp = static_cast<int>(s.Take() - '0');
6c5f2c01 sago007 2017-03-15 17:56 1304
                if (expMinus) {
6c5f2c01 sago007 2017-03-15 17:56 1305
                    while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
6c5f2c01 sago007 2017-03-15 17:56 1306
                        exp = exp * 10 + static_cast<int>(s.Take() - '0');
6c5f2c01 sago007 2017-03-15 17:56 1307
                        if (exp >= 214748364) {                         // Issue #313: prevent overflow exponent
6c5f2c01 sago007 2017-03-15 17:56 1308
                            while (CEREAL_RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9'))  // Consume the rest of exponent
6c5f2c01 sago007 2017-03-15 17:56 1309
                                s.Take();
6c5f2c01 sago007 2017-03-15 17:56 1310
                        }
6c5f2c01 sago007 2017-03-15 17:56 1311
                    }
6c5f2c01 sago007 2017-03-15 17:56 1312
                }
6c5f2c01 sago007 2017-03-15 17:56 1313
                else {  // positive exp
6c5f2c01 sago007 2017-03-15 17:56 1314
                    int maxExp = 308 - expFrac;
6c5f2c01 sago007 2017-03-15 17:56 1315
                    while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
6c5f2c01 sago007 2017-03-15 17:56 1316
                        exp = exp * 10 + static_cast<int>(s.Take() - '0');
6c5f2c01 sago007 2017-03-15 17:56 1317
                        if (CEREAL_RAPIDJSON_UNLIKELY(exp > maxExp))
6c5f2c01 sago007 2017-03-15 17:56 1318
                            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
6c5f2c01 sago007 2017-03-15 17:56 1319
                    }
6c5f2c01 sago007 2017-03-15 17:56 1320
                }
6c5f2c01 sago007 2017-03-15 17:56 1321
            }
6c5f2c01 sago007 2017-03-15 17:56 1322
            else
6c5f2c01 sago007 2017-03-15 17:56 1323
                CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
6c5f2c01 sago007 2017-03-15 17:56 1324
6c5f2c01 sago007 2017-03-15 17:56 1325
            if (expMinus)
6c5f2c01 sago007 2017-03-15 17:56 1326
                exp = -exp;
6c5f2c01 sago007 2017-03-15 17:56 1327
        }
6c5f2c01 sago007 2017-03-15 17:56 1328
6c5f2c01 sago007 2017-03-15 17:56 1329
        // Finish parsing, call event according to the type of number.
6c5f2c01 sago007 2017-03-15 17:56 1330
        bool cont = true;
6c5f2c01 sago007 2017-03-15 17:56 1331
6c5f2c01 sago007 2017-03-15 17:56 1332
        if (parseFlags & kParseNumbersAsStringsFlag) {
6c5f2c01 sago007 2017-03-15 17:56 1333
            if (parseFlags & kParseInsituFlag) {
6c5f2c01 sago007 2017-03-15 17:56 1334
                s.Pop();  // Pop stack no matter if it will be used or not.
6c5f2c01 sago007 2017-03-15 17:56 1335
                typename InputStream::Ch* head = is.PutBegin();
6c5f2c01 sago007 2017-03-15 17:56 1336
                const size_t length = s.Tell() - startOffset;
6c5f2c01 sago007 2017-03-15 17:56 1337
                CEREAL_RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
6c5f2c01 sago007 2017-03-15 17:56 1338
                // unable to insert the \0 character here, it will erase the comma after this number
6c5f2c01 sago007 2017-03-15 17:56 1339
                const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
6c5f2c01 sago007 2017-03-15 17:56 1340
                cont = handler.RawNumber(str, SizeType(length), false);
6c5f2c01 sago007 2017-03-15 17:56 1341
            }
6c5f2c01 sago007 2017-03-15 17:56 1342
            else {
6c5f2c01 sago007 2017-03-15 17:56 1343
                SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
6c5f2c01 sago007 2017-03-15 17:56 1344
                StringStream srcStream(s.Pop());
6c5f2c01 sago007 2017-03-15 17:56 1345
                StackStream<typename TargetEncoding::Ch> dstStream(stack_);
6c5f2c01 sago007 2017-03-15 17:56 1346
                while (numCharsToCopy--) {
6c5f2c01 sago007 2017-03-15 17:56 1347
                    Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);
6c5f2c01 sago007 2017-03-15 17:56 1348
                }
6c5f2c01 sago007 2017-03-15 17:56 1349
                dstStream.Put('\0');
6c5f2c01 sago007 2017-03-15 17:56 1350
                const typename TargetEncoding::Ch* str = dstStream.Pop();
6c5f2c01 sago007 2017-03-15 17:56 1351
                const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;
6c5f2c01 sago007 2017-03-15 17:56 1352
                cont = handler.RawNumber(str, SizeType(length), true);
6c5f2c01 sago007 2017-03-15 17:56 1353
            }
6c5f2c01 sago007 2017-03-15 17:56 1354
        }
6c5f2c01 sago007 2017-03-15 17:56 1355
        else {
6c5f2c01 sago007 2017-03-15 17:56 1356
           size_t length = s.Length();
6c5f2c01 sago007 2017-03-15 17:56 1357
           const char* decimal = s.Pop();  // Pop stack no matter if it will be used or not.
6c5f2c01 sago007 2017-03-15 17:56 1358
6c5f2c01 sago007 2017-03-15 17:56 1359
           if (useDouble) {
6c5f2c01 sago007 2017-03-15 17:56 1360
               int p = exp + expFrac;
6c5f2c01 sago007 2017-03-15 17:56 1361
               if (parseFlags & kParseFullPrecisionFlag)
6c5f2c01 sago007 2017-03-15 17:56 1362
                   d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
6c5f2c01 sago007 2017-03-15 17:56 1363
               else
6c5f2c01 sago007 2017-03-15 17:56 1364
                   d = internal::StrtodNormalPrecision(d, p);
6c5f2c01 sago007 2017-03-15 17:56 1365
6c5f2c01 sago007 2017-03-15 17:56 1366
               cont = handler.Double(minus ? -d : d);
6c5f2c01 sago007 2017-03-15 17:56 1367
           }
6c5f2c01 sago007 2017-03-15 17:56 1368
           else if (useNanOrInf) {
6c5f2c01 sago007 2017-03-15 17:56 1369
               cont = handler.Double(d);
6c5f2c01 sago007 2017-03-15 17:56 1370
           }
6c5f2c01 sago007 2017-03-15 17:56 1371
           else {
6c5f2c01 sago007 2017-03-15 17:56 1372
               if (use64bit) {
6c5f2c01 sago007 2017-03-15 17:56 1373
                   if (minus)
6c5f2c01 sago007 2017-03-15 17:56 1374
                       cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
6c5f2c01 sago007 2017-03-15 17:56 1375
                   else
6c5f2c01 sago007 2017-03-15 17:56 1376
                       cont = handler.Uint64(i64);
6c5f2c01 sago007 2017-03-15 17:56 1377
               }
6c5f2c01 sago007 2017-03-15 17:56 1378
               else {
6c5f2c01 sago007 2017-03-15 17:56 1379
                   if (minus)
6c5f2c01 sago007 2017-03-15 17:56 1380
                       cont = handler.Int(static_cast<int32_t>(~i + 1));
6c5f2c01 sago007 2017-03-15 17:56 1381
                   else
6c5f2c01 sago007 2017-03-15 17:56 1382
                       cont = handler.Uint(i);
6c5f2c01 sago007 2017-03-15 17:56 1383
               }
6c5f2c01 sago007 2017-03-15 17:56 1384
           }
6c5f2c01 sago007 2017-03-15 17:56 1385
        }
6c5f2c01 sago007 2017-03-15 17:56 1386
        if (CEREAL_RAPIDJSON_UNLIKELY(!cont))
6c5f2c01 sago007 2017-03-15 17:56 1387
            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset);
6c5f2c01 sago007 2017-03-15 17:56 1388
    }
6c5f2c01 sago007 2017-03-15 17:56 1389
6c5f2c01 sago007 2017-03-15 17:56 1390
    // Parse any JSON value
6c5f2c01 sago007 2017-03-15 17:56 1391
    template<unsigned parseFlags, typename InputStream, typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 1392
    void ParseValue(InputStream& is, Handler& handler) {
6c5f2c01 sago007 2017-03-15 17:56 1393
        switch (is.Peek()) {
6c5f2c01 sago007 2017-03-15 17:56 1394
            case 'n': ParseNull  <parseFlags>(is, handler); break;
6c5f2c01 sago007 2017-03-15 17:56 1395
            case 't': ParseTrue  <parseFlags>(is, handler); break;
6c5f2c01 sago007 2017-03-15 17:56 1396
            case 'f': ParseFalse <parseFlags>(is, handler); break;
6c5f2c01 sago007 2017-03-15 17:56 1397
            case '"': ParseString<parseFlags>(is, handler); break;
6c5f2c01 sago007 2017-03-15 17:56 1398
            case '{': ParseObject<parseFlags>(is, handler); break;
6c5f2c01 sago007 2017-03-15 17:56 1399
            case '[': ParseArray <parseFlags>(is, handler); break;
6c5f2c01 sago007 2017-03-15 17:56 1400
            default :
6c5f2c01 sago007 2017-03-15 17:56 1401
                      ParseNumber<parseFlags>(is, handler);
6c5f2c01 sago007 2017-03-15 17:56 1402
                      break;
6c5f2c01 sago007 2017-03-15 17:56 1403
6c5f2c01 sago007 2017-03-15 17:56 1404
        }
6c5f2c01 sago007 2017-03-15 17:56 1405
    }
6c5f2c01 sago007 2017-03-15 17:56 1406
6c5f2c01 sago007 2017-03-15 17:56 1407
    // Iterative Parsing
6c5f2c01 sago007 2017-03-15 17:56 1408
6c5f2c01 sago007 2017-03-15 17:56 1409
    // States
6c5f2c01 sago007 2017-03-15 17:56 1410
    enum IterativeParsingState {
6c5f2c01 sago007 2017-03-15 17:56 1411
        IterativeParsingStartState = 0,
6c5f2c01 sago007 2017-03-15 17:56 1412
        IterativeParsingFinishState,
6c5f2c01 sago007 2017-03-15 17:56 1413
        IterativeParsingErrorState,
6c5f2c01 sago007 2017-03-15 17:56 1414
6c5f2c01 sago007 2017-03-15 17:56 1415
        // Object states
6c5f2c01 sago007 2017-03-15 17:56 1416
        IterativeParsingObjectInitialState,
6c5f2c01 sago007 2017-03-15 17:56 1417
        IterativeParsingMemberKeyState,
6c5f2c01 sago007 2017-03-15 17:56 1418
        IterativeParsingKeyValueDelimiterState,
6c5f2c01 sago007 2017-03-15 17:56 1419
        IterativeParsingMemberValueState,
6c5f2c01 sago007 2017-03-15 17:56 1420
        IterativeParsingMemberDelimiterState,
6c5f2c01 sago007 2017-03-15 17:56 1421
        IterativeParsingObjectFinishState,
6c5f2c01 sago007 2017-03-15 17:56 1422
6c5f2c01 sago007 2017-03-15 17:56 1423
        // Array states
6c5f2c01 sago007 2017-03-15 17:56 1424
        IterativeParsingArrayInitialState,
6c5f2c01 sago007 2017-03-15 17:56 1425
        IterativeParsingElementState,
6c5f2c01 sago007 2017-03-15 17:56 1426
        IterativeParsingElementDelimiterState,
6c5f2c01 sago007 2017-03-15 17:56 1427
        IterativeParsingArrayFinishState,
6c5f2c01 sago007 2017-03-15 17:56 1428
6c5f2c01 sago007 2017-03-15 17:56 1429
        // Single value state
6c5f2c01 sago007 2017-03-15 17:56 1430
        IterativeParsingValueState
6c5f2c01 sago007 2017-03-15 17:56 1431
    };
6c5f2c01 sago007 2017-03-15 17:56 1432
6c5f2c01 sago007 2017-03-15 17:56 1433
    enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 };
6c5f2c01 sago007 2017-03-15 17:56 1434
6c5f2c01 sago007 2017-03-15 17:56 1435
    // Tokens
6c5f2c01 sago007 2017-03-15 17:56 1436
    enum Token {
6c5f2c01 sago007 2017-03-15 17:56 1437
        LeftBracketToken = 0,
6c5f2c01 sago007 2017-03-15 17:56 1438
        RightBracketToken,
6c5f2c01 sago007 2017-03-15 17:56 1439
6c5f2c01 sago007 2017-03-15 17:56 1440
        LeftCurlyBracketToken,
6c5f2c01 sago007 2017-03-15 17:56 1441
        RightCurlyBracketToken,
6c5f2c01 sago007 2017-03-15 17:56 1442
6c5f2c01 sago007 2017-03-15 17:56 1443
        CommaToken,
6c5f2c01 sago007 2017-03-15 17:56 1444
        ColonToken,
6c5f2c01 sago007 2017-03-15 17:56 1445
6c5f2c01 sago007 2017-03-15 17:56 1446
        StringToken,
6c5f2c01 sago007 2017-03-15 17:56 1447
        FalseToken,
6c5f2c01 sago007 2017-03-15 17:56 1448
        TrueToken,
6c5f2c01 sago007 2017-03-15 17:56 1449
        NullToken,
6c5f2c01 sago007 2017-03-15 17:56 1450
        NumberToken,
6c5f2c01 sago007 2017-03-15 17:56 1451
6c5f2c01 sago007 2017-03-15 17:56 1452
        kTokenCount
6c5f2c01 sago007 2017-03-15 17:56 1453
    };
6c5f2c01 sago007 2017-03-15 17:56 1454
6c5f2c01 sago007 2017-03-15 17:56 1455
    CEREAL_RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
6c5f2c01 sago007 2017-03-15 17:56 1456
6c5f2c01 sago007 2017-03-15 17:56 1457
//!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN
6c5f2c01 sago007 2017-03-15 17:56 1458
#define N NumberToken
6c5f2c01 sago007 2017-03-15 17:56 1459
#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
6c5f2c01 sago007 2017-03-15 17:56 1460
        // Maps from ASCII to Token
6c5f2c01 sago007 2017-03-15 17:56 1461
        static const unsigned char tokenMap[256] = {
6c5f2c01 sago007 2017-03-15 17:56 1462
            N16, // 00~0F
6c5f2c01 sago007 2017-03-15 17:56 1463
            N16, // 10~1F
6c5f2c01 sago007 2017-03-15 17:56 1464
            N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
6c5f2c01 sago007 2017-03-15 17:56 1465
            N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
6c5f2c01 sago007 2017-03-15 17:56 1466
            N16, // 40~4F
6c5f2c01 sago007 2017-03-15 17:56 1467
            N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
6c5f2c01 sago007 2017-03-15 17:56 1468
            N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
6c5f2c01 sago007 2017-03-15 17:56 1469
            N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
6c5f2c01 sago007 2017-03-15 17:56 1470
            N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
6c5f2c01 sago007 2017-03-15 17:56 1471
        };
6c5f2c01 sago007 2017-03-15 17:56 1472
#undef N
6c5f2c01 sago007 2017-03-15 17:56 1473
#undef N16
6c5f2c01 sago007 2017-03-15 17:56 1474
//!@endcond
6c5f2c01 sago007 2017-03-15 17:56 1475
6c5f2c01 sago007 2017-03-15 17:56 1476
        if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
6c5f2c01 sago007 2017-03-15 17:56 1477
            return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
6c5f2c01 sago007 2017-03-15 17:56 1478
        else
6c5f2c01 sago007 2017-03-15 17:56 1479
            return NumberToken;
6c5f2c01 sago007 2017-03-15 17:56 1480
    }
6c5f2c01 sago007 2017-03-15 17:56 1481
6c5f2c01 sago007 2017-03-15 17:56 1482
    CEREAL_RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
6c5f2c01 sago007 2017-03-15 17:56 1483
        // current state x one lookahead token -> new state
6c5f2c01 sago007 2017-03-15 17:56 1484
        static const char G[cIterativeParsingStateCount][kTokenCount] = {
6c5f2c01 sago007 2017-03-15 17:56 1485
            // Start
6c5f2c01 sago007 2017-03-15 17:56 1486
            {
6c5f2c01 sago007 2017-03-15 17:56 1487
                IterativeParsingArrayInitialState,  // Left bracket
6c5f2c01 sago007 2017-03-15 17:56 1488
                IterativeParsingErrorState,         // Right bracket
6c5f2c01 sago007 2017-03-15 17:56 1489
                IterativeParsingObjectInitialState, // Left curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1490
                IterativeParsingErrorState,         // Right curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1491
                IterativeParsingErrorState,         // Comma
6c5f2c01 sago007 2017-03-15 17:56 1492
                IterativeParsingErrorState,         // Colon
6c5f2c01 sago007 2017-03-15 17:56 1493
                IterativeParsingValueState,         // String
6c5f2c01 sago007 2017-03-15 17:56 1494
                IterativeParsingValueState,         // False
6c5f2c01 sago007 2017-03-15 17:56 1495
                IterativeParsingValueState,         // True
6c5f2c01 sago007 2017-03-15 17:56 1496
                IterativeParsingValueState,         // Null
6c5f2c01 sago007 2017-03-15 17:56 1497
                IterativeParsingValueState          // Number
6c5f2c01 sago007 2017-03-15 17:56 1498
            },
6c5f2c01 sago007 2017-03-15 17:56 1499
            // Finish(sink state)
6c5f2c01 sago007 2017-03-15 17:56 1500
            {
6c5f2c01 sago007 2017-03-15 17:56 1501
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
6c5f2c01 sago007 2017-03-15 17:56 1502
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
6c5f2c01 sago007 2017-03-15 17:56 1503
                IterativeParsingErrorState
6c5f2c01 sago007 2017-03-15 17:56 1504
            },
6c5f2c01 sago007 2017-03-15 17:56 1505
            // Error(sink state)
6c5f2c01 sago007 2017-03-15 17:56 1506
            {
6c5f2c01 sago007 2017-03-15 17:56 1507
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
6c5f2c01 sago007 2017-03-15 17:56 1508
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
6c5f2c01 sago007 2017-03-15 17:56 1509
                IterativeParsingErrorState
6c5f2c01 sago007 2017-03-15 17:56 1510
            },
6c5f2c01 sago007 2017-03-15 17:56 1511
            // ObjectInitial
6c5f2c01 sago007 2017-03-15 17:56 1512
            {
6c5f2c01 sago007 2017-03-15 17:56 1513
                IterativeParsingErrorState,         // Left bracket
6c5f2c01 sago007 2017-03-15 17:56 1514
                IterativeParsingErrorState,         // Right bracket
6c5f2c01 sago007 2017-03-15 17:56 1515
                IterativeParsingErrorState,         // Left curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1516
                IterativeParsingObjectFinishState,  // Right curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1517
                IterativeParsingErrorState,         // Comma
6c5f2c01 sago007 2017-03-15 17:56 1518
                IterativeParsingErrorState,         // Colon
6c5f2c01 sago007 2017-03-15 17:56 1519
                IterativeParsingMemberKeyState,     // String
6c5f2c01 sago007 2017-03-15 17:56 1520
                IterativeParsingErrorState,         // False
6c5f2c01 sago007 2017-03-15 17:56 1521
                IterativeParsingErrorState,         // True
6c5f2c01 sago007 2017-03-15 17:56 1522
                IterativeParsingErrorState,         // Null
6c5f2c01 sago007 2017-03-15 17:56 1523
                IterativeParsingErrorState          // Number
6c5f2c01 sago007 2017-03-15 17:56 1524
            },
6c5f2c01 sago007 2017-03-15 17:56 1525
            // MemberKey
6c5f2c01 sago007 2017-03-15 17:56 1526
            {
6c5f2c01 sago007 2017-03-15 17:56 1527
                IterativeParsingErrorState,             // Left bracket
6c5f2c01 sago007 2017-03-15 17:56 1528
                IterativeParsingErrorState,             // Right bracket
6c5f2c01 sago007 2017-03-15 17:56 1529
                IterativeParsingErrorState,             // Left curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1530
                IterativeParsingErrorState,             // Right curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1531
                IterativeParsingErrorState,             // Comma
6c5f2c01 sago007 2017-03-15 17:56 1532
                IterativeParsingKeyValueDelimiterState, // Colon
6c5f2c01 sago007 2017-03-15 17:56 1533
                IterativeParsingErrorState,             // String
6c5f2c01 sago007 2017-03-15 17:56 1534
                IterativeParsingErrorState,             // False
6c5f2c01 sago007 2017-03-15 17:56 1535
                IterativeParsingErrorState,             // True
6c5f2c01 sago007 2017-03-15 17:56 1536
                IterativeParsingErrorState,             // Null
6c5f2c01 sago007 2017-03-15 17:56 1537
                IterativeParsingErrorState              // Number
6c5f2c01 sago007 2017-03-15 17:56 1538
            },
6c5f2c01 sago007 2017-03-15 17:56 1539
            // KeyValueDelimiter
6c5f2c01 sago007 2017-03-15 17:56 1540
            {
6c5f2c01 sago007 2017-03-15 17:56 1541
                IterativeParsingArrayInitialState,      // Left bracket(push MemberValue state)
6c5f2c01 sago007 2017-03-15 17:56 1542
                IterativeParsingErrorState,             // Right bracket
6c5f2c01 sago007 2017-03-15 17:56 1543
                IterativeParsingObjectInitialState,     // Left curly bracket(push MemberValue state)
6c5f2c01 sago007 2017-03-15 17:56 1544
                IterativeParsingErrorState,             // Right curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1545
                IterativeParsingErrorState,             // Comma
6c5f2c01 sago007 2017-03-15 17:56 1546
                IterativeParsingErrorState,             // Colon
6c5f2c01 sago007 2017-03-15 17:56 1547
                IterativeParsingMemberValueState,       // String
6c5f2c01 sago007 2017-03-15 17:56 1548
                IterativeParsingMemberValueState,       // False
6c5f2c01 sago007 2017-03-15 17:56 1549
                IterativeParsingMemberValueState,       // True
6c5f2c01 sago007 2017-03-15 17:56 1550
                IterativeParsingMemberValueState,       // Null
6c5f2c01 sago007 2017-03-15 17:56 1551
                IterativeParsingMemberValueState        // Number
6c5f2c01 sago007 2017-03-15 17:56 1552
            },
6c5f2c01 sago007 2017-03-15 17:56 1553
            // MemberValue
6c5f2c01 sago007 2017-03-15 17:56 1554
            {
6c5f2c01 sago007 2017-03-15 17:56 1555
                IterativeParsingErrorState,             // Left bracket
6c5f2c01 sago007 2017-03-15 17:56 1556
                IterativeParsingErrorState,             // Right bracket
6c5f2c01 sago007 2017-03-15 17:56 1557
                IterativeParsingErrorState,             // Left curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1558
                IterativeParsingObjectFinishState,      // Right curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1559
                IterativeParsingMemberDelimiterState,   // Comma
6c5f2c01 sago007 2017-03-15 17:56 1560
                IterativeParsingErrorState,             // Colon
6c5f2c01 sago007 2017-03-15 17:56 1561
                IterativeParsingErrorState,             // String
6c5f2c01 sago007 2017-03-15 17:56 1562
                IterativeParsingErrorState,             // False
6c5f2c01 sago007 2017-03-15 17:56 1563
                IterativeParsingErrorState,             // True
6c5f2c01 sago007 2017-03-15 17:56 1564
                IterativeParsingErrorState,             // Null
6c5f2c01 sago007 2017-03-15 17:56 1565
                IterativeParsingErrorState              // Number
6c5f2c01 sago007 2017-03-15 17:56 1566
            },
6c5f2c01 sago007 2017-03-15 17:56 1567
            // MemberDelimiter
6c5f2c01 sago007 2017-03-15 17:56 1568
            {
6c5f2c01 sago007 2017-03-15 17:56 1569
                IterativeParsingErrorState,         // Left bracket
6c5f2c01 sago007 2017-03-15 17:56 1570
                IterativeParsingErrorState,         // Right bracket
6c5f2c01 sago007 2017-03-15 17:56 1571
                IterativeParsingErrorState,         // Left curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1572
                IterativeParsingObjectFinishState,  // Right curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1573
                IterativeParsingErrorState,         // Comma
6c5f2c01 sago007 2017-03-15 17:56 1574
                IterativeParsingErrorState,         // Colon
6c5f2c01 sago007 2017-03-15 17:56 1575
                IterativeParsingMemberKeyState,     // String
6c5f2c01 sago007 2017-03-15 17:56 1576
                IterativeParsingErrorState,         // False
6c5f2c01 sago007 2017-03-15 17:56 1577
                IterativeParsingErrorState,         // True
6c5f2c01 sago007 2017-03-15 17:56 1578
                IterativeParsingErrorState,         // Null
6c5f2c01 sago007 2017-03-15 17:56 1579
                IterativeParsingErrorState          // Number
6c5f2c01 sago007 2017-03-15 17:56 1580
            },
6c5f2c01 sago007 2017-03-15 17:56 1581
            // ObjectFinish(sink state)
6c5f2c01 sago007 2017-03-15 17:56 1582
            {
6c5f2c01 sago007 2017-03-15 17:56 1583
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
6c5f2c01 sago007 2017-03-15 17:56 1584
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
6c5f2c01 sago007 2017-03-15 17:56 1585
                IterativeParsingErrorState
6c5f2c01 sago007 2017-03-15 17:56 1586
            },
6c5f2c01 sago007 2017-03-15 17:56 1587
            // ArrayInitial
6c5f2c01 sago007 2017-03-15 17:56 1588
            {
6c5f2c01 sago007 2017-03-15 17:56 1589
                IterativeParsingArrayInitialState,      // Left bracket(push Element state)
6c5f2c01 sago007 2017-03-15 17:56 1590
                IterativeParsingArrayFinishState,       // Right bracket
6c5f2c01 sago007 2017-03-15 17:56 1591
                IterativeParsingObjectInitialState,     // Left curly bracket(push Element state)
6c5f2c01 sago007 2017-03-15 17:56 1592
                IterativeParsingErrorState,             // Right curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1593
                IterativeParsingErrorState,             // Comma
6c5f2c01 sago007 2017-03-15 17:56 1594
                IterativeParsingErrorState,             // Colon
6c5f2c01 sago007 2017-03-15 17:56 1595
                IterativeParsingElementState,           // String
6c5f2c01 sago007 2017-03-15 17:56 1596
                IterativeParsingElementState,           // False
6c5f2c01 sago007 2017-03-15 17:56 1597
                IterativeParsingElementState,           // True
6c5f2c01 sago007 2017-03-15 17:56 1598
                IterativeParsingElementState,           // Null
6c5f2c01 sago007 2017-03-15 17:56 1599
                IterativeParsingElementState            // Number
6c5f2c01 sago007 2017-03-15 17:56 1600
            },
6c5f2c01 sago007 2017-03-15 17:56 1601
            // Element
6c5f2c01 sago007 2017-03-15 17:56 1602
            {
6c5f2c01 sago007 2017-03-15 17:56 1603
                IterativeParsingErrorState,             // Left bracket
6c5f2c01 sago007 2017-03-15 17:56 1604
                IterativeParsingArrayFinishState,       // Right bracket
6c5f2c01 sago007 2017-03-15 17:56 1605
                IterativeParsingErrorState,             // Left curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1606
                IterativeParsingErrorState,             // Right curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1607
                IterativeParsingElementDelimiterState,  // Comma
6c5f2c01 sago007 2017-03-15 17:56 1608
                IterativeParsingErrorState,             // Colon
6c5f2c01 sago007 2017-03-15 17:56 1609
                IterativeParsingErrorState,             // String
6c5f2c01 sago007 2017-03-15 17:56 1610
                IterativeParsingErrorState,             // False
6c5f2c01 sago007 2017-03-15 17:56 1611
                IterativeParsingErrorState,             // True
6c5f2c01 sago007 2017-03-15 17:56 1612
                IterativeParsingErrorState,             // Null
6c5f2c01 sago007 2017-03-15 17:56 1613
                IterativeParsingErrorState              // Number
6c5f2c01 sago007 2017-03-15 17:56 1614
            },
6c5f2c01 sago007 2017-03-15 17:56 1615
            // ElementDelimiter
6c5f2c01 sago007 2017-03-15 17:56 1616
            {
6c5f2c01 sago007 2017-03-15 17:56 1617
                IterativeParsingArrayInitialState,      // Left bracket(push Element state)
6c5f2c01 sago007 2017-03-15 17:56 1618
                IterativeParsingArrayFinishState,       // Right bracket
6c5f2c01 sago007 2017-03-15 17:56 1619
                IterativeParsingObjectInitialState,     // Left curly bracket(push Element state)
6c5f2c01 sago007 2017-03-15 17:56 1620
                IterativeParsingErrorState,             // Right curly bracket
6c5f2c01 sago007 2017-03-15 17:56 1621
                IterativeParsingErrorState,             // Comma
6c5f2c01 sago007 2017-03-15 17:56 1622
                IterativeParsingErrorState,             // Colon
6c5f2c01 sago007 2017-03-15 17:56 1623
                IterativeParsingElementState,           // String
6c5f2c01 sago007 2017-03-15 17:56 1624
                IterativeParsingElementState,           // False
6c5f2c01 sago007 2017-03-15 17:56 1625
                IterativeParsingElementState,           // True
6c5f2c01 sago007 2017-03-15 17:56 1626
                IterativeParsingElementState,           // Null
6c5f2c01 sago007 2017-03-15 17:56 1627
                IterativeParsingElementState            // Number
6c5f2c01 sago007 2017-03-15 17:56 1628
            },
6c5f2c01 sago007 2017-03-15 17:56 1629
            // ArrayFinish(sink state)
6c5f2c01 sago007 2017-03-15 17:56 1630
            {
6c5f2c01 sago007 2017-03-15 17:56 1631
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
6c5f2c01 sago007 2017-03-15 17:56 1632
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
6c5f2c01 sago007 2017-03-15 17:56 1633
                IterativeParsingErrorState
6c5f2c01 sago007 2017-03-15 17:56 1634
            },
6c5f2c01 sago007 2017-03-15 17:56 1635
            // Single Value (sink state)
6c5f2c01 sago007 2017-03-15 17:56 1636
            {
6c5f2c01 sago007 2017-03-15 17:56 1637
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
6c5f2c01 sago007 2017-03-15 17:56 1638
                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
6c5f2c01 sago007 2017-03-15 17:56 1639
                IterativeParsingErrorState
6c5f2c01 sago007 2017-03-15 17:56 1640
            }
6c5f2c01 sago007 2017-03-15 17:56 1641
        }; // End of G
6c5f2c01 sago007 2017-03-15 17:56 1642
6c5f2c01 sago007 2017-03-15 17:56 1643
        return static_cast<IterativeParsingState>(G[state][token]);
6c5f2c01 sago007 2017-03-15 17:56 1644
    }
6c5f2c01 sago007 2017-03-15 17:56 1645
6c5f2c01 sago007 2017-03-15 17:56 1646
    // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
6c5f2c01 sago007 2017-03-15 17:56 1647
    // May return a new state on state pop.
6c5f2c01 sago007 2017-03-15 17:56 1648
    template <unsigned parseFlags, typename InputStream, typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 1649
    CEREAL_RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
6c5f2c01 sago007 2017-03-15 17:56 1650
        (void)token;
6c5f2c01 sago007 2017-03-15 17:56 1651
6c5f2c01 sago007 2017-03-15 17:56 1652
        switch (dst) {
6c5f2c01 sago007 2017-03-15 17:56 1653
        case IterativeParsingErrorState:
6c5f2c01 sago007 2017-03-15 17:56 1654
            return dst;
6c5f2c01 sago007 2017-03-15 17:56 1655
6c5f2c01 sago007 2017-03-15 17:56 1656
        case IterativeParsingObjectInitialState:
6c5f2c01 sago007 2017-03-15 17:56 1657
        case IterativeParsingArrayInitialState:
6c5f2c01 sago007 2017-03-15 17:56 1658
        {
6c5f2c01 sago007 2017-03-15 17:56 1659
            // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
6c5f2c01 sago007 2017-03-15 17:56 1660
            // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
6c5f2c01 sago007 2017-03-15 17:56 1661
            IterativeParsingState n = src;
6c5f2c01 sago007 2017-03-15 17:56 1662
            if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
6c5f2c01 sago007 2017-03-15 17:56 1663
                n = IterativeParsingElementState;
6c5f2c01 sago007 2017-03-15 17:56 1664
            else if (src == IterativeParsingKeyValueDelimiterState)
6c5f2c01 sago007 2017-03-15 17:56 1665
                n = IterativeParsingMemberValueState;
6c5f2c01 sago007 2017-03-15 17:56 1666
            // Push current state.
6c5f2c01 sago007 2017-03-15 17:56 1667
            *stack_.template Push<SizeType>(1) = n;
6c5f2c01 sago007 2017-03-15 17:56 1668
            // Initialize and push the member/element count.
6c5f2c01 sago007 2017-03-15 17:56 1669
            *stack_.template Push<SizeType>(1) = 0;
6c5f2c01 sago007 2017-03-15 17:56 1670
            // Call handler
6c5f2c01 sago007 2017-03-15 17:56 1671
            bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
6c5f2c01 sago007 2017-03-15 17:56 1672
            // On handler short circuits the parsing.
6c5f2c01 sago007 2017-03-15 17:56 1673
            if (!hr) {
6c5f2c01 sago007 2017-03-15 17:56 1674
                CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 1675
                return IterativeParsingErrorState;
6c5f2c01 sago007 2017-03-15 17:56 1676
            }
6c5f2c01 sago007 2017-03-15 17:56 1677
            else {
6c5f2c01 sago007 2017-03-15 17:56 1678
                is.Take();
6c5f2c01 sago007 2017-03-15 17:56 1679
                return dst;
6c5f2c01 sago007 2017-03-15 17:56 1680
            }
6c5f2c01 sago007 2017-03-15 17:56 1681
        }
6c5f2c01 sago007 2017-03-15 17:56 1682
6c5f2c01 sago007 2017-03-15 17:56 1683
        case IterativeParsingMemberKeyState:
6c5f2c01 sago007 2017-03-15 17:56 1684
            ParseString<parseFlags>(is, handler, true);
6c5f2c01 sago007 2017-03-15 17:56 1685
            if (HasParseError())
6c5f2c01 sago007 2017-03-15 17:56 1686
                return IterativeParsingErrorState;
7a956470 sago007 2016-02-14 17:09 1687
            else
6c5f2c01 sago007 2017-03-15 17:56 1688
                return dst;
6c5f2c01 sago007 2017-03-15 17:56 1689
6c5f2c01 sago007 2017-03-15 17:56 1690
        case IterativeParsingKeyValueDelimiterState:
6c5f2c01 sago007 2017-03-15 17:56 1691
            CEREAL_RAPIDJSON_ASSERT(token == ColonToken);
6c5f2c01 sago007 2017-03-15 17:56 1692
            is.Take();
6c5f2c01 sago007 2017-03-15 17:56 1693
            return dst;
6c5f2c01 sago007 2017-03-15 17:56 1694
6c5f2c01 sago007 2017-03-15 17:56 1695
        case IterativeParsingMemberValueState:
6c5f2c01 sago007 2017-03-15 17:56 1696
            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
6c5f2c01 sago007 2017-03-15 17:56 1697
            ParseValue<parseFlags>(is, handler);
6c5f2c01 sago007 2017-03-15 17:56 1698
            if (HasParseError()) {
6c5f2c01 sago007 2017-03-15 17:56 1699
                return IterativeParsingErrorState;
6c5f2c01 sago007 2017-03-15 17:56 1700
            }
6c5f2c01 sago007 2017-03-15 17:56 1701
            return dst;
6c5f2c01 sago007 2017-03-15 17:56 1702
6c5f2c01 sago007 2017-03-15 17:56 1703
        case IterativeParsingElementState:
6c5f2c01 sago007 2017-03-15 17:56 1704
            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
6c5f2c01 sago007 2017-03-15 17:56 1705
            ParseValue<parseFlags>(is, handler);
6c5f2c01 sago007 2017-03-15 17:56 1706
            if (HasParseError()) {
6c5f2c01 sago007 2017-03-15 17:56 1707
                return IterativeParsingErrorState;
6c5f2c01 sago007 2017-03-15 17:56 1708
            }
6c5f2c01 sago007 2017-03-15 17:56 1709
            return dst;
6c5f2c01 sago007 2017-03-15 17:56 1710
6c5f2c01 sago007 2017-03-15 17:56 1711
        case IterativeParsingMemberDelimiterState:
6c5f2c01 sago007 2017-03-15 17:56 1712
        case IterativeParsingElementDelimiterState:
6c5f2c01 sago007 2017-03-15 17:56 1713
            is.Take();
6c5f2c01 sago007 2017-03-15 17:56 1714
            // Update member/element count.
6c5f2c01 sago007 2017-03-15 17:56 1715
            *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
6c5f2c01 sago007 2017-03-15 17:56 1716
            return dst;
6c5f2c01 sago007 2017-03-15 17:56 1717
6c5f2c01 sago007 2017-03-15 17:56 1718
        case IterativeParsingObjectFinishState:
6c5f2c01 sago007 2017-03-15 17:56 1719
        {
6c5f2c01 sago007 2017-03-15 17:56 1720
            // Transit from delimiter is only allowed when trailing commas are enabled
6c5f2c01 sago007 2017-03-15 17:56 1721
            if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {
6c5f2c01 sago007 2017-03-15 17:56 1722
                CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 1723
                return IterativeParsingErrorState;
6c5f2c01 sago007 2017-03-15 17:56 1724
            }
6c5f2c01 sago007 2017-03-15 17:56 1725
            // Get member count.
6c5f2c01 sago007 2017-03-15 17:56 1726
            SizeType c = *stack_.template Pop<SizeType>(1);
6c5f2c01 sago007 2017-03-15 17:56 1727
            // If the object is not empty, count the last member.
6c5f2c01 sago007 2017-03-15 17:56 1728
            if (src == IterativeParsingMemberValueState)
6c5f2c01 sago007 2017-03-15 17:56 1729
                ++c;
6c5f2c01 sago007 2017-03-15 17:56 1730
            // Restore the state.
6c5f2c01 sago007 2017-03-15 17:56 1731
            IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
6c5f2c01 sago007 2017-03-15 17:56 1732
            // Transit to Finish state if this is the topmost scope.
6c5f2c01 sago007 2017-03-15 17:56 1733
            if (n == IterativeParsingStartState)
6c5f2c01 sago007 2017-03-15 17:56 1734
                n = IterativeParsingFinishState;
6c5f2c01 sago007 2017-03-15 17:56 1735
            // Call handler
6c5f2c01 sago007 2017-03-15 17:56 1736
            bool hr = handler.EndObject(c);
6c5f2c01 sago007 2017-03-15 17:56 1737
            // On handler short circuits the parsing.
6c5f2c01 sago007 2017-03-15 17:56 1738
            if (!hr) {
6c5f2c01 sago007 2017-03-15 17:56 1739
                CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 1740
                return IterativeParsingErrorState;
6c5f2c01 sago007 2017-03-15 17:56 1741
            }
6c5f2c01 sago007 2017-03-15 17:56 1742
            else {
6c5f2c01 sago007 2017-03-15 17:56 1743
                is.Take();
6c5f2c01 sago007 2017-03-15 17:56 1744
                return n;
6c5f2c01 sago007 2017-03-15 17:56 1745
            }
6c5f2c01 sago007 2017-03-15 17:56 1746
        }
6c5f2c01 sago007 2017-03-15 17:56 1747
6c5f2c01 sago007 2017-03-15 17:56 1748
        case IterativeParsingArrayFinishState:
6c5f2c01 sago007 2017-03-15 17:56 1749
        {
6c5f2c01 sago007 2017-03-15 17:56 1750
            // Transit from delimiter is only allowed when trailing commas are enabled
6c5f2c01 sago007 2017-03-15 17:56 1751
            if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) {
6c5f2c01 sago007 2017-03-15 17:56 1752
                CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 1753
                return IterativeParsingErrorState;
6c5f2c01 sago007 2017-03-15 17:56 1754
            }
6c5f2c01 sago007 2017-03-15 17:56 1755
            // Get element count.
6c5f2c01 sago007 2017-03-15 17:56 1756
            SizeType c = *stack_.template Pop<SizeType>(1);
6c5f2c01 sago007 2017-03-15 17:56 1757
            // If the array is not empty, count the last element.
6c5f2c01 sago007 2017-03-15 17:56 1758
            if (src == IterativeParsingElementState)
6c5f2c01 sago007 2017-03-15 17:56 1759
                ++c;
6c5f2c01 sago007 2017-03-15 17:56 1760
            // Restore the state.
6c5f2c01 sago007 2017-03-15 17:56 1761
            IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
6c5f2c01 sago007 2017-03-15 17:56 1762
            // Transit to Finish state if this is the topmost scope.
6c5f2c01 sago007 2017-03-15 17:56 1763
            if (n == IterativeParsingStartState)
6c5f2c01 sago007 2017-03-15 17:56 1764
                n = IterativeParsingFinishState;
6c5f2c01 sago007 2017-03-15 17:56 1765
            // Call handler
6c5f2c01 sago007 2017-03-15 17:56 1766
            bool hr = handler.EndArray(c);
6c5f2c01 sago007 2017-03-15 17:56 1767
            // On handler short circuits the parsing.
6c5f2c01 sago007 2017-03-15 17:56 1768
            if (!hr) {
6c5f2c01 sago007 2017-03-15 17:56 1769
                CEREAL_RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
6c5f2c01 sago007 2017-03-15 17:56 1770
                return IterativeParsingErrorState;
6c5f2c01 sago007 2017-03-15 17:56 1771
            }
6c5f2c01 sago007 2017-03-15 17:56 1772
            else {
6c5f2c01 sago007 2017-03-15 17:56 1773
                is.Take();
6c5f2c01 sago007 2017-03-15 17:56 1774
                return n;
6c5f2c01 sago007 2017-03-15 17:56 1775
            }
6c5f2c01 sago007 2017-03-15 17:56 1776
        }
6c5f2c01 sago007 2017-03-15 17:56 1777
6c5f2c01 sago007 2017-03-15 17:56 1778
        default:
6c5f2c01 sago007 2017-03-15 17:56 1779
            // This branch is for IterativeParsingValueState actually.
6c5f2c01 sago007 2017-03-15 17:56 1780
            // Use `default:` rather than
6c5f2c01 sago007 2017-03-15 17:56 1781
            // `case IterativeParsingValueState:` is for code coverage.
6c5f2c01 sago007 2017-03-15 17:56 1782
6c5f2c01 sago007 2017-03-15 17:56 1783
            // The IterativeParsingStartState is not enumerated in this switch-case.
6c5f2c01 sago007 2017-03-15 17:56 1784
            // It is impossible for that case. And it can be caught by following assertion.
6c5f2c01 sago007 2017-03-15 17:56 1785
6c5f2c01 sago007 2017-03-15 17:56 1786
            // The IterativeParsingFinishState is not enumerated in this switch-case either.
6c5f2c01 sago007 2017-03-15 17:56 1787
            // It is a "derivative" state which cannot triggered from Predict() directly.
6c5f2c01 sago007 2017-03-15 17:56 1788
            // Therefore it cannot happen here. And it can be caught by following assertion.
6c5f2c01 sago007 2017-03-15 17:56 1789
            CEREAL_RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
6c5f2c01 sago007 2017-03-15 17:56 1790
6c5f2c01 sago007 2017-03-15 17:56 1791
            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
6c5f2c01 sago007 2017-03-15 17:56 1792
            ParseValue<parseFlags>(is, handler);
6c5f2c01 sago007 2017-03-15 17:56 1793
            if (HasParseError()) {
6c5f2c01 sago007 2017-03-15 17:56 1794
                return IterativeParsingErrorState;
6c5f2c01 sago007 2017-03-15 17:56 1795
            }
6c5f2c01 sago007 2017-03-15 17:56 1796
            return IterativeParsingFinishState;
6c5f2c01 sago007 2017-03-15 17:56 1797
        }
6c5f2c01 sago007 2017-03-15 17:56 1798
    }
6c5f2c01 sago007 2017-03-15 17:56 1799
6c5f2c01 sago007 2017-03-15 17:56 1800
    template <typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 1801
    void HandleError(IterativeParsingState src, InputStream& is) {
6c5f2c01 sago007 2017-03-15 17:56 1802
        if (HasParseError()) {
6c5f2c01 sago007 2017-03-15 17:56 1803
            // Error flag has been set.
6c5f2c01 sago007 2017-03-15 17:56 1804
            return;
6c5f2c01 sago007 2017-03-15 17:56 1805
        }
6c5f2c01 sago007 2017-03-15 17:56 1806
6c5f2c01 sago007 2017-03-15 17:56 1807
        switch (src) {
6c5f2c01 sago007 2017-03-15 17:56 1808
        case IterativeParsingStartState:            CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
6c5f2c01 sago007 2017-03-15 17:56 1809
        case IterativeParsingFinishState:           CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
6c5f2c01 sago007 2017-03-15 17:56 1810
        case IterativeParsingObjectInitialState:
6c5f2c01 sago007 2017-03-15 17:56 1811
        case IterativeParsingMemberDelimiterState:  CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return;
6c5f2c01 sago007 2017-03-15 17:56 1812
        case IterativeParsingMemberKeyState:        CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return;
6c5f2c01 sago007 2017-03-15 17:56 1813
        case IterativeParsingMemberValueState:      CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return;
6c5f2c01 sago007 2017-03-15 17:56 1814
        case IterativeParsingKeyValueDelimiterState:
6c5f2c01 sago007 2017-03-15 17:56 1815
        case IterativeParsingArrayInitialState:
6c5f2c01 sago007 2017-03-15 17:56 1816
        case IterativeParsingElementDelimiterState: CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;
6c5f2c01 sago007 2017-03-15 17:56 1817
        default: CEREAL_RAPIDJSON_ASSERT(src == IterativeParsingElementState); CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
6c5f2c01 sago007 2017-03-15 17:56 1818
        }
6c5f2c01 sago007 2017-03-15 17:56 1819
    }
6c5f2c01 sago007 2017-03-15 17:56 1820
6c5f2c01 sago007 2017-03-15 17:56 1821
    template <unsigned parseFlags, typename InputStream, typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 1822
    ParseResult IterativeParse(InputStream& is, Handler& handler) {
6c5f2c01 sago007 2017-03-15 17:56 1823
        parseResult_.Clear();
6c5f2c01 sago007 2017-03-15 17:56 1824
        ClearStackOnExit scope(*this);
6c5f2c01 sago007 2017-03-15 17:56 1825
        IterativeParsingState state = IterativeParsingStartState;
6c5f2c01 sago007 2017-03-15 17:56 1826
6c5f2c01 sago007 2017-03-15 17:56 1827
        SkipWhitespaceAndComments<parseFlags>(is);
6c5f2c01 sago007 2017-03-15 17:56 1828
        CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
6c5f2c01 sago007 2017-03-15 17:56 1829
        while (is.Peek() != '\0') {
6c5f2c01 sago007 2017-03-15 17:56 1830
            Token t = Tokenize(is.Peek());
6c5f2c01 sago007 2017-03-15 17:56 1831
            IterativeParsingState n = Predict(state, t);
6c5f2c01 sago007 2017-03-15 17:56 1832
            IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
6c5f2c01 sago007 2017-03-15 17:56 1833
6c5f2c01 sago007 2017-03-15 17:56 1834
            if (d == IterativeParsingErrorState) {
6c5f2c01 sago007 2017-03-15 17:56 1835
                HandleError(state, is);
6c5f2c01 sago007 2017-03-15 17:56 1836
                break;
6c5f2c01 sago007 2017-03-15 17:56 1837
            }
6c5f2c01 sago007 2017-03-15 17:56 1838
6c5f2c01 sago007 2017-03-15 17:56 1839
            state = d;
6c5f2c01 sago007 2017-03-15 17:56 1840
6c5f2c01 sago007 2017-03-15 17:56 1841
            // Do not further consume streams if a root JSON has been parsed.
6c5f2c01 sago007 2017-03-15 17:56 1842
            if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
6c5f2c01 sago007 2017-03-15 17:56 1843
                break;
6c5f2c01 sago007 2017-03-15 17:56 1844
6c5f2c01 sago007 2017-03-15 17:56 1845
            SkipWhitespaceAndComments<parseFlags>(is);
6c5f2c01 sago007 2017-03-15 17:56 1846
            CEREAL_RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
6c5f2c01 sago007 2017-03-15 17:56 1847
        }
6c5f2c01 sago007 2017-03-15 17:56 1848
6c5f2c01 sago007 2017-03-15 17:56 1849
        // Handle the end of file.
6c5f2c01 sago007 2017-03-15 17:56 1850
        if (state != IterativeParsingFinishState)
6c5f2c01 sago007 2017-03-15 17:56 1851
            HandleError(state, is);
6c5f2c01 sago007 2017-03-15 17:56 1852
6c5f2c01 sago007 2017-03-15 17:56 1853
        return parseResult_;
6c5f2c01 sago007 2017-03-15 17:56 1854
    }
6c5f2c01 sago007 2017-03-15 17:56 1855
6c5f2c01 sago007 2017-03-15 17:56 1856
    static const size_t kDefaultStackCapacity = 256;    //!< Default stack capacity in bytes for storing a single decoded string.
6c5f2c01 sago007 2017-03-15 17:56 1857
    internal::Stack<StackAllocator> stack_;  //!< A stack for storing decoded string temporarily during non-destructive parsing.
6c5f2c01 sago007 2017-03-15 17:56 1858
    ParseResult parseResult_;
7a956470 sago007 2016-02-14 17:09 1859
}; // class GenericReader
7a956470 sago007 2016-02-14 17:09 1860
7a956470 sago007 2016-02-14 17:09 1861
//! Reader with UTF8 encoding and default allocator.
6c5f2c01 sago007 2017-03-15 17:56 1862
typedef GenericReader<UTF8<>, UTF8<> > Reader;
7a956470 sago007 2016-02-14 17:09 1863
6c5f2c01 sago007 2017-03-15 17:56 1864
CEREAL_RAPIDJSON_NAMESPACE_END
6c5f2c01 sago007 2017-03-15 17:56 1865
6c5f2c01 sago007 2017-03-15 17:56 1866
#ifdef __clang__
6c5f2c01 sago007 2017-03-15 17:56 1867
CEREAL_RAPIDJSON_DIAG_POP
6c5f2c01 sago007 2017-03-15 17:56 1868
#endif
6c5f2c01 sago007 2017-03-15 17:56 1869
6c5f2c01 sago007 2017-03-15 17:56 1870
6c5f2c01 sago007 2017-03-15 17:56 1871
#ifdef __GNUC__
6c5f2c01 sago007 2017-03-15 17:56 1872
CEREAL_RAPIDJSON_DIAG_POP
6c5f2c01 sago007 2017-03-15 17:56 1873
#endif
7a956470 sago007 2016-02-14 17:09 1874
7a956470 sago007 2016-02-14 17:09 1875
#ifdef _MSC_VER
6c5f2c01 sago007 2017-03-15 17:56 1876
CEREAL_RAPIDJSON_DIAG_POP
7a956470 sago007 2016-02-14 17:09 1877
#endif
7a956470 sago007 2016-02-14 17:09 1878
6c5f2c01 sago007 2017-03-15 17:56 1879
#endif // CEREAL_RAPIDJSON_READER_H_
1970-01-01 00:00 1880