15 #ifndef RAPIDJSON_WRITER_H_ 16 #define RAPIDJSON_WRITER_H_ 27 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) 29 #pragma intrinsic(_BitScanForward) 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 90 template <
typename OutputStream,
typename SourceEncoding = UTF8<>,
typename TargetEncoding = UTF8<>,
91 typename StackAllocator = CrtAllocator,
unsigned writeFlags = kWriteDefaultFlags>
95 typedef typename SourceEncoding::Ch
Ch;
120 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 260 #if RAPIDJSON_HAS_STDSTRING 261 bool String(
const std::basic_string<Ch>& str)
276 return String(str, length, copy);
279 #if RAPIDJSON_HAS_STDSTRING 280 bool Key(
const std::basic_string<Ch>& str)
321 bool Key(
const Ch*
const& str)
402 for (
const char* p = buffer; p != end; ++p)
403 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
412 for (
const char* p = buffer; p != end; ++p)
413 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
422 for (
const char* p = buffer; p != end; ++p)
423 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
432 for (
char* p = buffer; p != end; ++p)
433 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
472 for (
char* p = buffer; p != end; ++p)
473 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
479 static const typename OutputStream::Ch hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
480 '8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
481 static const char escape[256] = {
482 #define Z16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 484 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'b',
't',
'n',
'u',
'f',
'r',
'u',
'u',
485 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
486 0, 0,
'"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
488 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'\\', 0, 0, 0,
493 if (TargetEncoding::supportUnicode)
502 const Ch c = is.
Peek();
503 if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80)
511 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF))
522 unsigned s = codepoint - 0x010000;
523 unsigned lead = (s >> 10) + 0xD800;
524 unsigned trail = (s & 0x3FF) + 0xDC00;
537 else if ((
sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) &&
542 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
543 if (escape[static_cast<unsigned char>(c)] ==
'u')
547 PutUnsafe(*
os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
548 PutUnsafe(*
os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
649 char* buffer =
os_->Push(11);
651 os_->Pop(static_cast<size_t>(11 - (end - buffer)));
658 char* buffer =
os_->Push(10);
660 os_->Pop(static_cast<size_t>(10 - (end - buffer)));
667 char* buffer =
os_->Push(21);
669 os_->Pop(static_cast<size_t>(21 - (end - buffer)));
676 char* buffer =
os_->Push(20);
678 os_->Pop(static_cast<size_t>(20 - (end - buffer)));
716 char* buffer =
os_->Push(25);
718 os_->Pop(static_cast<size_t>(25 - (end - buffer)));
722 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) 732 const char* p = is.
src_;
733 const char* end = is.
head_ + length;
734 const char* nextAligned =
735 reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
736 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
737 if (nextAligned > end)
740 while (p != nextAligned)
741 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\')
747 os_->PutUnsafe(*p++);
750 static const char dquote[16] = {
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
751 '\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"' };
752 static const char bslash[16] = {
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
753 '\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\' };
754 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
755 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
756 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0]));
757 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0]));
758 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0]));
760 for (; p != endAligned; p += 16)
762 const __m128i
s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
763 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
764 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
765 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp);
766 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
767 unsigned short r =
static_cast<unsigned short>(_mm_movemask_epi8(x));
771 #if _MSC_VER // Find the index of first escaped 772 unsigned long offset;
773 _BitScanForward(&offset, r);
776 len =
static_cast<SizeType>(__builtin_ffs(r) - 1);
778 char* q =
reinterpret_cast<char*
>(
os_->PushUnsafe(len));
779 for (
size_t i = 0; i < len; i++)
785 _mm_storeu_si128(reinterpret_cast<__m128i*>(
os_->PushUnsafe(16)), s);
791 #elif defined(RAPIDJSON_NEON) 801 const char* p = is.
src_;
802 const char* end = is.
head_ + length;
803 const char* nextAligned =
804 reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
805 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
806 if (nextAligned > end)
809 while (p != nextAligned)
810 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\')
816 os_->PutUnsafe(*p++);
819 const uint8x16_t s0 = vmovq_n_u8(
'"');
820 const uint8x16_t s1 = vmovq_n_u8(
'\\');
821 const uint8x16_t s2 = vmovq_n_u8(
'\b');
822 const uint8x16_t s3 = vmovq_n_u8(32);
824 for (; p != endAligned; p += 16)
826 const uint8x16_t
s = vld1q_u8(reinterpret_cast<const uint8_t*>(p));
827 uint8x16_t x = vceqq_u8(s, s0);
828 x = vorrq_u8(x, vceqq_u8(s, s1));
829 x = vorrq_u8(x, vceqq_u8(s, s2));
830 x = vorrq_u8(x, vcltq_u8(s, s3));
833 uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0);
834 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1);
837 bool escaped =
false;
842 unsigned lz = (unsigned)__builtin_clzll(high);
849 unsigned lz = (unsigned)__builtin_clzll(low);
855 char* q =
reinterpret_cast<char*
>(
os_->PushUnsafe(len));
856 for (
size_t i = 0; i < len; i++)
862 vst1q_u8(reinterpret_cast<uint8_t*>(
os_->PushUnsafe(16)), s);
868 #endif // RAPIDJSON_NEON 872 #if defined(_MSC_VER) || defined(__clang__) 876 #endif // RAPIDJSON_RAPIDJSON_H_
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
char * u64toa(uint64_t value, char *buffer)
bool EndArray(SizeType elementCount=0)
bool EndObject(SizeType memberCount=0)
size_t valueCount
number of values in this level
void Flush()
Flush the output stream.
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
bool inArray
true if in array, otherwise in object
#define RAPIDJSON_ASSERT(x)
Assertion.
bool WriteInt64(int64_t i64)
bool String(const Ch *const &str)
Simpler but slower overload.
bool WriteUint64(uint64_t u64)
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
static const size_t kDefaultLevelDepth
Writer(StackAllocator *allocator=0, size_t levelDepth=kDefaultLevelDepth)
const Ch * src_
Current read position.
bool WriteRawValue(const Ch *json, size_t length)
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
bool Uint64(uint64_t u64)
int GetMaxDecimalPlaces() const
bool Double(double d)
Writes the given double value to the stream.
Validate encoding of JSON strings.
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
bool ScanWriteUnescapedString(GenericStringStream< SourceEncoding > &is, size_t length)
bool String(const Ch *str, SizeType length, bool copy=false)
bool WriteUint(unsigned u)
Information for each nested level.
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
unsigned __int64 uint64_t
bool Key(const Ch *str, SizeType length, bool copy=false)
char * u32toa(uint32_t value, char *buffer)
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
bool WriteString(const Ch *str, SizeType length)
bool IsComplete() const
Checks whether the output is a complete JSON.
WriteFlag
Combination of writeFlags.
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
bool Key(const Ch *const &str)
void Reset(OutputStream &os)
Reset the writer with a new stream.
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
Allow writing of Infinity, -Infinity and NaN.
internal::Stack< StackAllocator > level_stack_
bool WriteDouble(double d)
char * i64toa(int64_t value, char *buffer)
bool RawNumber(const Ch *str, SizeType length, bool copy=false)
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
char * i32toa(int32_t value, char *buffer)
char * dtoa(double value, char *buffer, int maxDecimalPlaces=324)
static const int kDefaultMaxDecimalPlaces
Writer & operator=(const Writer &)
const Ch * head_
Original head of the string.