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
110 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
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
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;
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
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>
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>
335 if (stream.Take() ==
'u' && stream.Take() ==
'l' && stream.Take() ==
'l')
341 template<
unsigned parseFlags,
typename Stream,
typename Handler>
346 if (stream.Take() ==
'r' && stream.Take() ==
'u' && stream.Take() ==
'e')
352 template<
unsigned parseFlags,
typename Stream,
typename Handler>
357 if (stream.Take() ==
'a' && stream.Take() ==
'l' && stream.Take() ==
's' && stream.Take() ==
'e')
364 template<
typename 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>
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,
394 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
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])
426 if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
427 if (s.Take() !=
'\\' || s.Take() !=
'u') {
432 if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) {
436 codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
442 if (parseFlags & kParseInsituFlag)
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>
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>
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);
683 #endif // RAPIDJSON_READER_H_