19 #ifndef RAPIDJSON_WRITER_H_ 20 #define RAPIDJSON_WRITER_H_ 32 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) 34 #pragma intrinsic(_BitScanForward) 36 #ifdef RAPIDJSON_SSE42 37 #include <nmmintrin.h> 38 #elif defined(RAPIDJSON_SSE2) 39 #include <emmintrin.h> 40 #elif defined(RAPIDJSON_NEON) 46 RAPIDJSON_DIAG_OFF(padded)
47 RAPIDJSON_DIAG_OFF(unreachable - code)
48 RAPIDJSON_DIAG_OFF(c++ 98 - compat)
49 #elif defined(_MSC_VER) 51 RAPIDJSON_DIAG_OFF(4127)
65 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS 66 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags 98 template <
typename OutputStream,
typename SourceEncoding = UTF8<>,
99 typename TargetEncoding = UTF8<>,
100 typename StackAllocator = CrtAllocator,
101 unsigned writeFlags = kWriteDefaultFlags>
104 typedef typename SourceEncoding::Ch
Ch;
113 explicit Writer(OutputStream &os, StackAllocator *stackAllocator = 0,
120 explicit Writer(StackAllocator *allocator = 0,
127 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 249 #if RAPIDJSON_HAS_STDSTRING 250 bool String(
const std::basic_string<Ch> &str) {
262 return String(str, length, copy);
265 #if RAPIDJSON_HAS_STDSTRING 266 bool Key(
const std::basic_string<Ch> &str) {
371 for (
const char *p = buffer; p != end; ++p)
372 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
380 for (
const char *p = buffer; p != end; ++p)
381 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
389 for (
const char *p = buffer; p != end; ++p)
390 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
398 for (
char *p = buffer; p != end; ++p)
399 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));
438 static const typename OutputStream::Ch hexDigits[16] = {
439 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
440 '8',
'9',
'A',
'B',
'C',
'D',
'E',
'F'};
441 static const char escape[256] = {
442 #define Z16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 445 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'b',
't',
446 'n',
'u',
'f',
'r',
'u',
'u',
447 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
448 'u',
'u',
'u',
'u',
'u',
'u',
449 0, 0,
'"', 0, 0, 0, 0, 0, 0, 0,
452 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
458 if (TargetEncoding::supportUnicode)
466 const Ch c = is.
Peek();
467 if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
474 if (codepoint <= 0xD7FF ||
475 (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
483 unsigned s = codepoint - 0x010000;
484 unsigned lead = (s >> 10) + 0xD800;
485 unsigned trail = (s & 0x3FF) + 0xDC00;
497 }
else if ((
sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) &&
502 escape[static_cast<unsigned char>(c)]));
503 if (escape[static_cast<unsigned char>(c)] ==
'u') {
506 PutUnsafe(*
os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
507 PutUnsafe(*
os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
514 TargetEncoding>::TranscodeUnsafe(is,
603 char *buffer =
os_->Push(11);
605 os_->Pop(static_cast<size_t>(11 - (end - buffer)));
611 char *buffer =
os_->Push(10);
613 os_->Pop(static_cast<size_t>(10 - (end - buffer)));
619 char *buffer =
os_->Push(21);
621 os_->Pop(static_cast<size_t>(21 - (end - buffer)));
627 char *buffer =
os_->Push(20);
629 os_->Pop(static_cast<size_t>(20 - (end - buffer)));
662 char *buffer =
os_->Push(25);
664 os_->Pop(static_cast<size_t>(25 - (end - buffer)));
668 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) 676 const char *p = is.
src_;
677 const char *end = is.
head_ + length;
678 const char *nextAligned =
reinterpret_cast<const char *
>(
679 (
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
680 const char *endAligned =
reinterpret_cast<const char *
>(
681 reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
682 if (nextAligned > end)
return true;
684 while (p != nextAligned)
685 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
689 os_->PutUnsafe(*p++);
692 static const char dquote[16] = {
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
693 '\"',
'\"',
'\"',
'\"',
'\"',
'\"',
694 '\"',
'\"',
'\"',
'\"'};
695 static const char bslash[16] = {
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
696 '\\',
'\\',
'\\',
'\\',
'\\',
'\\',
697 '\\',
'\\',
'\\',
'\\'};
698 static const char space[16] = {0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
699 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
700 0x1F, 0x1F, 0x1F, 0x1F};
702 _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
704 _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
706 _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
708 for (; p != endAligned; p += 16) {
709 const __m128i
s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
710 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
711 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
712 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp),
714 const __m128i
x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
715 unsigned short r =
static_cast<unsigned short>(_mm_movemask_epi8(x));
718 #ifdef _MSC_VER // Find the index of first escaped 719 unsigned long offset;
720 _BitScanForward(&offset, r);
723 len =
static_cast<SizeType>(__builtin_ffs(r) - 1);
725 char *q =
reinterpret_cast<char *
>(
os_->PushUnsafe(len));
726 for (
size_t i = 0; i < len; i++) q[i] = p[i];
731 _mm_storeu_si128(reinterpret_cast<__m128i *>(
os_->PushUnsafe(16)), s);
737 #elif defined(RAPIDJSON_NEON) 745 const char *p = is.
src_;
746 const char *end = is.
head_ + length;
747 const char *nextAligned =
reinterpret_cast<const char *
>(
748 (
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
749 const char *endAligned =
reinterpret_cast<const char *
>(
750 reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
751 if (nextAligned > end)
return true;
753 while (p != nextAligned)
754 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
758 os_->PutUnsafe(*p++);
761 const uint8x16_t s0 = vmovq_n_u8(
'"');
762 const uint8x16_t s1 = vmovq_n_u8(
'\\');
763 const uint8x16_t s2 = vmovq_n_u8(
'\b');
764 const uint8x16_t s3 = vmovq_n_u8(32);
766 for (; p != endAligned; p += 16) {
767 const uint8x16_t
s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
768 uint8x16_t
x = vceqq_u8(s, s0);
769 x = vorrq_u8(x, vceqq_u8(s, s1));
770 x = vorrq_u8(x, vceqq_u8(s, s2));
771 x = vorrq_u8(x, vcltq_u8(s, s3));
774 uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);
775 uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);
778 bool escaped =
false;
791 char *q =
reinterpret_cast<char *
>(
os_->PushUnsafe(len));
792 for (
size_t i = 0; i < len; i++) q[i] = p[i];
797 vst1q_u8(reinterpret_cast<uint8_t *>(
os_->PushUnsafe(16)), s);
803 #endif // RAPIDJSON_NEON 807 #if defined(_MSC_VER) || defined(__clang__) 811 #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
TFSIMD_FORCE_INLINE const tfScalar & x() const
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.
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
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.