15#ifndef RAPIDJSON_WRITER_H_
16#define RAPIDJSON_WRITER_H_
19#include "internal/clzll.h"
20#include "internal/meta.h"
21#include "internal/stack.h"
22#include "internal/strfunc.h"
23#include "internal/dtoa.h"
24#include "internal/itoa.h"
25#include "stringbuffer.h"
28#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
30#pragma intrinsic(_BitScanForward)
34#elif defined(RAPIDJSON_SSE2)
36#elif defined(RAPIDJSON_NEON)
42RAPIDJSON_DIAG_OFF(padded)
43RAPIDJSON_DIAG_OFF(unreachable-code)
44RAPIDJSON_DIAG_OFF(c++98-compat)
45#elif defined(_MSC_VER)
47RAPIDJSON_DIAG_OFF(4127)
50RAPIDJSON_NAMESPACE_BEGIN
61#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
62#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
90template<
typename OutputStream,
typename SourceEncoding = UTF8<>,
typename TargetEncoding = UTF8<>,
typename StackAllocator = CrtAllocator,
unsigned writeFlags = kWriteDefaultFlags>
93 typedef typename SourceEncoding::Ch Ch;
95 static const int kDefaultMaxDecimalPlaces = 324;
103 Writer(OutputStream& os, StackAllocator* stackAllocator = 0,
size_t levelDepth = kDefaultLevelDepth) :
104 os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(
Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
107 Writer(StackAllocator* allocator = 0,
size_t levelDepth = kDefaultLevelDepth) :
108 os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
110#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
111 Writer(Writer&& rhs) :
112 os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
138 level_stack_.Clear();
146 return hasRoot_ && level_stack_.Empty();
149 int GetMaxDecimalPlaces()
const {
150 return maxDecimalPlaces_;
175 maxDecimalPlaces_ = maxDecimalPlaces;
183 bool Null() { Prefix(kNullType);
return EndValue(WriteNull()); }
184 bool Bool(
bool b) { Prefix(b ? kTrueType : kFalseType);
return EndValue(WriteBool(b)); }
185 bool Int(
int i) { Prefix(kNumberType);
return EndValue(WriteInt(i)); }
186 bool Uint(
unsigned u) { Prefix(kNumberType);
return EndValue(WriteUint(u)); }
187 bool Int64(int64_t i64) { Prefix(kNumberType);
return EndValue(WriteInt64(i64)); }
188 bool Uint64(uint64_t u64) { Prefix(kNumberType);
return EndValue(WriteUint64(u64)); }
197 bool RawNumber(
const Ch* str,
SizeType length,
bool copy =
false) {
201 return EndValue(WriteString(str, length));
204 bool String(
const Ch* str, SizeType length,
bool copy =
false) {
208 return EndValue(WriteString(str, length));
211#if RAPIDJSON_HAS_STDSTRING
212 bool String(
const std::basic_string<Ch>& str) {
213 return String(str.data(),
SizeType(str.size()));
219 new (level_stack_.template Push<Level>()) Level(
false);
220 return WriteStartObject();
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)
228 return Key(str.data(),
SizeType(str.size()));
232 bool EndObject(SizeType memberCount = 0) {
237 level_stack_.template Pop<Level>(1);
238 return EndValue(WriteEndObject());
243 new (level_stack_.template Push<Level>()) Level(
true);
244 return WriteStartArray();
247 bool EndArray(SizeType elementCount = 0) {
251 level_stack_.template Pop<Level>(1);
252 return EndValue(WriteEndArray());
260 bool String(
const Ch*
const& str) {
return String(str, internal::StrLen(str)); }
261 bool Key(
const Ch*
const& str) {
return Key(str, internal::StrLen(str)); }
276 return EndValue(WriteRawValue(json, length));
287 static const size_t kDefaultLevelDepth = 32;
292 Level(
bool inArray_) : valueCount(0), inArray(inArray_) {}
302 bool WriteBool(
bool b) {
309 PutUnsafe(*os_,
'f'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'l'); PutUnsafe(*os_,
's'); PutUnsafe(*os_,
'e');
314 bool WriteInt(
int i) {
316 const char* end = internal::i32toa(i, buffer);
317 PutReserve(*os_,
static_cast<size_t>(end - buffer));
318 for (
const char* p = buffer; p != end; ++p)
319 PutUnsafe(*os_,
static_cast<typename OutputStream::Ch
>(*p));
323 bool WriteUint(
unsigned u) {
325 const char* end = internal::u32toa(u, buffer);
326 PutReserve(*os_,
static_cast<size_t>(end - buffer));
327 for (
const char* p = buffer; p != end; ++p)
328 PutUnsafe(*os_,
static_cast<typename OutputStream::Ch
>(*p));
332 bool WriteInt64(int64_t i64) {
334 const char* end = internal::i64toa(i64, buffer);
335 PutReserve(*os_,
static_cast<size_t>(end - buffer));
336 for (
const char* p = buffer; p != end; ++p)
337 PutUnsafe(*os_,
static_cast<typename OutputStream::Ch
>(*p));
341 bool WriteUint64(uint64_t u64) {
343 char* end = internal::u64toa(u64, buffer);
344 PutReserve(*os_,
static_cast<size_t>(end - buffer));
345 for (
char* p = buffer; p != end; ++p)
346 PutUnsafe(*os_,
static_cast<typename OutputStream::Ch
>(*p));
350 bool WriteDouble(
double d) {
351 if (internal::Double(d).IsNanOrInf()) {
352 if (!(writeFlags & kWriteNanAndInfFlag) && !(writeFlags & kWriteNanAndInfNullFlag))
354 if (writeFlags & kWriteNanAndInfNullFlag) {
359 if (internal::Double(d).IsNan()) {
364 if (internal::Double(d).Sign()) {
376 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
377 PutReserve(*os_,
static_cast<size_t>(end - buffer));
378 for (
char* p = buffer; p != end; ++p)
379 PutUnsafe(*os_,
static_cast<typename OutputStream::Ch
>(*p));
383 bool WriteString(
const Ch* str, SizeType length) {
384 static const typename OutputStream::Ch hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
385 static const char escape[256] = {
386#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
388 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'b',
't',
'n',
'u',
'f',
'r',
'u',
'u',
389 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
390 0, 0,
'"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
392 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'\\', 0, 0, 0,
393 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
397 if (TargetEncoding::supportUnicode)
403 GenericStringStream<SourceEncoding> is(str);
404 while (ScanWriteUnescapedString(is, length)) {
405 const Ch c = is.Peek();
406 if (!TargetEncoding::supportUnicode &&
static_cast<unsigned>(c) >= 0x80) {
413 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
414 PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
415 PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
416 PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
417 PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
422 unsigned s = codepoint - 0x010000;
423 unsigned lead = (s >> 10) + 0xD800;
424 unsigned trail = (s & 0x3FF) + 0xDC00;
425 PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
426 PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
427 PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
428 PutUnsafe(*os_, hexDigits[(lead ) & 15]);
431 PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
432 PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
433 PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
434 PutUnsafe(*os_, hexDigits[(trail ) & 15]);
437 else if ((
sizeof(Ch) == 1 ||
static_cast<unsigned>(c) < 256) &&
RAPIDJSON_UNLIKELY(escape[
static_cast<unsigned char>(c)])) {
440 PutUnsafe(*os_,
static_cast<typename OutputStream::Ch
>(escape[
static_cast<unsigned char>(c)]));
441 if (escape[
static_cast<unsigned char>(c)] ==
'u') {
444 PutUnsafe(*os_, hexDigits[
static_cast<unsigned char>(c) >> 4]);
445 PutUnsafe(*os_, hexDigits[
static_cast<unsigned char>(c) & 0xF]);
449 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
450 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
457 bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is,
size_t length) {
461 bool WriteStartObject() { os_->Put(
'{');
return true; }
462 bool WriteEndObject() { os_->Put(
'}');
return true; }
463 bool WriteStartArray() { os_->Put(
'[');
return true; }
464 bool WriteEndArray() { os_->Put(
']');
return true; }
466 bool WriteRawValue(
const Ch* json,
size_t length) {
468 GenericStringStream<SourceEncoding> is(json);
472 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
473 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
479 void Prefix(Type type) {
482 Level* level = level_stack_.template Top<Level>();
483 if (level->valueCount > 0) {
487 os_->Put((level->valueCount % 2 == 0) ?
',' :
':');
489 if (!level->inArray && level->valueCount % 2 == 0)
500 bool EndValue(
bool ret) {
507 internal::Stack<StackAllocator> level_stack_;
508 int maxDecimalPlaces_;
513 Writer(
const Writer&);
514 Writer& operator=(
const Writer&);
520inline bool Writer<StringBuffer>::WriteInt(
int i) {
521 char *buffer = os_->Push(11);
522 const char* end = internal::i32toa(i, buffer);
523 os_->Pop(
static_cast<size_t>(11 - (end - buffer)));
528inline bool Writer<StringBuffer>::WriteUint(
unsigned u) {
529 char *buffer = os_->Push(10);
530 const char* end = internal::u32toa(u, buffer);
531 os_->Pop(
static_cast<size_t>(10 - (end - buffer)));
536inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
537 char *buffer = os_->Push(21);
538 const char* end = internal::i64toa(i64, buffer);
539 os_->Pop(
static_cast<size_t>(21 - (end - buffer)));
544inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
545 char *buffer = os_->Push(20);
546 const char* end = internal::u64toa(u, buffer);
547 os_->Pop(
static_cast<size_t>(20 - (end - buffer)));
552inline bool Writer<StringBuffer>::WriteDouble(
double d) {
553 if (internal::Double(d).IsNanOrInf()) {
555 if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
557 if (kWriteDefaultFlags & kWriteNanAndInfNullFlag) {
562 if (internal::Double(d).IsNan()) {
567 if (internal::Double(d).Sign()) {
578 char *buffer = os_->Push(25);
579 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
580 os_->Pop(
static_cast<size_t>(25 - (end - buffer)));
584#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
586inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is,
size_t length) {
593 const char* p = is.src_;
594 const char* end = is.head_ + length;
595 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
596 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) &
static_cast<size_t>(~15));
597 if (nextAligned > end)
600 while (p != nextAligned)
601 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
606 os_->PutUnsafe(*p++);
609 static const char dquote[16] = {
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"' };
610 static const char bslash[16] = {
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\' };
611 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
612 const __m128i dq = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(&dquote[0]));
613 const __m128i bs = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(&bslash[0]));
614 const __m128i sp = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(&space[0]));
616 for (; p != endAligned; p += 16) {
617 const __m128i s = _mm_load_si128(
reinterpret_cast<const __m128i *
>(p));
618 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
619 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
620 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp);
621 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
622 unsigned short r =
static_cast<unsigned short>(_mm_movemask_epi8(x));
626 unsigned long offset;
627 _BitScanForward(&offset, r);
630 len =
static_cast<SizeType>(__builtin_ffs(r) - 1);
632 char* q =
reinterpret_cast<char*
>(os_->PushUnsafe(len));
633 for (
size_t i = 0; i < len; i++)
639 _mm_storeu_si128(
reinterpret_cast<__m128i *
>(os_->PushUnsafe(16)), s);
645#elif defined(RAPIDJSON_NEON)
647inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is,
size_t length) {
654 const char* p = is.src_;
655 const char* end = is.head_ + length;
656 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
657 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) &
static_cast<size_t>(~15));
658 if (nextAligned > end)
661 while (p != nextAligned)
662 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
667 os_->PutUnsafe(*p++);
670 const uint8x16_t s0 = vmovq_n_u8(
'"');
671 const uint8x16_t s1 = vmovq_n_u8(
'\\');
672 const uint8x16_t s2 = vmovq_n_u8(
'\b');
673 const uint8x16_t s3 = vmovq_n_u8(32);
675 for (; p != endAligned; p += 16) {
676 const uint8x16_t s = vld1q_u8(
reinterpret_cast<const uint8_t *
>(p));
677 uint8x16_t x = vceqq_u8(s, s0);
678 x = vorrq_u8(x, vceqq_u8(s, s1));
679 x = vorrq_u8(x, vceqq_u8(s, s2));
680 x = vorrq_u8(x, vcltq_u8(s, s3));
683 uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);
684 uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);
687 bool escaped =
false;
690 uint32_t lz = internal::clzll(high);
695 uint32_t lz = internal::clzll(low);
700 char* q =
reinterpret_cast<char*
>(os_->PushUnsafe(len));
701 for (
size_t i = 0; i < len; i++)
707 vst1q_u8(
reinterpret_cast<uint8_t *
>(os_->PushUnsafe(16)), s);
715RAPIDJSON_NAMESPACE_END
717#if defined(_MSC_VER) || defined(__clang__)
JSON writer.
Definition writer.h:91
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition writer.h:145
void Flush()
Flush the output stream.
Definition writer.h:283
bool String(const Ch *const &str)
Simpler but slower overload.
Definition writer.h:260
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition writer.h:273
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition writer.h:103
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition writer.h:174
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition writer.h:135
bool Double(double d)
Writes the given double value to the stream.
Definition writer.h:195
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
User-defined kWriteDefaultFlags definition.
Definition writer.h:62
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition rapidjson.h:494
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition rapidjson.h:507
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition rapidjson.h:437
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
Definition stream.h:91
unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition rapidjson.h:415
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
Definition stream.h:84
WriteFlag
Combination of writeFlags.
Definition writer.h:66
@ kWriteNanAndInfFlag
Allow writing of Infinity, -Infinity and NaN.
Definition writer.h:69
@ kWriteNanAndInfNullFlag
Allow writing of Infinity, -Infinity and NaN as null.
Definition writer.h:70
@ kWriteDefaultFlags
Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS.
Definition writer.h:71
@ kWriteValidateEncodingFlag
Validate encoding of JSON strings.
Definition writer.h:68
@ kWriteNoFlags
No flags are set.
Definition writer.h:67
Type
Type of JSON value.
Definition rapidjson.h:729
@ kNumberType
number
Definition rapidjson.h:736
Information for each nested level.
Definition writer.h:291
bool inArray
true if in array, otherwise in object
Definition writer.h:294
size_t valueCount
number of values in this level
Definition writer.h:293