git repos / blockattack-game

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

normal view · raw

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