| 537 | #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) |
| 538 | template<> |
| 539 | inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) { |
| 540 | if (length < 16) |
| 541 | return RAPIDJSON_LIKELY(is.Tell() < length); |
| 542 | |
| 543 | if (!RAPIDJSON_LIKELY(is.Tell() < length)) |
| 544 | return false; |
| 545 | |
| 546 | const char* p = is.src_; |
| 547 | const char* end = is.head_ + length; |
| 548 | const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); |
| 549 | const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15)); |
| 550 | if (nextAligned > end) |
| 551 | return true; |
| 552 | |
| 553 | while (p != nextAligned) |
| 554 | if (*p < 0x20 || *p == '\"' || *p == '\\') { |
| 555 | is.src_ = p; |
| 556 | return RAPIDJSON_LIKELY(is.Tell() < length); |
| 557 | } |
| 558 | else |
| 559 | os_->PutUnsafe(*p++); |
| 560 | |
| 561 | // The rest of string using SIMD |
| 562 | static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; |
| 563 | static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; |
| 564 | static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; |
| 565 | const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); |
| 566 | const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); |
| 567 | const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); |
| 568 | |
| 569 | for (; p != endAligned; p += 16) { |
| 570 | const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); |
| 571 | const __m128i t1 = _mm_cmpeq_epi8(s, dq); |
| 572 | const __m128i t2 = _mm_cmpeq_epi8(s, bs); |
| 573 | const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 |
| 574 | const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); |
| 575 | unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); |
| 576 | if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped |
| 577 | SizeType len; |
| 578 | #ifdef _MSC_VER // Find the index of first escaped |
| 579 | unsigned long offset; |
| 580 | _BitScanForward(&offset, r); |
| 581 | len = offset; |
| 582 | #else |
| 583 | len = static_cast<SizeType>(__builtin_ffs(r) - 1); |
| 584 | #endif |
| 585 | char* q = reinterpret_cast<char*>(os_->PushUnsafe(len)); |
| 586 | for (size_t i = 0; i < len; i++) |
| 587 | q[i] = p[i]; |
| 588 | |
| 589 | p += len; |
| 590 | break; |
| 591 | } |
| 592 | _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s); |
| 593 | } |
| 594 | |
| 595 | is.src_ = p; |
| 596 | return RAPIDJSON_LIKELY(is.Tell() < length); |
nothing calls this directly
no test coverage detected