15 #ifndef RAPIDJSON_WRITER_H_
16 #define RAPIDJSON_WRITER_H_
26 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
28 #pragma intrinsic(_BitScanForward)
30 #ifdef RAPIDJSON_SSE42
31 #include <nmmintrin.h>
32 #elif defined(RAPIDJSON_SSE2)
33 #include <emmintrin.h>
38 RAPIDJSON_DIAG_OFF(4127)
43 RAPIDJSON_DIAG_OFF(padded)
44 RAPIDJSON_DIAG_OFF(unreachable-code)
58 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
59 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
86 template<
typename OutputStream,
typename SourceEncoding = UTF8<>,
typename TargetEncoding = UTF8<>,
typename StackAllocator = CrtAllocator,
unsigned writeFlags = kWriteDefaultFlags>
89 typedef typename SourceEncoding::Ch
Ch;
200 #if RAPIDJSON_HAS_STDSTRING
201 bool String(
const std::basic_string<Ch>& str) {
291 for (
const char* p = buffer; p != end; ++p)
292 PutUnsafe(*
os_,
static_cast<typename TargetEncoding::Ch
>(*p));
300 for (
const char* p = buffer; p != end; ++p)
301 PutUnsafe(*
os_,
static_cast<typename TargetEncoding::Ch
>(*p));
309 for (
const char* p = buffer; p != end; ++p)
310 PutUnsafe(*
os_,
static_cast<typename TargetEncoding::Ch
>(*p));
318 for (
char* p = buffer; p != end; ++p)
319 PutUnsafe(*
os_,
static_cast<typename TargetEncoding::Ch
>(*p));
346 for (
char* p = buffer; p != end; ++p)
347 PutUnsafe(*
os_,
static_cast<typename TargetEncoding::Ch
>(*p));
352 static const typename TargetEncoding::Ch hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
353 static const char escape[256] = {
354 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
356 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'b',
't',
'n',
'u',
'f',
'r',
'u',
'u',
357 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
358 0, 0,
'"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
360 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'\\', 0, 0, 0,
365 if (TargetEncoding::supportUnicode)
374 if (!TargetEncoding::supportUnicode &&
static_cast<unsigned>(
c) >= 0x80) {
381 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
390 unsigned s = codepoint - 0x010000;
391 unsigned lead = (s >> 10) + 0xD800;
392 unsigned trail = (s & 0x3FF) + 0xDC00;
405 else if ((
sizeof(
Ch) == 1 ||
static_cast<unsigned>(
c) < 256) &&
RAPIDJSON_UNLIKELY(escape[
static_cast<unsigned char>(
c)])) {
408 PutUnsafe(*
os_,
static_cast<typename TargetEncoding::Ch
>(escape[
static_cast<unsigned char>(
c)]));
409 if (escape[
static_cast<unsigned char>(
c)] ==
'u') {
412 PutUnsafe(*
os_, hexDigits[
static_cast<unsigned char>(
c) >> 4]);
413 PutUnsafe(*
os_, hexDigits[
static_cast<unsigned char>(
c) & 0xF]);
436 for (
size_t i = 0; i < length; i++) {
485 char *buffer = os_->Push(11);
487 os_->Pop(
static_cast<size_t>(11 - (end - buffer)));
493 char *buffer = os_->Push(10);
495 os_->Pop(
static_cast<size_t>(10 - (end - buffer)));
501 char *buffer = os_->Push(21);
503 os_->Pop(
static_cast<size_t>(21 - (end - buffer)));
509 char *buffer = os_->Push(20);
511 os_->Pop(
static_cast<size_t>(20 - (end - buffer)));
537 char *buffer = os_->Push(25);
539 os_->Pop(
static_cast<size_t>(25 - (end - buffer)));
543 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
552 const char* p = is.
src_;
553 const char* end = is.
head_ + length;
554 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
555 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) &
static_cast<size_t>(~15));
556 if (nextAligned > end)
559 while (p != nextAligned)
560 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
565 os_->PutUnsafe(*p++);
568 static const char dquote[16] = {
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"' };
569 static const char bslash[16] = {
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\' };
570 static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
571 const __m128i dq = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(&dquote[0]));
572 const __m128i bs = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(&bslash[0]));
573 const __m128i sp = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(&space[0]));
575 for (; p != endAligned; p += 16) {
576 const __m128i s = _mm_load_si128(
reinterpret_cast<const __m128i *
>(p));
577 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
578 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
579 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp);
580 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
581 unsigned short r =
static_cast<unsigned short>(_mm_movemask_epi8(x));
584 #ifdef _MSC_VER // Find the index of first escaped
585 unsigned long offset;
586 _BitScanForward(&offset, r);
589 len =
static_cast<SizeType>(__builtin_ffs(r) - 1);
591 char* q =
reinterpret_cast<char*
>(os_->PushUnsafe(len));
592 for (
size_t i = 0; i < len; i++)
598 _mm_storeu_si128(
reinterpret_cast<__m128i *
>(os_->PushUnsafe(16)), s);
604 #endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
616 #endif // RAPIDJSON_RAPIDJSON_H_