reader.h

Engine/source/persistence/rapidjson/reader.h

More...

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