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