15 #ifndef RAPIDJSON_WRITER_H_ 16 #define RAPIDJSON_WRITER_H_ 27 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) 29 #pragma intrinsic(_BitScanForward) 31 #ifdef RAPIDJSON_SSE42 32 #include <nmmintrin.h> 33 #elif defined(RAPIDJSON_SSE2) 34 #include <emmintrin.h> 35 #elif defined(RAPIDJSON_NEON) 41 RAPIDJSON_DIAG_OFF(padded)
42 RAPIDJSON_DIAG_OFF(unreachable-code)
43 RAPIDJSON_DIAG_OFF(c++98-compat)
44 #elif defined(_MSC_VER) 46 RAPIDJSON_DIAG_OFF(4127)
60 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS 61 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags 88 template<
typename OutputStream,
typename SourceEncoding = UTF8<>,
typename TargetEncoding = UTF8<>,
typename StackAllocator = CrtAllocator,
unsigned writeFlags = kWriteDefaultFlags>
91 typedef typename SourceEncoding::Ch
Ch;
108 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 209 #if RAPIDJSON_HAS_STDSTRING 210 bool String(
const std::basic_string<Ch>& str) {
221 bool Key(
const Ch* str,
SizeType length,
bool copy =
false) {
return String(str, length, copy); }
223 #if RAPIDJSON_HAS_STDSTRING 224 bool Key(
const std::basic_string<Ch>& str)
316 for (
const char* p = buffer; p != end; ++p)
317 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
325 for (
const char* p = buffer; p != end; ++p)
326 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
334 for (
const char* p = buffer; p != end; ++p)
335 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
343 for (
char* p = buffer; p != end; ++p)
344 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
371 for (
char* p = buffer; p != end; ++p)
372 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
377 static const typename OutputStream::Ch hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
378 static const char escape[256] = {
379 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 381 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'b',
't',
'n',
'u',
'f',
'r',
'u',
'u',
382 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
383 0, 0,
'"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
385 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'\\', 0, 0, 0,
390 if (TargetEncoding::supportUnicode)
398 const Ch c = is.
Peek();
399 if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
406 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
415 unsigned s = codepoint - 0x010000;
416 unsigned lead = (s >> 10) + 0xD800;
417 unsigned trail = (s & 0x3FF) + 0xDC00;
430 else if ((
sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) &&
RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
433 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
434 if (escape[static_cast<unsigned char>(c)] ==
'u') {
437 PutUnsafe(*
os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
438 PutUnsafe(*
os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
514 char *buffer =
os_->Push(11);
516 os_->Pop(static_cast<size_t>(11 - (end - buffer)));
522 char *buffer =
os_->Push(10);
524 os_->Pop(static_cast<size_t>(10 - (end - buffer)));
530 char *buffer =
os_->Push(21);
532 os_->Pop(static_cast<size_t>(21 - (end - buffer)));
538 char *buffer =
os_->Push(20);
540 os_->Pop(static_cast<size_t>(20 - (end - buffer)));
566 char *buffer =
os_->Push(25);
568 os_->Pop(static_cast<size_t>(25 - (end - buffer)));
572 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) 581 const char* p = is.
src_;
582 const char* end = is.
head_ + length;
583 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
584 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
585 if (nextAligned > end)
588 while (p != nextAligned)
589 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
594 os_->PutUnsafe(*p++);
597 static const char dquote[16] = {
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"' };
598 static const char bslash[16] = {
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\' };
599 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
600 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
601 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
602 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
604 for (; p != endAligned; p += 16) {
605 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
606 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
607 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
608 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp);
609 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
610 unsigned short r =
static_cast<unsigned short>(_mm_movemask_epi8(x));
613 #ifdef _MSC_VER // Find the index of first escaped 614 unsigned long offset;
615 _BitScanForward(&offset, r);
618 len =
static_cast<SizeType>(__builtin_ffs(r) - 1);
620 char* q =
reinterpret_cast<char*
>(
os_->PushUnsafe(len));
621 for (
size_t i = 0; i < len; i++)
627 _mm_storeu_si128(reinterpret_cast<__m128i *>(
os_->PushUnsafe(16)), s);
633 #elif defined(RAPIDJSON_NEON) 642 const char* p = is.
src_;
643 const char* end = is.
head_ + length;
644 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
645 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
646 if (nextAligned > end)
649 while (p != nextAligned)
650 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
655 os_->PutUnsafe(*p++);
658 const uint8x16_t s0 = vmovq_n_u8(
'"');
659 const uint8x16_t s1 = vmovq_n_u8(
'\\');
660 const uint8x16_t s2 = vmovq_n_u8(
'\b');
661 const uint8x16_t s3 = vmovq_n_u8(32);
663 for (; p != endAligned; p += 16) {
664 const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
665 uint8x16_t x = vceqq_u8(s, s0);
666 x = vorrq_u8(x, vceqq_u8(s, s1));
667 x = vorrq_u8(x, vceqq_u8(s, s2));
668 x = vorrq_u8(x, vcltq_u8(s, s3));
671 uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0);
672 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1);
675 bool escaped =
false;
678 unsigned lz = (unsigned)__builtin_clzll(high);
683 unsigned lz = (unsigned)__builtin_clzll(low);
688 char* q =
reinterpret_cast<char*
>(
os_->PushUnsafe(len));
689 for (
size_t i = 0; i < len; i++)
695 vst1q_u8(reinterpret_cast<uint8_t *>(
os_->PushUnsafe(16)), s);
701 #endif // RAPIDJSON_NEON 705 #if defined(_MSC_VER) || defined(__clang__) 709 #endif // RAPIDJSON_RAPIDJSON_H_
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
Writer(StackAllocator *allocator=0, size_t levelDepth=kDefaultLevelDepth)
char * u64toa(uint64_t value, char *buffer)
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
void Reset(OutputStream &os)
Reset the writer with a new stream.
Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS. ...
internal::Stack< StackAllocator > level_stack_
Writer & operator=(const Writer &)
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Validate encoding of JSON strings.
bool String(const Ch *str, SizeType length, bool copy=false)
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
int GetMaxDecimalPlaces() const
bool IsComplete() const
Checks whether the output is a complete JSON.
bool Uint64(uint64_t u64)
bool String(const Ch *const &str)
Simpler but slower overload.
bool WriteUint64(uint64_t u64)
bool Key(const Ch *const &str)
static const size_t kDefaultLevelDepth
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
bool WriteString(const Ch *str, SizeType length)
const Ch * src_
Current read position.
unsigned __int64 uint64_t
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
bool ScanWriteUnescapedString(GenericStringStream< SourceEncoding > &is, size_t length)
bool WriteInt64(int64_t i64)
size_t valueCount
number of values in this level
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
char * u32toa(uint32_t value, char *buffer)
bool Double(double d)
Writes the given double value to the stream.
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Information for each nested level.
bool WriteUint(unsigned u)
bool EndArray(SizeType elementCount=0)
bool WriteDouble(double d)
bool WriteRawValue(const Ch *json, size_t length)
WriteFlag
Combination of writeFlags.
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
bool RawNumber(const Ch *str, SizeType length, bool copy=false)
bool EndObject(SizeType memberCount=0)
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Allow writing of Infinity, -Infinity and NaN.
const Ch * head_
Original head of the string.
static const int kDefaultMaxDecimalPlaces
char * i64toa(int64_t value, char *buffer)
bool inArray
true if in array, otherwise in object
void Flush()
Flush the output stream.
char * i32toa(int32_t value, char *buffer)
#define RAPIDJSON_ASSERT(x)
Assertion.
char * dtoa(double value, char *buffer, int maxDecimalPlaces=324)
bool Key(const Ch *str, SizeType length, bool copy=false)