1 #ifndef RAPIDJSON_READER_H_
2 #define RAPIDJSON_READER_H_
12 #ifdef RAPIDJSON_SSE42
13 #include <nmmintrin.h>
14 #elif defined(RAPIDJSON_SSE2)
15 #include <emmintrin.h>
20 #pragma warning(disable : 4127) // conditional expression is constant
23 #ifndef RAPIDJSON_PARSE_ERROR
24 #define RAPIDJSON_PARSE_ERROR(msg, offset) \
25 RAPIDJSON_MULTILINEMACRO_BEGIN \
27 errorOffset_ = offset; \
28 longjmp(jmpbuf_, 1); \
29 RAPIDJSON_MULTILINEMACRO_END
74 template<
typename Encoding = UTF8<> >
76 typedef typename Encoding::Ch
Ch;
100 template<
typename Stream>
103 while (s.Peek() ==
' ' || s.Peek() ==
'\n' || s.Peek() ==
'\r' || s.Peek() ==
'\t')
108 #ifdef RAPIDJSON_SSE42
109 inline const char *SkipWhitespace_SIMD(
const char* p) {
111 static const char whitespace[16] =
" \n\r\t";
112 __m128i w = _mm_loadu_si128((
const __m128i *)&whitespace[0]);
115 __m128i s = _mm_loadu_si128((
const __m128i *)p);
116 unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
120 #ifdef _MSC_VER // Find the index of first non-whitespace
121 unsigned long offset;
122 if (_BitScanForward(&offset, r))
126 return p + __builtin_ffs(r) - 1;
132 #elif defined(RAPIDJSON_SSE2)
135 inline const char *SkipWhitespace_SIMD(
const char* p) {
136 static const char whitespaces[4][17] = {
138 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
139 "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
140 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
142 __m128i w0 = _mm_loadu_si128((
const __m128i *)&whitespaces[0][0]);
143 __m128i w1 = _mm_loadu_si128((
const __m128i *)&whitespaces[1][0]);
144 __m128i w2 = _mm_loadu_si128((
const __m128i *)&whitespaces[2][0]);
145 __m128i w3 = _mm_loadu_si128((
const __m128i *)&whitespaces[3][0]);
148 __m128i s = _mm_loadu_si128((
const __m128i *)p);
149 __m128i
x = _mm_cmpeq_epi8(s, w0);
150 x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
151 x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
152 x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
153 unsigned short r = ~_mm_movemask_epi8(x);
157 #ifdef _MSC_VER // Find the index of first non-whitespace
158 unsigned long offset;
159 if (_BitScanForward(&offset, r))
163 return p + __builtin_ffs(r) - 1;
169 #endif // RAPIDJSON_SSE2
171 #ifdef RAPIDJSON_SIMD
174 stream.src_ =
const_cast<char*
>(SkipWhitespace_SIMD(stream.src_));
179 stream.src_ = SkipWhitespace_SIMD(stream.src_);
181 #endif // RAPIDJSON_SIMD
201 template <
typename Encoding,
typename Allocator = MemoryPoolAllocator<> >
204 typedef typename Encoding::Ch
Ch;
210 GenericReader(
Allocator* allocator = 0,
size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {}
220 template <
unsigned parseFlags,
typename Stream,
typename Handler>
226 #pragma warning(push)
227 #pragma warning(disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
229 if (setjmp(jmpbuf_)) {
239 if (stream.Peek() ==
'\0')
242 switch (stream.Peek()) {
243 case '{': ParseObject<parseFlags>(stream, handler);
break;
244 case '[': ParseArray<parseFlags>(stream, handler);
break;
249 if (stream.Peek() !=
'\0')
262 template<
unsigned parseFlags,
typename Stream,
typename Handler>
266 handler.StartObject();
269 if (stream.Peek() ==
'}') {
271 handler.EndObject(0);
276 if (stream.Peek() !=
'"') {
281 ParseString<parseFlags>(stream, handler);
284 if (stream.Take() !=
':') {
290 ParseValue<parseFlags>(stream, handler);
295 switch(stream.Take()) {
297 case '}': handler.EndObject(memberCount);
return;
304 template<
unsigned parseFlags,
typename Stream,
typename Handler>
305 void ParseArray(Stream& stream, Handler& handler) {
308 handler.StartArray();
311 if (stream.Peek() ==
']') {
318 ParseValue<parseFlags>(stream, handler);
322 switch (stream.Take()) {
324 case ']': handler.EndArray(elementCount);
return;
330 template<
unsigned parseFlags,
typename Stream,
typename Handler>
331 void ParseNull(Stream& stream, Handler& handler) {
335 if (stream.Take() ==
'u' && stream.Take() ==
'l' && stream.Take() ==
'l')
341 template<
unsigned parseFlags,
typename Stream,
typename Handler>
342 void ParseTrue(Stream& stream, Handler& handler) {
346 if (stream.Take() ==
'r' && stream.Take() ==
'u' && stream.Take() ==
'e')
352 template<
unsigned parseFlags,
typename Stream,
typename Handler>
353 void ParseFalse(Stream& stream, Handler& handler) {
357 if (stream.Take() ==
'a' && stream.Take() ==
'l' && stream.Take() ==
's' && stream.Take() ==
'e')
364 template<
typename Stream>
365 unsigned ParseHex4(Stream& stream) {
367 unsigned codepoint = 0;
368 for (
int i = 0; i < 4; i++) {
372 if (c >=
'0' && c <=
'9')
374 else if (c >=
'A' && c <=
'F')
375 codepoint -=
'A' - 10;
376 else if (c >=
'a' && c <=
'f')
377 codepoint -=
'a' - 10;
386 template<
unsigned parseFlags,
typename Stream,
typename Handler>
387 void ParseString(Stream& stream, Handler& handler) {
388 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
389 static const Ch escape[256] = {
390 Z16,
Z16, 0, 0,
'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'/',
391 Z16,
Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'\\', 0, 0, 0,
392 0, 0,
'\b', 0, 0, 0,
'\f', 0, 0, 0, 0, 0, 0, 0,
'\n', 0,
393 0, 0,
'\r', 0,
'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
408 #define RAPIDJSON_PUT(x) \
410 if (parseFlags & kParseInsituFlag) \
413 *stack_.template Push<Ch>() = x; \
422 if ((
sizeof(
Ch) == 1 || e < 256) && escape[(
unsigned char)e])
425 unsigned codepoint = ParseHex4(s);
426 if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
427 if (s.Take() !=
'\\' || s.Take() !=
'u') {
431 unsigned codepoint2 = ParseHex4(s);
432 if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) {
436 codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
440 SizeType count =
SizeType(Encoding::Encode(buffer, codepoint) - &buffer[0]);
442 if (parseFlags & kParseInsituFlag)
443 for (
SizeType i = 0; i < count; i++)
446 memcpy(stack_.template Push<Ch>(count), buffer, count *
sizeof(
Ch));
456 if (parseFlags & kParseInsituFlag) {
457 size_t length = s.PutEnd(head);
460 handler.String(head,
SizeType(length),
false);
464 handler.String(stack_.template Pop<Ch>(len), len - 1,
true);
469 else if (c ==
'\0') {
473 else if ((
unsigned)c < 0x20) {
483 template<
unsigned parseFlags,
typename Stream,
typename Handler>
484 void ParseNumber(Stream& stream, Handler& handler) {
488 if (s.Peek() ==
'-') {
495 bool try64bit =
false;
496 if (s.Peek() ==
'0') {
500 else if (s.Peek() >=
'1' && s.Peek() <=
'9') {
504 while (s.Peek() >=
'0' && s.Peek() <=
'9') {
505 if (i >= 214748364) {
506 if (i != 214748364 || s.Peek() >
'8') {
511 i = i * 10 + (s.Take() -
'0');
514 while (s.Peek() >=
'0' && s.Peek() <=
'9') {
515 if (i >= 429496729) {
516 if (i != 429496729 || s.Peek() >
'5') {
521 i = i * 10 + (s.Take() -
'0');
531 bool useDouble =
false;
535 while (s.Peek() >=
'0' && s.Peek() <=
'9') {
536 if (i64 >= 922337203685477580uLL)
537 if (i64 != 922337203685477580uLL || s.Peek() >
'8') {
541 i64 = i64 * 10 + (s.Take() -
'0');
544 while (s.Peek() >=
'0' && s.Peek() <=
'9') {
545 if (i64 >= 1844674407370955161uLL)
546 if (i64 != 1844674407370955161uLL || s.Peek() >
'5') {
550 i64 = i64 * 10 + (s.Take() -
'0');
558 while (s.Peek() >=
'0' && s.Peek() <=
'9') {
563 d = d * 10 + (s.Take() -
'0');
569 if (s.Peek() ==
'.') {
571 d = try64bit ? (double)i64 : (
double)i;
576 if (s.Peek() >= '0' && s.Peek() <= '9') {
577 d = d * 10 + (s.Take() -
'0');
585 while (s.Peek() >=
'0' && s.Peek() <=
'9') {
587 d = d * 10 + (s.Peek() -
'0');
596 if (s.Peek() ==
'e' || s.Peek() ==
'E') {
598 d = try64bit ? (double)i64 : (
double)i;
603 bool expMinus = false;
606 else if (s.Peek() == '-') {
611 if (s.Peek() >=
'0' && s.Peek() <=
'9') {
612 exp = s.Take() -
'0';
613 while (s.Peek() >=
'0' && s.Peek() <=
'9') {
614 exp = exp * 10 + (s.Take() -
'0');
633 handler.Double(minus ? -d : d);
638 handler.Int64(-(int64_t)i64);
644 handler.Int(-(
int)i);
654 template<
unsigned parseFlags,
typename Stream,
typename Handler>
655 void ParseValue(Stream& stream, Handler& handler) {
656 switch (stream.Peek()) {
657 case 'n': ParseNull <parseFlags>(stream, handler);
break;
658 case 't': ParseTrue <parseFlags>(stream, handler);
break;
659 case 'f': ParseFalse <parseFlags>(stream, handler);
break;
660 case '"': ParseString<parseFlags>(stream, handler);
break;
661 case '{': ParseObject<parseFlags>(stream, handler);
break;
662 case '[': ParseArray <parseFlags>(stream, handler);
break;
663 default : ParseNumber<parseFlags>(stream, handler);
667 static const size_t kDefaultStackCapacity = 256;
668 internal::Stack<Allocator> stack_;
670 const char* parseError_;
683 #endif // RAPIDJSON_READER_H_
Concept for receiving events from GenericReader upon parsing.
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
unsigned SizeType
Use 32-bit array/string indices even for 64-bit platform, instead of using size_t.
GenericInsituStringStream< UTF8<> > InsituStringStream
GenericReader(Allocator *allocator=0, size_t stackCapacity=kDefaultStackCapacity)
Constructor.
std::vector< double > x(ncmax, 0)
#define RAPIDJSON_ASSERT(x)
Assertion.
double Pow10(int n)
Computes integer powers of 10 in double (10.0^n).
#define RAPIDJSON_PARSE_ERROR(msg, offset)
GenericStringStream< UTF8<> > StringStream
Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer...
ParseFlag
Combination of parseFlags.
Concept for reading and writing characters.
void SkipWhitespace(Stream &stream)
Skip the JSON white spaces in a stream.
size_t GetErrorOffset() const
GenericReader< UTF8<> > Reader
Reader with UTF8 encoding and default allocator.
Default implementation of Handler.
const char * GetParseError() const
In-situ(destructive) parsing.
Concept for allocating, resizing and freeing memory block.
bool HasParseError() const
bool Parse(Stream &stream, Handler &handler)
Parse JSON text.
void String(const Ch *, SizeType, bool)