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(4127)
46 RAPIDJSON_DIAG_OFF(padded)
47 RAPIDJSON_DIAG_OFF(unreachable-code)
48 RAPIDJSON_DIAG_OFF(c++98-compat)
62 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS 63 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags 90 template<
typename OutputStream,
typename SourceEncoding = UTF8<>,
typename TargetEncoding = UTF8<>,
typename StackAllocator = CrtAllocator,
unsigned writeFlags = kWriteDefaultFlags>
93 typedef typename SourceEncoding::Ch
Ch;
110 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 211 #if RAPIDJSON_HAS_STDSTRING 212 bool String(
const std::basic_string<Ch>& str) {
223 bool Key(
const Ch* str,
SizeType length,
bool copy =
false) {
return String(str, length, copy); }
225 #if RAPIDJSON_HAS_STDSTRING 226 bool Key(
const std::basic_string<Ch>& str)
318 for (
const char* p = buffer; p != end; ++p)
319 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
327 for (
const char* p = buffer; p != end; ++p)
328 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
336 for (
const char* p = buffer; p != end; ++p)
337 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
345 for (
char* p = buffer; p != end; ++p)
346 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
373 for (
char* p = buffer; p != end; ++p)
374 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(*p));
379 static const typename OutputStream::Ch hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
380 static const char escape[256] = {
381 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 383 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'b',
't',
'n',
'u',
'f',
'r',
'u',
'u',
384 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
385 0, 0,
'"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
387 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'\\', 0, 0, 0,
392 if (TargetEncoding::supportUnicode)
400 const Ch c = is.
Peek();
401 if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
408 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
417 unsigned s = codepoint - 0x010000;
418 unsigned lead = (s >> 10) + 0xD800;
419 unsigned trail = (s & 0x3FF) + 0xDC00;
432 else if ((
sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) &&
RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
435 PutUnsafe(*
os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
436 if (escape[static_cast<unsigned char>(c)] ==
'u') {
439 PutUnsafe(*
os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
440 PutUnsafe(*
os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
463 for (
size_t i = 0; i < length; i++) {
474 if (level->valueCount > 0) {
478 os_->Put((level->valueCount % 2 == 0) ?
',' :
':');
480 if (!level->inArray && level->valueCount % 2 == 0)
512 char *buffer =
os_->Push(11);
514 os_->Pop(static_cast<size_t>(11 - (end - buffer)));
520 char *buffer =
os_->Push(10);
522 os_->Pop(static_cast<size_t>(10 - (end - buffer)));
528 char *buffer =
os_->Push(21);
530 os_->Pop(static_cast<size_t>(21 - (end - buffer)));
536 char *buffer =
os_->Push(20);
538 os_->Pop(static_cast<size_t>(20 - (end - buffer)));
564 char *buffer =
os_->Push(25);
566 os_->Pop(static_cast<size_t>(25 - (end - buffer)));
570 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) 579 const char* p = is.
src_;
580 const char* end = is.
head_ + length;
581 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
582 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
583 if (nextAligned > end)
586 while (p != nextAligned)
587 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
592 os_->PutUnsafe(*p++);
595 static const char dquote[16] = {
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"' };
596 static const char bslash[16] = {
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\' };
597 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
598 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
599 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
600 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
602 for (; p != endAligned; p += 16) {
603 const __m128i
s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
604 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
605 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
606 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp);
607 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
608 unsigned short r =
static_cast<unsigned short>(_mm_movemask_epi8(x));
611 #ifdef _MSC_VER // Find the index of first escaped 612 unsigned long offset;
613 _BitScanForward(&offset, r);
616 len =
static_cast<SizeType>(__builtin_ffs(r) - 1);
618 char* q =
reinterpret_cast<char*
>(
os_->PushUnsafe(len));
619 for (
size_t i = 0; i < len; i++)
625 _mm_storeu_si128(reinterpret_cast<__m128i *>(
os_->PushUnsafe(16)), s);
631 #elif defined(RAPIDJSON_NEON) 640 const char* p = is.
src_;
641 const char* end = is.
head_ + length;
642 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
643 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
644 if (nextAligned > end)
647 while (p != nextAligned)
648 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
653 os_->PutUnsafe(*p++);
656 const uint8x16_t s0 = vmovq_n_u8(
'"');
657 const uint8x16_t s1 = vmovq_n_u8(
'\\');
658 const uint8x16_t s2 = vmovq_n_u8(
'\b');
659 const uint8x16_t s3 = vmovq_n_u8(32);
661 for (; p != endAligned; p += 16) {
662 const uint8x16_t
s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
663 uint8x16_t x = vceqq_u8(s, s0);
664 x = vorrq_u8(x, vceqq_u8(s, s1));
665 x = vorrq_u8(x, vceqq_u8(s, s2));
666 x = vorrq_u8(x, vcltq_u8(s, s3));
669 uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0);
670 uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1);
673 bool escaped =
false;
676 unsigned lz = (unsigned)__builtin_clzll(high);
681 unsigned lz = (unsigned)__builtin_clzll(low);
686 char* q =
reinterpret_cast<char*
>(
os_->PushUnsafe(len));
687 for (
size_t i = 0; i < len; i++)
693 vst1q_u8(reinterpret_cast<uint8_t *>(
os_->PushUnsafe(16)), s);
699 #endif // RAPIDJSON_NEON 711 #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
Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS. ...
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.