reader.h
Go to the documentation of this file.
1 //Copyright (c) 2013-2023, The MercuryDPM Developers Team. All rights reserved.
2 //For the list of developers, see <http://www.MercuryDPM.org/Team>.
3 //
4 //Redistribution and use in source and binary forms, with or without
5 //modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name MercuryDPM nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 //WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 //DISCLAIMED. IN NO EVENT SHALL THE MERCURYDPM DEVELOPERS TEAM BE LIABLE FOR ANY
19 //DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 //(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 //ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 //(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 #ifndef RAPIDJSON_READER_H_
27 #define RAPIDJSON_READER_H_
28 
29 // Copyright (c) 2011-2023Milo Yip (miloyip@gmail.com)
30 // Version 0.1
31 
32 #include "rapidjson.h"
33 #include "internal/pow10.h"
34 #include "internal/stack.h"
35 #include <csetjmp>
36 
37 // All part of denormalized parsing
38 #include <limits> // for numeric_limits
39 #include <cmath> // for fpclassify
40 #include <sstream>
41 
42 #ifdef RAPIDJSON_SSE42
43 #include <nmmintrin.h>
44 #elif defined(RAPIDJSON_SSE2)
45 #include <emmintrin.h>
46 #endif
47 
48 #ifdef _MSC_VER
49 #pragma warning(push)
50 #pragma warning(disable : 4127) // conditional expression is constant
51 #endif
52 
53 #ifndef RAPIDJSON_PARSE_ERROR
54 #define RAPIDJSON_PARSE_ERROR(msg, offset) \
55  RAPIDJSON_MULTILINEMACRO_BEGIN \
56  parseError_ = msg; \
57  errorOffset_ = offset; \
58  longjmp(jmpbuf_, 1); \
59  RAPIDJSON_MULTILINEMACRO_END
60 #endif
61 namespace rapidjson {
62 
64 // ParseFlag
65 
67 enum ParseFlag {
69  kParseInsituFlag = 1
70 };
71 
73 // Handler
74 
97 // BaseReaderHandler
98 
100 
103 template<typename Encoding = UTF8<> >
105  typedef typename Encoding::Ch Ch;
106 
107  void Default() {}
108  void Null_() { Default(); }
109  void Bool_(bool) { Default(); }
110  void Int(int) { Default(); }
111  void Uint(unsigned) { Default(); }
112  void Int64(int64_t) { Default(); }
113  void Uint64(uint64_t) { Default(); }
114  void Double(double) { Default(); }
115  void String(const Ch*, SizeType, bool) { Default(); }
116  void StartObject() { Default(); }
118  void StartArray() { Default(); }
119  void EndArray(SizeType) { Default(); }
120 };
121 
123 // SkipWhitespace
124 
126 
129 template<typename Stream>
130 void SkipWhitespace(Stream& stream) {
131  Stream s = stream; // Use a local copy for optimization
132  while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
133  s.Take();
134  stream = s;
135 }
136 
137 #ifdef RAPIDJSON_SSE42
139 inline const char *SkipWhitespace_SIMD(const char* p) {
140  static const char whitespace[16] = " \n\r\t";
141  __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]);
142 
143  for (;;) {
144  __m128i s = _mm_loadu_si128((const __m128i *)p);
145  unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
146  if (r == 0) // all 16 characters are whitespace
147  p += 16;
148  else { // some of characters may be non-whitespace
149 #ifdef _MSC_VER // Find the index of first non-whitespace
150  unsigned long offset;
151  if (_BitScanForward(&offset, r))
152  return p + offset;
153 #else
154  if (r != 0)
155  return p + __builtin_ffs(r) - 1;
156 #endif
157  }
158  }
159 }
160 
161 #elif defined(RAPIDJSON_SSE2)
162 
164 inline const char *SkipWhitespace_SIMD(const char* p) {
165  static const char whitespaces[4][17] = {
166  " ",
167  "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
168  "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
169  "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
170 
171  __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]);
172  __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]);
173  __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]);
174  __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]);
175 
176  for (;;) {
177  __m128i s = _mm_loadu_si128((const __m128i *)p);
178  __m128i x = _mm_cmpeq_epi8(s, w0);
179  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
180  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
181  x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
182  unsigned short r = ~_mm_movemask_epi8(x);
183  if (r == 0) // all 16 characters are whitespace
184  p += 16;
185  else { // some of characters may be non-whitespace
186 #ifdef _MSC_VER // Find the index of first non-whitespace
187  unsigned long offset;
188  if (_BitScanForward(&offset, r))
189  return p + offset;
190 #else
191  if (r != 0)
192  return p + __builtin_ffs(r) - 1;
193 #endif
194  }
195  }
196 }
197 
198 #endif // RAPIDJSON_SSE2
199 
200 #ifdef RAPIDJSON_SIMD
202 template<> inline void SkipWhitespace(InsituStringStream& stream) {
203  stream.src_ = const_cast<char*>(SkipWhitespace_SIMD(stream.src_));
204 }
205 
207 template<> inline void SkipWhitespace(StringStream& stream) {
208  stream.src_ = SkipWhitespace_SIMD(stream.src_);
209 }
210 #endif // RAPIDJSON_SIMD
211 
213 // GenericReader
214 
216 
230 template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
232 public:
233  typedef typename Encoding::Ch Ch;
234 
236 
239  GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {}
240 
242 
249  template <unsigned parseFlags, typename Stream, typename Handler>
250  bool Parse(Stream& stream, Handler& handler) {
251  parseError_ = 0;
252  errorOffset_ = 0;
253 
254 #ifdef _MSC_VER
255 #pragma warning(push)
256 #pragma warning(disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
257 #endif
258  if (setjmp(jmpbuf_)) {
259 #ifdef _MSC_VER
260 #pragma warning(pop)
261 #endif
262  stack_.Clear();
263  return false;
264  }
265 
266  SkipWhitespace(stream);
267 
268  if (stream.Peek() == '\0')
269  RAPIDJSON_PARSE_ERROR("Text only contains white space(s)", stream.Tell());
270  else {
271  switch (stream.Peek()) {
272  case '{': ParseObject<parseFlags>(stream, handler); break;
273  case '[': ParseArray<parseFlags>(stream, handler); break;
274  default: RAPIDJSON_PARSE_ERROR("Expect either an object or array at root", stream.Tell());
275  }
276  SkipWhitespace(stream);
277 
278  if (stream.Peek() != '\0' && stream.Peek() != static_cast<Ch>(std::char_traits<Ch>::eof()))
279  RAPIDJSON_PARSE_ERROR("Nothing should follow the root object or array.", stream.Tell());
280  }
281 
282  return true;
283  }
284 
285  bool HasParseError() const { return parseError_ != 0; }
286  const char* GetParseError() const { return parseError_; }
287  size_t GetErrorOffset() const { return errorOffset_; }
288 
289 private:
290  // Parse object: { string : value, ... }
291  template<unsigned parseFlags, typename Stream, typename Handler>
292  void ParseObject(Stream& stream, Handler& handler) {
293  RAPIDJSON_ASSERT(stream.Peek() == '{');
294  stream.Take(); // Skip '{'
295  handler.StartObject();
296  SkipWhitespace(stream);
297 
298  if (stream.Peek() == '}') {
299  stream.Take();
300  handler.EndObject(0); // empty object
301  return;
302  }
303 
304  for (SizeType memberCount = 0;;) {
305  if (stream.Peek() != '"') {
306  RAPIDJSON_PARSE_ERROR("Name of an object member must be a string", stream.Tell());
307  break;
308  }
309 
310  ParseString<parseFlags>(stream, handler);
311  SkipWhitespace(stream);
312 
313  if (stream.Take() != ':') {
314  RAPIDJSON_PARSE_ERROR("There must be a colon after the name of object member", stream.Tell());
315  break;
316  }
317  SkipWhitespace(stream);
318 
319  ParseValue<parseFlags>(stream, handler);
320  SkipWhitespace(stream);
321 
322  ++memberCount;
323 
324  switch(stream.Take()) {
325  case ',': SkipWhitespace(stream); break;
326  case '}': handler.EndObject(memberCount); return;
327  default: RAPIDJSON_PARSE_ERROR("Must be a comma or '}' after an object member", stream.Tell());
328  }
329  }
330  }
331 
332  // Parse array: [ value, ... ]
333  template<unsigned parseFlags, typename Stream, typename Handler>
334  void ParseArray(Stream& stream, Handler& handler) {
335  RAPIDJSON_ASSERT(stream.Peek() == '[');
336  stream.Take(); // Skip '['
337  handler.StartArray();
338  SkipWhitespace(stream);
339 
340  if (stream.Peek() == ']') {
341  stream.Take();
342  handler.EndArray(0); // empty array
343  return;
344  }
345 
346  for (SizeType elementCount = 0;;) {
347  ParseValue<parseFlags>(stream, handler);
348  ++elementCount;
349  SkipWhitespace(stream);
350 
351  switch (stream.Take()) {
352  case ',': SkipWhitespace(stream); break;
353  case ']': handler.EndArray(elementCount); return;
354  default: RAPIDJSON_PARSE_ERROR("Must be a comma or ']' after an array element.", stream.Tell());
355  }
356  }
357  }
358 
359  // Parses for null or NaN
360  template<unsigned parseFlags, typename Stream, typename Handler>
361  void ParseNaNNull_(Stream& stream, Handler& handler) {
362  RAPIDJSON_ASSERT(stream.Peek() == 'n');
363  stream.Take();
364 
365  if( stream.Peek() == 'a' && stream.Take() == 'a' && stream.Take() == 'n' )
366  handler.Double( std::numeric_limits<double>::quiet_NaN() );
367  else if (stream.Take() == 'u' && stream.Take() == 'l' && stream.Take() == 'l')
368  handler.Null_();
369  else
370  RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1);
371  }
372 
373  // Parses for infinity
374  template<unsigned parseFlags, typename Stream, typename Handler>
375  void ParseInfinity(Stream& stream, Handler& handler) {
376  RAPIDJSON_ASSERT(stream.Peek() == 'i');
377  stream.Take();
378 
379  if (stream.Take() == 'n' && stream.Take() == 'f')
380  handler.Double( std::numeric_limits<double>::infinity() );
381  else
382  RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1);
383  }
384 
385  template<unsigned parseFlags, typename Stream, typename Handler>
386  void ParseTrue(Stream& stream, Handler& handler) {
387  RAPIDJSON_ASSERT(stream.Peek() == 't');
388  stream.Take();
389 
390  if (stream.Take() == 'r' && stream.Take() == 'u' && stream.Take() == 'e')
391  handler.Bool_(true);
392  else
393  RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell());
394  }
395 
396  template<unsigned parseFlags, typename Stream, typename Handler>
397  void ParseFalse(Stream& stream, Handler& handler) {
398  RAPIDJSON_ASSERT(stream.Peek() == 'f');
399  stream.Take();
400 
401  if (stream.Take() == 'a' && stream.Take() == 'l' && stream.Take() == 's' && stream.Take() == 'e')
402  handler.Bool_(false);
403  else
404  RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1);
405  }
406 
407  // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
408  template<typename Stream>
409  unsigned ParseHex4(Stream& stream) {
410  Stream s = stream; // Use a local copy for optimization
411  unsigned codepoint = 0;
412  for (int i = 0; i < 4; i++) {
413  Ch c = s.Take();
414  codepoint <<= 4;
415  codepoint += c;
416  if (c >= '0' && c <= '9')
417  codepoint -= '0';
418  else if (c >= 'A' && c <= 'F')
419  codepoint -= 'A' - 10;
420  else if (c >= 'a' && c <= 'f')
421  codepoint -= 'a' - 10;
422  else
423  RAPIDJSON_PARSE_ERROR("Incorrect hex digit after \\u escape", s.Tell() - 1);
424  }
425  stream = s; // Restore stream
426  return codepoint;
427  }
428 
429  // cereal Temporary until constexpr support is added in RTM
430 #ifdef _MSC_VER
431  template <class Ch>
432  bool characterOk( Ch c )
433  {
434  return c < 256;
435  }
436 
437  template <>
438  bool characterOk<char>( Ch )
439  {
440  return true;
441  }
442 
443 #else
444  // As part of a fix for GCC 4.7
445  template <class T>
446  static constexpr int to_int( T t ){ return t; }
447 
448  template<class Ch>
449  typename std::enable_if < to_int(std::numeric_limits<Ch>::max()) < to_int(256), bool>::type
450  characterOk( Ch )
451  {
452  return true;
453  }
454 
455  template<class Ch>
456  typename std::enable_if< to_int(std::numeric_limits<Ch>::max()) >= to_int(256), bool>::type
458  { return c < 256; }
459 #endif
460 
461  // Parse string, handling the prefix and suffix double quotes and escaping.
462  template<unsigned parseFlags, typename Stream, typename Handler>
463  void ParseString(Stream& stream, Handler& handler) {
464 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
465  static const Ch escape[256] = {
466  Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
467  Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
468  0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
469  0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
470  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
471  };
472 #undef Z16
473 
474  Stream s = stream; // Use a local copy for optimization
475  RAPIDJSON_ASSERT(s.Peek() == '\"');
476  s.Take(); // Skip '\"'
477  Ch *head;
478  SizeType len;
479  if (parseFlags & kParseInsituFlag)
480  head = s.PutBegin();
481  else
482  len = 0;
483 
484 #define RAPIDJSON_PUT(x) \
485  do { \
486  if (parseFlags & kParseInsituFlag) \
487  s.Put(x); \
488  else { \
489  *stack_.template Push<Ch>() = x; \
490  ++len; \
491  } \
492  } while(false)
493 
494  for (;;) {
495  Ch c = s.Take();
496  if (c == '\\') { // Escape
497  Ch e = s.Take();
498  if ((sizeof(Ch) == 1 || characterOk(e)) && escape[(unsigned char)e])
499  RAPIDJSON_PUT(escape[(unsigned char)e]);
500  else if (e == 'u') { // Unicode
501  unsigned codepoint = ParseHex4(s);
502  if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { // Handle UTF-16 surrogate pair
503  if (s.Take() != '\\' || s.Take() != 'u') {
504  RAPIDJSON_PARSE_ERROR("Missing the second \\u in surrogate pair", s.Tell() - 2);
505  return;
506  }
507  unsigned codepoint2 = ParseHex4(s);
508  if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) {
509  RAPIDJSON_PARSE_ERROR("The second \\u in surrogate pair is invalid", s.Tell() - 2);
510  return;
511  }
512  codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
513  }
514 
515  Ch buffer[4];
516  SizeType count = SizeType(Encoding::Encode(buffer, codepoint) - &buffer[0]);
517 
518  if (parseFlags & kParseInsituFlag)
519  for (SizeType i = 0; i < count; i++)
520  s.Put(buffer[i]);
521  else {
522  memcpy(stack_.template Push<Ch>(count), buffer, count * sizeof(Ch));
523  len += count;
524  }
525  }
526  else {
527  RAPIDJSON_PARSE_ERROR("Unknown escape character", stream.Tell() - 1);
528  return;
529  }
530  }
531  else if (c == '"') { // Closing double quote
532  if (parseFlags & kParseInsituFlag) {
533  size_t length = s.PutEnd(head);
534  RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
535  RAPIDJSON_PUT('\0'); // null-terminate the string
536  handler.String(head, SizeType(length), false);
537  }
538  else {
539  RAPIDJSON_PUT('\0');
540  handler.String(stack_.template Pop<Ch>(len), len - 1, true);
541  }
542  stream = s; // restore stream
543  return;
544  }
545  else if (c == '\0') {
546  RAPIDJSON_PARSE_ERROR("lacks ending quotation before the end of string", stream.Tell() - 1);
547  return;
548  }
549  else if ((unsigned)c < 0x20) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
550  RAPIDJSON_PARSE_ERROR("Incorrect unescaped character in string", stream.Tell() - 1);
551  return;
552  }
553  else
554  RAPIDJSON_PUT(c); // Normal character, just copy
555  }
556 #undef RAPIDJSON_PUT
557  }
558 
559  template<unsigned parseFlags, typename Stream, typename Handler>
560  void ParseNumber(Stream& stream, Handler& handler) {
561  Stream s = stream; // Local copy for optimization
562 
563  // Parse minus
564  bool minus = false;
565  if (s.Peek() == '-') {
566  minus = true;
567  s.Take();
568  }
569 
570  // Parse int: zero / ( digit1-9 *DIGIT )
571  unsigned i;
572  bool try64bit = false;
573  if (s.Peek() == '0') {
574  i = 0;
575  s.Take();
576  }
577  else if (s.Peek() >= '1' && s.Peek() <= '9') {
578  i = s.Take() - '0';
579 
580  if (minus)
581  while (s.Peek() >= '0' && s.Peek() <= '9') {
582  if (i >= 214748364) { // 2^31 = 2147483648
583  if (i != 214748364 || s.Peek() > '8') {
584  try64bit = true;
585  break;
586  }
587  }
588  i = i * 10 + (s.Take() - '0');
589  }
590  else
591  while (s.Peek() >= '0' && s.Peek() <= '9') {
592  if (i >= 429496729) { // 2^32 - 1 = 4294967295
593  if (i != 429496729 || s.Peek() > '5') {
594  try64bit = true;
595  break;
596  }
597  }
598  i = i * 10 + (s.Take() - '0');
599  }
600  }
601  else {
602  RAPIDJSON_PARSE_ERROR("Expect a value here.", stream.Tell());
603  return;
604  }
605 
606  // Parse 64bit int
607  uint64_t i64 = 0;
608  bool useDouble = false;
609  if (try64bit) {
610  i64 = i;
611  if (minus)
612  while (s.Peek() >= '0' && s.Peek() <= '9') {
613  if (i64 >= 922337203685477580uLL) // 2^63 = 9223372036854775808
614  if (i64 != 922337203685477580uLL || s.Peek() > '8') {
615  useDouble = true;
616  break;
617  }
618  i64 = i64 * 10 + (s.Take() - '0');
619  }
620  else
621  while (s.Peek() >= '0' && s.Peek() <= '9') {
622  if (i64 >= 1844674407370955161uLL) // 2^64 - 1 = 18446744073709551615
623  if (i64 != 1844674407370955161uLL || s.Peek() > '5') {
624  useDouble = true;
625  break;
626  }
627  i64 = i64 * 10 + (s.Take() - '0');
628  }
629  }
630 
631  // Force double for big integer
632  double d = 0.0;
633  if (useDouble) {
634  d = (double)i64;
635  while (s.Peek() >= '0' && s.Peek() <= '9') {
636  if (d >= 1E307) {
637  RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell());
638  return;
639  }
640  d = d * 10 + (s.Take() - '0');
641  }
642  }
643 
644  // Parse frac = decimal-point 1*DIGIT
645  int expFrac = 0;
646  if (s.Peek() == '.') {
647  if (!useDouble) {
648  d = try64bit ? (double)i64 : (double)i;
649  useDouble = true;
650  }
651  s.Take();
652 
653  if (s.Peek() >= '0' && s.Peek() <= '9') {
654  d = d * 10 + (s.Take() - '0');
655  --expFrac;
656  }
657  else {
658  RAPIDJSON_PARSE_ERROR("At least one digit in fraction part", stream.Tell());
659  return;
660  }
661 
662  while (s.Peek() >= '0' && s.Peek() <= '9') {
663  if (expFrac > -20) {
664  d = d * 10 + (s.Peek() - '0');
665  --expFrac;
666  }
667  s.Take();
668  }
669  }
670 
671  // Parse exp = e [ minus / plus ] 1*DIGIT
672  int exp = 0;
673  if (s.Peek() == 'e' || s.Peek() == 'E') {
674  if (!useDouble) {
675  d = try64bit ? (double)i64 : (double)i;
676  useDouble = true;
677  }
678  s.Take();
679 
680  bool expMinus = false;
681  if (s.Peek() == '+')
682  s.Take();
683  else if (s.Peek() == '-') {
684  s.Take();
685  expMinus = true;
686  }
687 
688  if (s.Peek() >= '0' && s.Peek() <= '9') {
689  exp = s.Take() - '0';
690  while (s.Peek() >= '0' && s.Peek() <= '9') {
691  exp = exp * 10 + (s.Take() - '0');
692  if (exp > 308) {
693  // Attempt denormalized construction
694  std::stringstream ss;
695  ss.precision( std::numeric_limits<double>::max_digits10 );
696  ss << d * internal::Pow10(expFrac) << 'e' << (expMinus ? '-' : '+') << exp;
697 
698  double dd;
699  ss >> dd;
700 
701  if( std::fpclassify( dd ) == FP_SUBNORMAL )
702  handler.Double( dd );
703  else
704  RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell());
705 
706  return;
707  }
708  }
709  }
710  else {
711  RAPIDJSON_PARSE_ERROR("At least one digit in exponent", s.Tell());
712  return;
713  }
714 
715  if (expMinus)
716  exp = -exp;
717  }
718 
719  // Finish parsing, call event according to the type of number.
720  if (useDouble) {
721  d *= internal::Pow10(exp + expFrac);
722  handler.Double(minus ? -d : d);
723  }
724  else {
725  if (try64bit) {
726  if (minus)
727  handler.Int64(-(int64_t)i64);
728  else
729  handler.Uint64(i64);
730  }
731  else {
732  if (minus)
733  handler.Int(-(int)i);
734  else
735  handler.Uint(i);
736  }
737  }
738 
739  stream = s; // restore stream
740  }
741 
742  // Parse any JSON value
743  template<unsigned parseFlags, typename Stream, typename Handler>
744  void ParseValue(Stream& stream, Handler& handler) {
745  switch (stream.Peek()) {
746  case 'n': ParseNaNNull_ <parseFlags>(stream, handler); break;
747  case 'i': ParseInfinity <parseFlags>(stream, handler); break;
748  case 't': ParseTrue <parseFlags>(stream, handler); break;
749  case 'f': ParseFalse <parseFlags>(stream, handler); break;
750  case '"': ParseString <parseFlags>(stream, handler); break;
751  case '{': ParseObject <parseFlags>(stream, handler); break;
752  case '[': ParseArray <parseFlags>(stream, handler); break;
753  default : ParseNumber <parseFlags>(stream, handler);
754  }
755  }
756 
757  static const size_t kDefaultStackCapacity = 256;
759  jmp_buf jmpbuf_;
760  const char* parseError_;
761  size_t errorOffset_;
762 }; // class GenericReader
763 
766 
767 } // namespace rapidjson
768 
769 #ifdef _MSC_VER
770 #pragma warning(pop)
771 #endif
772 
773 #endif // RAPIDJSON_READER_H_
Concept for allocating, resizing and freeing memory block.
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
Definition: reader.h:231
void ParseValue(Stream &stream, Handler &handler)
Definition: reader.h:744
void ParseObject(Stream &stream, Handler &handler)
Definition: reader.h:292
void ParseNumber(Stream &stream, Handler &handler)
Definition: reader.h:560
jmp_buf jmpbuf_
setjmp buffer for fast exit from nested parsing function calls.
Definition: reader.h:759
void ParseInfinity(Stream &stream, Handler &handler)
Definition: reader.h:375
bool Parse(Stream &stream, Handler &handler)
Parse JSON text.
Definition: reader.h:250
unsigned ParseHex4(Stream &stream)
Definition: reader.h:409
internal::Stack< Allocator > stack_
A stack for storing decoded string temporarily during non-destructive parsing.
Definition: reader.h:758
void ParseArray(Stream &stream, Handler &handler)
Definition: reader.h:334
Encoding::Ch Ch
Definition: reader.h:233
const char * parseError_
Definition: reader.h:760
void ParseString(Stream &stream, Handler &handler)
Definition: reader.h:463
void ParseTrue(Stream &stream, Handler &handler)
Definition: reader.h:386
void ParseNaNNull_(Stream &stream, Handler &handler)
Definition: reader.h:361
const char * GetParseError() const
Definition: reader.h:286
std::enable_if< to_int(std::numeric_limits< Ch >::max())< to_int(256), bool >::type characterOk(Ch) { return true;} template< class Ch > typename std::enable_if< to_int(std::numeric_limits< Ch >::max()) >=to_int(256), bool >::type characterOk(Ch c)
Definition: reader.h:457
static constexpr int to_int(T t)
Definition: reader.h:446
size_t errorOffset_
Definition: reader.h:761
void ParseFalse(Stream &stream, Handler &handler)
Definition: reader.h:397
GenericReader(Allocator *allocator=0, size_t stackCapacity=kDefaultStackCapacity)
Constructor.
Definition: reader.h:239
bool HasParseError() const
Definition: reader.h:285
static const size_t kDefaultStackCapacity
Default stack capacity in bytes for storing a single decoded string.
Definition: reader.h:757
size_t GetErrorOffset() const
Definition: reader.h:287
Concept for receiving events from GenericReader upon parsing.
Concept for reading and writing characters.
A type-unsafe stack for storing different types of data.
Definition: stack.h:39
const std::complex< Mdouble > i
Definition: ExtendedMath.h:51
Mdouble exp(Mdouble Exponent)
Definition: ExtendedMath.cc:84
double Pow10(int n)
Computes integer powers of 10 in double (10.0^n).
Definition: pow10.h:37
Definition: document.h:38
unsigned SizeType
Use 32-bit array/string indices even for 64-bit platform, instead of using size_t.
Definition: rapidjson.h:92
GenericInsituStringStream< UTF8<> > InsituStringStream
Definition: rapidjson.h:532
void SkipWhitespace(Stream &stream)
Skip the JSON white spaces in a stream.
Definition: reader.h:130
GenericReader< UTF8<> > Reader
Reader with UTF8 encoding and default allocator.
Definition: reader.h:765
ParseFlag
Combination of parseFlags.
Definition: reader.h:67
@ kParseInsituFlag
In-situ(destructive) parsing.
Definition: reader.h:69
@ kParseDefaultFlags
Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer.
Definition: reader.h:68
GenericStringStream< UTF8<> > StringStream
Definition: rapidjson.h:502
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:105
#define RAPIDJSON_PUT(x)
#define RAPIDJSON_PARSE_ERROR(msg, offset)
Definition: reader.h:54
#define Z16
Default implementation of Handler.
Definition: reader.h:104
void Default()
Definition: reader.h:107
void Int(int)
Definition: reader.h:110
void StartObject()
Definition: reader.h:116
void Null_()
Definition: reader.h:108
void Bool_(bool)
Definition: reader.h:109
void EndObject(SizeType)
Definition: reader.h:117
void StartArray()
Definition: reader.h:118
void Double(double)
Definition: reader.h:114
void Uint(unsigned)
Definition: reader.h:111
void Int64(int64_t)
Definition: reader.h:112
void Uint64(uint64_t)
Definition: reader.h:113
void EndArray(SizeType)
Definition: reader.h:119
void String(const Ch *, SizeType, bool)
Definition: reader.h:115
Encoding::Ch Ch
Definition: reader.h:105