rapidjson::GenericReader< Encoding, Allocator > Class Template Reference

SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator. More...

#include <reader.h>

Public Types

typedef Encoding::Ch Ch
 

Public Member Functions

 GenericReader (Allocator *allocator=0, size_t stackCapacity=kDefaultStackCapacity)
 Constructor. More...
 
template<unsigned parseFlags, typename Stream , typename Handler >
bool Parse (Stream &stream, Handler &handler)
 Parse JSON text. More...
 
bool HasParseError () const
 
const charGetParseError () const
 
size_t GetErrorOffset () const
 

Private Member Functions

template<unsigned parseFlags, typename Stream , typename Handler >
void ParseObject (Stream &stream, Handler &handler)
 
template<unsigned parseFlags, typename Stream , typename Handler >
void ParseArray (Stream &stream, Handler &handler)
 
template<unsigned parseFlags, typename Stream , typename Handler >
void ParseNaNNull_ (Stream &stream, Handler &handler)
 
template<unsigned parseFlags, typename Stream , typename Handler >
void ParseInfinity (Stream &stream, Handler &handler)
 
template<unsigned parseFlags, typename Stream , typename Handler >
void ParseTrue (Stream &stream, Handler &handler)
 
template<unsigned parseFlags, typename Stream , typename Handler >
void ParseFalse (Stream &stream, Handler &handler)
 
template<typename Stream >
unsigned ParseHex4 (Stream &stream)
 
template<class Ch >
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)
 
template<unsigned parseFlags, typename Stream , typename Handler >
void ParseString (Stream &stream, Handler &handler)
 
template<unsigned parseFlags, typename Stream , typename Handler >
void ParseNumber (Stream &stream, Handler &handler)
 
template<unsigned parseFlags, typename Stream , typename Handler >
void ParseValue (Stream &stream, Handler &handler)
 

Static Private Member Functions

template<class T >
static constexpr int to_int (T t)
 

Private Attributes

internal::Stack< Allocatorstack_
 A stack for storing decoded string temporarily during non-destructive parsing. More...
 
jmp_buf jmpbuf_
 setjmp buffer for fast exit from nested parsing function calls. More...
 
const charparseError_
 
size_t errorOffset_
 

Static Private Attributes

static const size_t kDefaultStackCapacity = 256
 Default stack capacity in bytes for storing a single decoded string. More...
 

Detailed Description

template<typename Encoding, typename Allocator = MemoryPoolAllocator<>>
class rapidjson::GenericReader< Encoding, Allocator >

SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.

GenericReader parses JSON text from a stream, and send events synchronously to an object implementing Handler concept.

It needs to allocate a stack for storing a single decoded string during non-destructive parsing.

For in-situ parsing, the decoded string is directly written to the source text string, no temporary buffer is required.

A GenericReader object can be reused for parsing multiple JSON text.

Template Parameters
EncodingEncoding of both the stream and the parse output.
AllocatorAllocator type for stack.

Member Typedef Documentation

◆ Ch

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
typedef Encoding::Ch rapidjson::GenericReader< Encoding, Allocator >::Ch

Constructor & Destructor Documentation

◆ GenericReader()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
rapidjson::GenericReader< Encoding, Allocator >::GenericReader ( Allocator allocator = 0,
size_t  stackCapacity = kDefaultStackCapacity 
)
inline

Constructor.

Parameters
allocatorOptional allocator for allocating stack memory. (Only use for non-destructive parsing)
stackCapacitystack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
239 : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {}
internal::Stack< Allocator > stack_
A stack for storing decoded string temporarily during non-destructive parsing.
Definition: reader.h:758
const char * parseError_
Definition: reader.h:760
size_t errorOffset_
Definition: reader.h:761

Member Function Documentation

◆ characterOk()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<class Ch >
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 rapidjson::GenericReader< Encoding, Allocator >::characterOk ( Ch  c)
inlineprivate
458  { return c < 256; }

Referenced by rapidjson::GenericReader< Encoding, Allocator >::ParseString().

◆ GetErrorOffset()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
size_t rapidjson::GenericReader< Encoding, Allocator >::GetErrorOffset ( ) const
inline

◆ GetParseError()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
const char* rapidjson::GenericReader< Encoding, Allocator >::GetParseError ( ) const
inline

◆ HasParseError()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
bool rapidjson::GenericReader< Encoding, Allocator >::HasParseError ( ) const
inline

◆ Parse()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<unsigned parseFlags, typename Stream , typename Handler >
bool rapidjson::GenericReader< Encoding, Allocator >::Parse ( Stream stream,
Handler handler 
)
inline

Parse JSON text.

Template Parameters
parseFlagsCombination of ParseFlag.
StreamType of input stream.
HandlerType of handler which must implement Handler concept.
Parameters
streamInput stream to be parsed.
handlerThe handler to receive events.
Returns
Whether the parsing is successful.
250  {
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  }
jmp_buf jmpbuf_
setjmp buffer for fast exit from nested parsing function calls.
Definition: reader.h:759
Encoding::Ch Ch
Definition: reader.h:233
void SkipWhitespace(Stream &stream)
Skip the JSON white spaces in a stream.
Definition: reader.h:130
#define RAPIDJSON_PARSE_ERROR(msg, offset)
Definition: reader.h:54

References rapidjson::GenericReader< Encoding, Allocator >::errorOffset_, rapidjson::GenericReader< Encoding, Allocator >::jmpbuf_, rapidjson::GenericReader< Encoding, Allocator >::parseError_, RAPIDJSON_PARSE_ERROR, rapidjson::SkipWhitespace(), and rapidjson::GenericReader< Encoding, Allocator >::stack_.

