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