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)
32 #ifdef RAPIDJSON_SSE42
33 #include <nmmintrin.h>
34 #elif defined(RAPIDJSON_SSE2)
35 #include <emmintrin.h>
36 #elif defined(RAPIDJSON_NEON)
42 RAPIDJSON_DIAG_OFF(padded)
43 RAPIDJSON_DIAG_OFF(unreachable-code)
44 RAPIDJSON_DIAG_OFF(c++98-compat)
45 #elif defined(_MSC_VER)
47 RAPIDJSON_DIAG_OFF(4127)
50 RAPIDJSON_NAMESPACE_BEGIN
61 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
62 #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;
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()); }
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&);
520 inline 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)));
528 inline 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)));
536 inline 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)));
544 inline 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)));
552 inline 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)
586 inline 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));
625 #ifdef _MSC_VER // Find the index of first escaped
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)
647 inline 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);
713 #endif // RAPIDJSON_NEON
715 RAPIDJSON_NAMESPACE_END
717 #if defined(_MSC_VER) || defined(__clang__)
721 #endif // RAPIDJSON_RAPIDJSON_H_
true
Definition: rapidjson.h:732
bool inArray
true if in array, otherwise in object
Definition: writer.h:294
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition: writer.h:174
No flags are set.
Definition: writer.h:67
Validate encoding of JSON strings.
Definition: writer.h:68
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
Definition: stream.h:84
unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:415
bool String(const Ch *const &str)
Simpler but slower overload.
Definition: writer.h:260
WriteFlag
Combination of writeFlags.
Definition: writer.h:66
false
Definition: rapidjson.h:731
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:273
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:494
Information for each nested level.
Definition: writer.h:291
size_t valueCount
number of values in this level
Definition: writer.h:293
Type
Type of JSON value.
Definition: rapidjson.h:729
object
Definition: rapidjson.h:733
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:507
array
Definition: rapidjson.h:734
JSON writer.
Definition: fwd.h:95
null
Definition: rapidjson.h:730
string
Definition: rapidjson.h:735
Allow writing of Infinity, -Infinity and NaN as null.
Definition: writer.h:70
Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS. ...
Definition: writer.h:71
void Flush()
Flush the output stream.
Definition: writer.h:283
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
User-defined kWriteDefaultFlags definition.
Definition: writer.h:62
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:145
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:195
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
Definition: stream.h:91
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:103
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:437
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:135
number
Definition: rapidjson.h:736
Allow writing of Infinity, -Infinity and NaN.
Definition: writer.h:69