◆ ParseArray()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<unsigned parseFlags, typename Stream , typename Handler >
void rapidjson::GenericReader< Encoding, Allocator >::ParseArray ( Stream stream,
Handler handler 
)
inlineprivate
334  {
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  }
unsigned SizeType
Use 32-bit array/string indices even for 64-bit platform, instead of using size_t.
Definition: rapidjson.h:92
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:105

References RAPIDJSON_ASSERT, RAPIDJSON_PARSE_ERROR, and rapidjson::SkipWhitespace().

◆ ParseFalse()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<unsigned parseFlags, typename Stream , typename Handler >
void rapidjson::GenericReader< Encoding, Allocator >::ParseFalse ( Stream stream,
Handler handler 
)
inlineprivate
397  {
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  }

References RAPIDJSON_ASSERT, and RAPIDJSON_PARSE_ERROR.

◆ ParseHex4()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<typename Stream >
unsigned rapidjson::GenericReader< Encoding, Allocator >::ParseHex4 ( Stream stream)
inlineprivate
409  {
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  }
Concept for reading and writing characters.
const std::complex< Mdouble > i
Definition: ExtendedMath.h:51

References constants::i, and RAPIDJSON_PARSE_ERROR.

Referenced by rapidjson::GenericReader< Encoding, Allocator >::ParseString().

◆ ParseInfinity()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<unsigned parseFlags, typename Stream , typename Handler >
void rapidjson::GenericReader< Encoding, Allocator >::ParseInfinity ( Stream stream,
Handler handler 
)
inlineprivate
375  {
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  }

References RAPIDJSON_ASSERT, and RAPIDJSON_PARSE_ERROR.

◆ ParseNaNNull_()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<unsigned parseFlags, typename Stream , typename Handler >
void rapidjson::GenericReader< Encoding, Allocator >::ParseNaNNull_ ( Stream stream,
Handler handler 
)
inlineprivate
361  {
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  }

References RAPIDJSON_ASSERT, and RAPIDJSON_PARSE_ERROR.

◆ ParseNumber()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<unsigned parseFlags, typename Stream , typename Handler >
void rapidjson::GenericReader< Encoding, Allocator >::ParseNumber ( Stream stream,
Handler handler 
)
inlineprivate
560  {
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  }
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

References mathsFunc::exp(), constants::i, rapidjson::internal::Pow10(), and RAPIDJSON_PARSE_ERROR.

◆ ParseObject()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<unsigned parseFlags, typename Stream , typename Handler >
void rapidjson::GenericReader< Encoding, Allocator >::ParseObject ( Stream stream,
Handler handler 
)
inlineprivate
292  {
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  }

References RAPIDJSON_ASSERT, RAPIDJSON_PARSE_ERROR, and rapidjson::SkipWhitespace().

◆ ParseString()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<unsigned parseFlags, typename Stream , typename Handler >
void rapidjson::GenericReader< Encoding, Allocator >::ParseString ( Stream stream,
Handler handler 
)
inlineprivate
463  {
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  }
unsigned ParseHex4(Stream &stream)
Definition: reader.h:409
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
@ kParseInsituFlag
In-situ(destructive) parsing.
Definition: reader.h:69
#define RAPIDJSON_PUT(x)
#define Z16

References rapidjson::GenericReader< Encoding, Allocator >::characterOk(), constants::i, rapidjson::kParseInsituFlag, rapidjson::GenericReader< Encoding, Allocator >::ParseHex4(), RAPIDJSON_ASSERT, RAPIDJSON_PARSE_ERROR, RAPIDJSON_PUT, rapidjson::GenericReader< Encoding, Allocator >::stack_, and Z16.

◆ ParseTrue()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<unsigned parseFlags, typename Stream , typename Handler >
void rapidjson::GenericReader< Encoding, Allocator >::ParseTrue ( Stream stream,
Handler handler 
)
inlineprivate
386  {
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  }

References RAPIDJSON_ASSERT, and RAPIDJSON_PARSE_ERROR.

◆ ParseValue()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<unsigned parseFlags, typename Stream , typename Handler >
void rapidjson::GenericReader< Encoding, Allocator >::ParseValue ( Stream stream,
Handler handler 
)
inlineprivate
744  {
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  }

◆ to_int()

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
template<class T >
static constexpr int rapidjson::GenericReader< Encoding, Allocator >::to_int ( t)
inlinestaticconstexprprivate
446 { return t; }

Member Data Documentation

◆ errorOffset_

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
size_t rapidjson::GenericReader< Encoding, Allocator >::errorOffset_
private

◆ jmpbuf_

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
jmp_buf rapidjson::GenericReader< Encoding, Allocator >::jmpbuf_
private

setjmp buffer for fast exit from nested parsing function calls.

Referenced by rapidjson::GenericReader< Encoding, Allocator >::Parse().

◆ kDefaultStackCapacity

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
const size_t rapidjson::GenericReader< Encoding, Allocator >::kDefaultStackCapacity = 256
staticprivate

Default stack capacity in bytes for storing a single decoded string.

◆ parseError_

◆ stack_

template<typename Encoding , typename Allocator = MemoryPoolAllocator<>>
internal::Stack<Allocator> rapidjson::GenericReader< Encoding, Allocator >::stack_
private

A stack for storing decoded string temporarily during non-destructive parsing.

Referenced by rapidjson::GenericReader< Encoding, Allocator >::Parse(), and rapidjson::GenericReader< Encoding, Allocator >::ParseString().


The documentation for this class was generated from the following file: