DeepCover Embedded Security in IoT: Public-key Secured Data Paths

Dependencies:   MaximInterface

The MAXREFDES155# is an internet-of-things (IoT) embedded-security reference design, built to authenticate and control a sensing node using elliptic-curve-based public-key cryptography with control and notification from a web server.

The hardware includes an ARM® mbed™ shield and attached sensor endpoint. The shield contains a DS2476 DeepCover® ECDSA/SHA-2 coprocessor, Wifi communication, LCD push-button controls, and status LEDs. The sensor endpoint is attached to the shield using a 300mm cable and contains a DS28C36 DeepCover ECDSA/SHA-2 authenticator, IR-thermal sensor, and aiming laser for the IR sensor. The MAXREFDES155# is equipped with a standard Arduino® form-factor shield connector for immediate testing using an mbed board such as the MAX32600MBED#. The combination of these two devices represent an IoT device. Communication to the web server is accomplished with the shield Wifi circuitry. Communication from the shield to the attached sensor module is accomplished over I2C . The sensor module represents an IoT endpoint that generates small data with a requirement for message authenticity/integrity and secure on/off operational control.

The design is hierarchical with each mbed platform and shield communicating data from the sensor node to a web server that maintains a centralized log and dispatches notifications as necessary. The simplicity of this design enables rapid integration into any star-topology IoT network to provide security with the low overhead and cost provided by the ECDSA-P256 asymmetric-key and SHA-256 symmetric-key algorithms.

More information about the MAXREFDES155# is available on the Maxim Integrated website.

Committer:
IanBenzMaxim
Date:
Fri Jan 19 10:28:27 2018 -0600
Revision:
15:75404fab3615
Parent:
0:33d4e66780c0
Updated MaximInterface revision.

Who changed what in which revision?

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