| 7a956470 |
sago007 |
2016-02-14 17:09 |
1 |
#ifndef RAPIDJSON_READER_H_ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
2 |
#define RAPIDJSON_READER_H_ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
3 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
4 |
// Copyright (c) 2011 Milo Yip (miloyip@gmail.com) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
5 |
// Version 0.1 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
6 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
7 |
#include "rapidjson.h" |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
8 |
#include "internal/pow10.h" |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
9 |
#include "internal/stack.h" |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
10 |
#include <csetjmp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
11 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
12 |
// All part of denormalized parsing |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
13 |
#include <limits> // for numeric_limits |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
14 |
#include <cmath> // for fpclassify |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
15 |
#include <sstream> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
16 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
17 |
#ifdef RAPIDJSON_SSE42 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
18 |
#include <nmmintrin.h> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
19 |
#elif defined(RAPIDJSON_SSE2) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
20 |
#include <emmintrin.h> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
21 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
22 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
23 |
#ifdef _MSC_VER |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
24 |
#pragma warning(push) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
25 |
#pragma warning(disable : 4127) // conditional expression is constant |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
26 |
#pragma warning(disable : 4702) // uncreachable code |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
27 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
28 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
29 |
#ifndef RAPIDJSON_PARSE_ERROR |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
30 |
#define RAPIDJSON_PARSE_ERROR(msg, offset) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
31 |
RAPIDJSON_MULTILINEMACRO_BEGIN \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
32 |
parseError_ = msg; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
33 |
errorOffset_ = offset; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
34 |
longjmp(jmpbuf_, 1); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
35 |
RAPIDJSON_MULTILINEMACRO_END |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
36 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
37 |
namespace rapidjson { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
38 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
39 |
/////////////////////////////////////////////////////////////////////////////// |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
40 |
// ParseFlag |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
41 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
42 |
//! Combination of parseFlags |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
43 |
enum ParseFlag { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
44 |
kParseDefaultFlags = 0, //!< Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
45 |
kParseInsituFlag = 1 //!< In-situ(destructive) parsing. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
46 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
47 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
48 |
/////////////////////////////////////////////////////////////////////////////// |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
49 |
// Handler |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
50 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
51 |
/*! \class rapidjson::Handler |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
52 |
\brief Concept for receiving events from GenericReader upon parsing. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
53 |
\code |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
54 |
concept Handler { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
55 |
typename Ch; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
56 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
57 |
void Null_(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
58 |
void Bool_(bool b); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
59 |
void Int(int i); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
60 |
void Uint(unsigned i); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
61 |
void Int64(int64_t i); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
62 |
void Uint64(uint64_t i); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
63 |
void Double(double d); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
64 |
void String(const Ch* str, SizeType length, bool copy); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
65 |
void StartObject(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
66 |
void EndObject(SizeType memberCount); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
67 |
void StartArray(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
68 |
void EndArray(SizeType elementCount); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
69 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
70 |
\endcode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
71 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
72 |
/////////////////////////////////////////////////////////////////////////////// |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
73 |
// BaseReaderHandler |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
74 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
75 |
//! Default implementation of Handler. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
76 |
/*! This can be used as base class of any reader handler. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
77 |
\implements Handler |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
78 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
79 |
template<typename Encoding = UTF8<> > |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
80 |
struct BaseReaderHandler { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
81 |
typedef typename Encoding::Ch Ch; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
82 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
83 |
void Default() {} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
84 |
void Null_() { Default(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
85 |
void Bool_(bool) { Default(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
86 |
void Int(int) { Default(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
87 |
void Uint(unsigned) { Default(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
88 |
void Int64(int64_t) { Default(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
89 |
void Uint64(uint64_t) { Default(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
90 |
void Double(double) { Default(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
91 |
void String(const Ch*, SizeType, bool) { Default(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
92 |
void StartObject() { Default(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
93 |
void EndObject(SizeType) { Default(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
94 |
void StartArray() { Default(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
95 |
void EndArray(SizeType) { Default(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
96 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
97 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
98 |
/////////////////////////////////////////////////////////////////////////////// |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
99 |
// SkipWhitespace |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
100 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
101 |
//! Skip the JSON white spaces in a stream. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
102 |
/*! \param stream A input stream for skipping white spaces. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
103 |
\note This function has SSE2/SSE4.2 specialization. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
104 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
105 |
template<typename Stream> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
106 |
void SkipWhitespace(Stream& stream) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
107 |
Stream s = stream; // Use a local copy for optimization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
108 |
while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
109 |
s.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
110 |
stream = s; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
111 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
112 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
113 |
#ifdef RAPIDJSON_SSE42 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
114 |
//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
115 |
inline const char *SkipWhitespace_SIMD(const char* p) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
116 |
static const char whitespace[16] = " \n\r\t"; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
117 |
__m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
118 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
119 |
for (;;) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
120 |
__m128i s = _mm_loadu_si128((const __m128i *)p); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
121 |
unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
122 |
if (r == 0) // all 16 characters are whitespace |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
123 |
p += 16; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
124 |
else { // some of characters may be non-whitespace |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
125 |
#ifdef _MSC_VER // Find the index of first non-whitespace |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
126 |
unsigned long offset; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
127 |
if (_BitScanForward(&offset, r)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
128 |
return p + offset; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
129 |
#else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
130 |
if (r != 0) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
131 |
return p + __builtin_ffs(r) - 1; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
132 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
133 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
134 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
135 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
136 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
137 |
#elif defined(RAPIDJSON_SSE2) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
138 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
139 |
//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
140 |
inline const char *SkipWhitespace_SIMD(const char* p) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
141 |
static const char whitespaces[4][17] = { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
142 |
" ", |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
143 |
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
144 |
"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
145 |
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
146 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
147 |
__m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
148 |
__m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
149 |
__m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
150 |
__m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
151 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
152 |
for (;;) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
153 |
__m128i s = _mm_loadu_si128((const __m128i *)p); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
154 |
__m128i x = _mm_cmpeq_epi8(s, w0); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
155 |
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
156 |
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
157 |
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
158 |
unsigned short r = ~_mm_movemask_epi8(x); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
159 |
if (r == 0) // all 16 characters are whitespace |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
160 |
p += 16; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
161 |
else { // some of characters may be non-whitespace |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
162 |
#ifdef _MSC_VER // Find the index of first non-whitespace |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
163 |
unsigned long offset; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
164 |
if (_BitScanForward(&offset, r)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
165 |
return p + offset; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
166 |
#else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
167 |
if (r != 0) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
168 |
return p + __builtin_ffs(r) - 1; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
169 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
170 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
171 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
172 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
173 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
174 |
#endif // RAPIDJSON_SSE2 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
175 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
176 |
#ifdef RAPIDJSON_SIMD |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
177 |
//! Template function specialization for InsituStringStream |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
178 |
template<> inline void SkipWhitespace(InsituStringStream& stream) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
179 |
stream.src_ = const_cast<char*>(SkipWhitespace_SIMD(stream.src_)); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
180 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
181 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
182 |
//! Template function specialization for StringStream |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
183 |
template<> inline void SkipWhitespace(StringStream& stream) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
184 |
stream.src_ = SkipWhitespace_SIMD(stream.src_); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
185 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
186 |
#endif // RAPIDJSON_SIMD |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
187 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
188 |
/////////////////////////////////////////////////////////////////////////////// |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
189 |
// GenericReader |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
190 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
191 |
//! SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
192 |
/*! GenericReader parses JSON text from a stream, and send events synchronously to an |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
193 |
object implementing Handler concept. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
194 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
195 |
It needs to allocate a stack for storing a single decoded string during |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
196 |
non-destructive parsing. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
197 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
198 |
For in-situ parsing, the decoded string is directly written to the source |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
199 |
text string, no temporary buffer is required. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
200 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
201 |
A GenericReader object can be reused for parsing multiple JSON text. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
202 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
203 |
\tparam Encoding Encoding of both the stream and the parse output. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
204 |
\tparam Allocator Allocator type for stack. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
205 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
206 |
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
207 |
class GenericReader { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
208 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
209 |
typedef typename Encoding::Ch Ch; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
210 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
211 |
//! Constructor. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
212 |
/*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
213 |
\param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
214 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
215 |
GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
216 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
217 |
//! Parse JSON text. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
218 |
/*! \tparam parseFlags Combination of ParseFlag. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
219 |
\tparam Stream Type of input stream. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
220 |
\tparam Handler Type of handler which must implement Handler concept. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
221 |
\param stream Input stream to be parsed. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
222 |
\param handler The handler to receive events. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
223 |
\return Whether the parsing is successful. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
224 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
225 |
template <unsigned parseFlags, typename Stream, typename Handler> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
226 |
bool Parse(Stream& stream, Handler& handler) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
227 |
parseError_ = 0; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
228 |
errorOffset_ = 0; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
229 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
230 |
#ifdef _MSC_VER |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
231 |
#pragma warning(push) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
232 |
#pragma warning(disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
233 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
234 |
if (setjmp(jmpbuf_)) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
235 |
#ifdef _MSC_VER |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
236 |
#pragma warning(pop) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
237 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
238 |
stack_.Clear(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
239 |
return false; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
240 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
241 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
242 |
SkipWhitespace(stream); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
243 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
244 |
if (stream.Peek() == '\0') |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
245 |
RAPIDJSON_PARSE_ERROR("Text only contains white space(s)", stream.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
246 |
else { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
247 |
switch (stream.Peek()) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
248 |
case '{': ParseObject<parseFlags>(stream, handler); break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
249 |
case '[': ParseArray<parseFlags>(stream, handler); break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
250 |
default: RAPIDJSON_PARSE_ERROR("Expect either an object or array at root", stream.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
251 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
252 |
SkipWhitespace(stream); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
253 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
254 |
if (stream.Peek() != '\0' && stream.Peek() != static_cast<Ch>(std::char_traits<Ch>::eof())) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
255 |
RAPIDJSON_PARSE_ERROR("Nothing should follow the root object or array.", stream.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
256 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
257 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
258 |
return true; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
259 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
260 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
261 |
bool HasParseError() const { return parseError_ != 0; } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
262 |
const char* GetParseError() const { return parseError_; } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
263 |
size_t GetErrorOffset() const { return errorOffset_; } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
264 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
265 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
266 |
// Parse object: { string : value, ... } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
267 |
template<unsigned parseFlags, typename Stream, typename Handler> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
268 |
void ParseObject(Stream& stream, Handler& handler) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
269 |
RAPIDJSON_ASSERT(stream.Peek() == '{'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
270 |
stream.Take(); // Skip '{' |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
271 |
handler.StartObject(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
272 |
SkipWhitespace(stream); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
273 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
274 |
if (stream.Peek() == '}') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
275 |
stream.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
276 |
handler.EndObject(0); // empty object |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
277 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
278 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
279 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
280 |
for (SizeType memberCount = 0;;) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
281 |
if (stream.Peek() != '"') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
282 |
RAPIDJSON_PARSE_ERROR("Name of an object member must be a string", stream.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
283 |
break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
284 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
285 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
286 |
ParseString<parseFlags>(stream, handler); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
287 |
SkipWhitespace(stream); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
288 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
289 |
if (stream.Take() != ':') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
290 |
RAPIDJSON_PARSE_ERROR("There must be a colon after the name of object member", stream.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
291 |
break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
292 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
293 |
SkipWhitespace(stream); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
294 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
295 |
ParseValue<parseFlags>(stream, handler); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
296 |
SkipWhitespace(stream); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
297 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
298 |
++memberCount; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
299 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
300 |
switch(stream.Take()) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
301 |
case ',': SkipWhitespace(stream); break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
302 |
case '}': handler.EndObject(memberCount); return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
303 |
default: RAPIDJSON_PARSE_ERROR("Must be a comma or '}' after an object member", stream.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
304 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
305 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
306 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
307 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
308 |
// Parse array: [ value, ... ] |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
309 |
template<unsigned parseFlags, typename Stream, typename Handler> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
310 |
void ParseArray(Stream& stream, Handler& handler) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
311 |
RAPIDJSON_ASSERT(stream.Peek() == '['); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
312 |
stream.Take(); // Skip '[' |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
313 |
handler.StartArray(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
314 |
SkipWhitespace(stream); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
315 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
316 |
if (stream.Peek() == ']') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
317 |
stream.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
318 |
handler.EndArray(0); // empty array |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
319 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
320 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
321 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
322 |
for (SizeType elementCount = 0;;) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
323 |
ParseValue<parseFlags>(stream, handler); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
324 |
++elementCount; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
325 |
SkipWhitespace(stream); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
326 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
327 |
switch (stream.Take()) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
328 |
case ',': SkipWhitespace(stream); break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
329 |
case ']': handler.EndArray(elementCount); return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
330 |
default: RAPIDJSON_PARSE_ERROR("Must be a comma or ']' after an array element.", stream.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
331 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
332 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
333 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
334 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
335 |
// Parses for null or NaN |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
336 |
template<unsigned parseFlags, typename Stream, typename Handler> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
337 |
void ParseNaNNull_(Stream& stream, Handler& handler) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
338 |
RAPIDJSON_ASSERT(stream.Peek() == 'n'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
339 |
stream.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
340 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
341 |
if( stream.Peek() == 'a' && stream.Take() == 'a' && stream.Take() == 'n' ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
342 |
handler.Double( std::numeric_limits<double>::quiet_NaN() ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
343 |
else if (stream.Take() == 'u' && stream.Take() == 'l' && stream.Take() == 'l') |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
344 |
handler.Null_(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
345 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
346 |
RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
347 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
348 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
349 |
// Parses for infinity |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
350 |
template<unsigned parseFlags, typename Stream, typename Handler> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
351 |
void ParseInfinity(Stream& stream, Handler& handler) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
352 |
RAPIDJSON_ASSERT(stream.Peek() == 'i'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
353 |
stream.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
354 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
355 |
if (stream.Take() == 'n' && stream.Take() == 'f') |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
356 |
handler.Double( std::numeric_limits<double>::infinity() ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
357 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
358 |
RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
359 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
360 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
361 |
template<unsigned parseFlags, typename Stream, typename Handler> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
362 |
void ParseTrue(Stream& stream, Handler& handler) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
363 |
RAPIDJSON_ASSERT(stream.Peek() == 't'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
364 |
stream.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
365 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
366 |
if (stream.Take() == 'r' && stream.Take() == 'u' && stream.Take() == 'e') |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
367 |
handler.Bool_(true); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
368 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
369 |
RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
370 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
371 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
372 |
template<unsigned parseFlags, typename Stream, typename Handler> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
373 |
void ParseFalse(Stream& stream, Handler& handler) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
374 |
RAPIDJSON_ASSERT(stream.Peek() == 'f'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
375 |
stream.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
376 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
377 |
if (stream.Take() == 'a' && stream.Take() == 'l' && stream.Take() == 's' && stream.Take() == 'e') |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
378 |
handler.Bool_(false); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
379 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
380 |
RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
381 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
382 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
383 |
// Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
384 |
template<typename Stream> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
385 |
unsigned ParseHex4(Stream& stream) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
386 |
Stream s = stream; // Use a local copy for optimization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
387 |
unsigned codepoint = 0; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
388 |
for (int i = 0; i < 4; i++) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
389 |
Ch c = s.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
390 |
codepoint <<= 4; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
391 |
codepoint += c; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
392 |
if (c >= '0' && c <= '9') |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
393 |
codepoint -= '0'; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
394 |
else if (c >= 'A' && c <= 'F') |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
395 |
codepoint -= 'A' - 10; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
396 |
else if (c >= 'a' && c <= 'f') |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
397 |
codepoint -= 'a' - 10; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
398 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
399 |
RAPIDJSON_PARSE_ERROR("Incorrect hex digit after \\u escape", s.Tell() - 1); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
400 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
401 |
stream = s; // Restore stream |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
402 |
return codepoint; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
403 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
404 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
405 |
// cereal Temporary until constexpr support is added in RTM |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
406 |
#ifdef _MSC_VER |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
407 |
template <class Ch> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
408 |
bool characterOk( Ch c ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
409 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
410 |
return c < 256; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
411 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
412 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
413 |
template <> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
414 |
bool characterOk<char>( char ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
415 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
416 |
return true; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
417 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
418 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
419 |
#else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
420 |
// As part of a fix for GCC 4.7 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
421 |
template <class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
422 |
static constexpr int to_int( T t ){ return t; } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
423 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
424 |
template<class Ch> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
425 |
typename std::enable_if < to_int(std::numeric_limits<Ch>::max()) < to_int(256), bool>::type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
426 |
characterOk( Ch ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
427 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
428 |
return true; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
429 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
430 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
431 |
template<class Ch> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
432 |
typename std::enable_if< to_int(std::numeric_limits<Ch>::max()) >= to_int(256), bool>::type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
433 |
characterOk(Ch c) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
434 |
{ return c < 256; } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
435 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
436 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
437 |
// Parse string, handling the prefix and suffix double quotes and escaping. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
438 |
template<unsigned parseFlags, typename Stream, typename Handler> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
439 |
void ParseString(Stream& stream, Handler& handler) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
440 |
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
441 |
static const Ch escape[256] = { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
442 |
Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
443 |
Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
444 |
0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
445 |
0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
446 |
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
447 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
448 |
#undef Z16 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
449 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
450 |
Stream s = stream; // Use a local copy for optimization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
451 |
RAPIDJSON_ASSERT(s.Peek() == '\"'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
452 |
s.Take(); // Skip '\"' |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
453 |
Ch *head; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
454 |
SizeType len; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
455 |
if (parseFlags & kParseInsituFlag) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
456 |
head = s.PutBegin(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
457 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
458 |
len = 0; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
459 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
460 |
#define RAPIDJSON_PUT(x) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
461 |
do { \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
462 |
if (parseFlags & kParseInsituFlag) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
463 |
s.Put(x); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
464 |
else { \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
465 |
*stack_.template Push<Ch>() = x; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
466 |
++len; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
467 |
} \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
468 |
} while(false) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
469 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
470 |
for (;;) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
471 |
Ch c = s.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
472 |
if (c == '\\') { // Escape |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
473 |
Ch e = s.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
474 |
if ((sizeof(Ch) == 1 || characterOk(e)) && escape[(unsigned char)e]) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
475 |
RAPIDJSON_PUT(escape[(unsigned char)e]); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
476 |
else if (e == 'u') { // Unicode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
477 |
unsigned codepoint = ParseHex4(s); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
478 |
if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { // Handle UTF-16 surrogate pair |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
479 |
if (s.Take() != '\\' || s.Take() != 'u') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
480 |
RAPIDJSON_PARSE_ERROR("Missing the second \\u in surrogate pair", s.Tell() - 2); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
481 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
482 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
483 |
unsigned codepoint2 = ParseHex4(s); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
484 |
if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
485 |
RAPIDJSON_PARSE_ERROR("The second \\u in surrogate pair is invalid", s.Tell() - 2); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
486 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
487 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
488 |
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
489 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
490 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
491 |
Ch buffer[4]; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
492 |
SizeType count = SizeType(Encoding::Encode(buffer, codepoint) - &buffer[0]); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
493 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
494 |
if (parseFlags & kParseInsituFlag) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
495 |
for (SizeType i = 0; i < count; i++) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
496 |
s.Put(buffer[i]); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
497 |
else { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
498 |
memcpy(stack_.template Push<Ch>(count), buffer, count * sizeof(Ch)); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
499 |
len += count; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
500 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
501 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
502 |
else { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
503 |
RAPIDJSON_PARSE_ERROR("Unknown escape character", stream.Tell() - 1); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
504 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
505 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
506 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
507 |
else if (c == '"') { // Closing double quote |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
508 |
if (parseFlags & kParseInsituFlag) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
509 |
size_t length = s.PutEnd(head); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
510 |
RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
511 |
RAPIDJSON_PUT('\0'); // null-terminate the string |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
512 |
handler.String(head, SizeType(length), false); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
513 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
514 |
else { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
515 |
RAPIDJSON_PUT('\0'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
516 |
handler.String(stack_.template Pop<Ch>(len), len - 1, true); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
517 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
518 |
stream = s; // restore stream |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
519 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
520 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
521 |
else if (c == '\0') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
522 |
RAPIDJSON_PARSE_ERROR("lacks ending quotation before the end of string", stream.Tell() - 1); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
523 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
524 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
525 |
else if ((unsigned)c < 0x20) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
526 |
RAPIDJSON_PARSE_ERROR("Incorrect unescaped character in string", stream.Tell() - 1); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
527 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
528 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
529 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
530 |
RAPIDJSON_PUT(c); // Normal character, just copy |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
531 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
532 |
#undef RAPIDJSON_PUT |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
533 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
534 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
535 |
template<unsigned parseFlags, typename Stream, typename Handler> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
536 |
void ParseNumber(Stream& stream, Handler& handler) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
537 |
Stream s = stream; // Local copy for optimization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
538 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
539 |
// Parse minus |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
540 |
bool minus = false; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
541 |
if (s.Peek() == '-') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
542 |
minus = true; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
543 |
s.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
544 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
545 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
546 |
// Parse int: zero / ( digit1-9 *DIGIT ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
547 |
unsigned i; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
548 |
bool try64bit = false; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
549 |
if (s.Peek() == '0') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
550 |
i = 0; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
551 |
s.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
552 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
553 |
else if (s.Peek() >= '1' && s.Peek() <= '9') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
554 |
i = s.Take() - '0'; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
555 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
556 |
if (minus) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
557 |
while (s.Peek() >= '0' && s.Peek() <= '9') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
558 |
if (i >= 214748364) { // 2^31 = 2147483648 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
559 |
if (i != 214748364 || s.Peek() > '8') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
560 |
try64bit = true; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
561 |
break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
562 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
563 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
564 |
i = i * 10 + (s.Take() - '0'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
565 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
566 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
567 |
while (s.Peek() >= '0' && s.Peek() <= '9') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
568 |
if (i >= 429496729) { // 2^32 - 1 = 4294967295 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
569 |
if (i != 429496729 || s.Peek() > '5') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
570 |
try64bit = true; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
571 |
break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
572 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
573 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
574 |
i = i * 10 + (s.Take() - '0'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
575 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
576 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
577 |
else { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
578 |
RAPIDJSON_PARSE_ERROR("Expect a value here.", stream.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
579 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
580 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
581 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
582 |
// Parse 64bit int |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
583 |
uint64_t i64 = 0; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
584 |
bool useDouble = false; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
585 |
if (try64bit) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
586 |
i64 = i; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
587 |
if (minus) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
588 |
while (s.Peek() >= '0' && s.Peek() <= '9') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
589 |
if (i64 >= 922337203685477580uLL) // 2^63 = 9223372036854775808 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
590 |
if (i64 != 922337203685477580uLL || s.Peek() > '8') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
591 |
useDouble = true; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
592 |
break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
593 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
594 |
i64 = i64 * 10 + (s.Take() - '0'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
595 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
596 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
597 |
while (s.Peek() >= '0' && s.Peek() <= '9') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
598 |
if (i64 >= 1844674407370955161uLL) // 2^64 - 1 = 18446744073709551615 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
599 |
if (i64 != 1844674407370955161uLL || s.Peek() > '5') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
600 |
useDouble = true; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
601 |
break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
602 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
603 |
i64 = i64 * 10 + (s.Take() - '0'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
604 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
605 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
606 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
607 |
// Force double for big integer |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
608 |
double d = 0.0; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
609 |
if (useDouble) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
610 |
d = (double)i64; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
611 |
while (s.Peek() >= '0' && s.Peek() <= '9') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
612 |
if (d >= 1E307) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
613 |
RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
614 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
615 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
616 |
d = d * 10 + (s.Take() - '0'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
617 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
618 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
619 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
620 |
// Parse frac = decimal-point 1*DIGIT |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
621 |
int expFrac = 0; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
622 |
if (s.Peek() == '.') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
623 |
if (!useDouble) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
624 |
d = try64bit ? (double)i64 : (double)i; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
625 |
useDouble = true; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
626 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
627 |
s.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
628 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
629 |
if (s.Peek() >= '0' && s.Peek() <= '9') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
630 |
d = d * 10 + (s.Take() - '0'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
631 |
--expFrac; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
632 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
633 |
else { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
634 |
RAPIDJSON_PARSE_ERROR("At least one digit in fraction part", stream.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
635 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
636 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
637 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
638 |
while (s.Peek() >= '0' && s.Peek() <= '9') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
639 |
if (expFrac > -20) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
640 |
d = d * 10 + (s.Peek() - '0'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
641 |
--expFrac; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
642 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
643 |
s.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
644 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
645 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
646 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
647 |
// Parse exp = e [ minus / plus ] 1*DIGIT |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
648 |
int exp = 0; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
649 |
if (s.Peek() == 'e' || s.Peek() == 'E') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
650 |
if (!useDouble) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
651 |
d = try64bit ? (double)i64 : (double)i; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
652 |
useDouble = true; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
653 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
654 |
s.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
655 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
656 |
bool expMinus = false; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
657 |
if (s.Peek() == '+') |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
658 |
s.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
659 |
else if (s.Peek() == '-') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
660 |
s.Take(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
661 |
expMinus = true; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
662 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
663 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
664 |
if (s.Peek() >= '0' && s.Peek() <= '9') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
665 |
exp = s.Take() - '0'; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
666 |
while (s.Peek() >= '0' && s.Peek() <= '9') { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
667 |
exp = exp * 10 + (s.Take() - '0'); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
668 |
if (exp > 308) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
669 |
// Attempt denormalized construction |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
670 |
std::stringstream ss; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
671 |
ss.precision( std::numeric_limits<double>::max_digits10 ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
672 |
ss << d * internal::Pow10(expFrac) << 'e' << (expMinus ? '-' : '+') << exp; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
673 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
674 |
double dd; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
675 |
ss >> dd; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
676 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
677 |
if( std::fpclassify( dd ) == FP_SUBNORMAL ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
678 |
handler.Double( dd ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
679 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
680 |
RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
681 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
682 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
683 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
684 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
685 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
686 |
else { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
687 |
RAPIDJSON_PARSE_ERROR("At least one digit in exponent", s.Tell()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
688 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
689 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
690 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
691 |
if (expMinus) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
692 |
exp = -exp; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
693 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
694 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
695 |
// Finish parsing, call event according to the type of number. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
696 |
if (useDouble) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
697 |
d *= internal::Pow10(exp + expFrac); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
698 |
handler.Double(minus ? -d : d); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
699 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
700 |
else { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
701 |
if (try64bit) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
702 |
if (minus) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
703 |
handler.Int64(-(int64_t)i64); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
704 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
705 |
handler.Uint64(i64); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
706 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
707 |
else { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
708 |
if (minus) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
709 |
handler.Int(-(int)i); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
710 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
711 |
handler.Uint(i); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
712 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
713 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
714 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
715 |
stream = s; // restore stream |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
716 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
717 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
718 |
// Parse any JSON value |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
719 |
template<unsigned parseFlags, typename Stream, typename Handler> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
720 |
void ParseValue(Stream& stream, Handler& handler) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
721 |
switch (stream.Peek()) { |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
722 |
case 'n': ParseNaNNull_ <parseFlags>(stream, handler); break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
723 |
case 'i': ParseInfinity <parseFlags>(stream, handler); break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
724 |
case 't': ParseTrue <parseFlags>(stream, handler); break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
725 |
case 'f': ParseFalse <parseFlags>(stream, handler); break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
726 |
case '"': ParseString <parseFlags>(stream, handler); break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
727 |
case '{': ParseObject <parseFlags>(stream, handler); break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
728 |
case '[': ParseArray <parseFlags>(stream, handler); break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
729 |
default : ParseNumber <parseFlags>(stream, handler); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
730 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
731 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
732 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
733 |
static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
734 |
internal::Stack<Allocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
735 |
jmp_buf jmpbuf_; //!< setjmp buffer for fast exit from nested parsing function calls. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
736 |
const char* parseError_; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
737 |
size_t errorOffset_; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
738 |
}; // class GenericReader |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
739 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
740 |
//! Reader with UTF8 encoding and default allocator. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
741 |
typedef GenericReader<UTF8<> > Reader; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
742 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
743 |
} // namespace rapidjson |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
744 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
745 |
#ifdef _MSC_VER |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
746 |
#pragma warning(pop) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
747 |
#endif |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
748 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
749 |
#endif // RAPIDJSON_READER_H_ |
|
|
1970-01-01 00:00 |
750 |
|