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;
198 #if RAPIDJSON_HAS_STDSTRING
199 bool String(
const std::basic_string<Ch>& str) {
285 for (
const char*
p = buffer;
p !=
end; ++
p)
286 PutUnsafe(*
os_, static_cast<typename TargetEncoding::Ch>(*
p));
294 for (
const char*
p = buffer;
p !=
end; ++
p)
295 PutUnsafe(*
os_, static_cast<typename TargetEncoding::Ch>(*
p));
303 for (
const char*
p = buffer;
p !=
end; ++
p)
304 PutUnsafe(*
os_, static_cast<typename TargetEncoding::Ch>(*
p));
312 for (
char*
p = buffer;
p !=
end; ++
p)
313 PutUnsafe(*
os_, static_cast<typename TargetEncoding::Ch>(*
p));
340 for (
char*
p = buffer;
p !=
end; ++
p)
341 PutUnsafe(*
os_, static_cast<typename TargetEncoding::Ch>(*
p));
346 static const typename TargetEncoding::Ch hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
347 static const char escape[256] = {
348 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
350 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'b',
't',
'n',
'u',
'f',
'r',
'u',
'u',
351 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
352 0, 0,
'"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
354 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'\\', 0, 0, 0,
355 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
359 if (TargetEncoding::supportUnicode)
368 if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
375 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
384 unsigned s = codepoint - 0x010000;
385 unsigned lead = (s >> 10) + 0xD800;
386 unsigned trail = (s & 0x3FF) + 0xDC00;
399 else if ((
sizeof(
Ch) == 1 || static_cast<unsigned>(c) < 256) &&
RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
402 PutUnsafe(*
os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
403 if (escape[static_cast<unsigned char>(c)] ==
'u') {
406 PutUnsafe(*
os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
407 PutUnsafe(*
os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
430 for (
size_t i = 0; i <
length; i++) {
479 char *
buffer = os_->Push(11);
481 os_->Pop(static_cast<size_t>(11 - (end - buffer)));
487 char *
buffer = os_->Push(10);
489 os_->Pop(static_cast<size_t>(10 - (end - buffer)));
495 char *
buffer = os_->Push(21);
497 os_->Pop(static_cast<size_t>(21 - (end - buffer)));
503 char *
buffer = os_->Push(20);
505 os_->Pop(static_cast<size_t>(20 - (end - buffer)));
531 char *
buffer = os_->Push(25);
533 os_->Pop(static_cast<size_t>(25 - (end - buffer)));
537 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
546 const char*
p = is.
src_;
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)
553 while (p != nextAligned)
554 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
559 os_->PutUnsafe(*p++);
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]));
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);
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));
578 #ifdef _MSC_VER // Find the index of first escaped
580 _BitScanForward(&offset, r);
583 len =
static_cast<SizeType>(__builtin_ffs(r) - 1);
585 char*
q =
reinterpret_cast<char*
>(os_->PushUnsafe(len));
586 for (
size_t i = 0; i <
len; i++)
592 _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
598 #endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
610 #endif // RAPIDJSON_RAPIDJSON_H_