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)
61#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
62#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
68 kWriteValidateEncodingFlag = 1,
69 kWriteNanAndInfFlag = 2,
70 kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS
89template<
typename OutputStream,
typename SourceEncoding = UTF8<>,
typename TargetEncoding = UTF8<>,
typename StackAllocator = CrtAllocator,
unsigned writeFlags = kWriteDefaultFlags>
92 typedef typename SourceEncoding::Ch Ch;
94 static const int kDefaultMaxDecimalPlaces = 324;
102 Writer(OutputStream& os, StackAllocator* stackAllocator = 0,
size_t levelDepth = kDefaultLevelDepth) :
103 os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(
Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
106 Writer(StackAllocator* allocator = 0,
size_t levelDepth = kDefaultLevelDepth) :
107 os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
109#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
111 os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
137 level_stack_.Clear();
145 return hasRoot_ && level_stack_.Empty();
148 int GetMaxDecimalPlaces()
const {
149 return maxDecimalPlaces_;
174 maxDecimalPlaces_ = maxDecimalPlaces;
182 bool Null() { Prefix(
kNullType);
return EndValue(WriteNull()); }
184 bool Int(
int i) { Prefix(
kNumberType);
return EndValue(WriteInt(i)); }
185 bool Uint(
unsigned u) { Prefix(
kNumberType);
return EndValue(WriteUint(u)); }
186 bool Int64(int64_t i64) { Prefix(
kNumberType);
return EndValue(WriteInt64(i64)); }
187 bool Uint64(uint64_t u64) { Prefix(
kNumberType);
return EndValue(WriteUint64(u64)); }
196 bool RawNumber(
const Ch* str,
SizeType length,
bool copy =
false) {
200 return EndValue(WriteString(str, length));
203 bool String(
const Ch* str,
SizeType length,
bool copy =
false) {
207 return EndValue(WriteString(str, length));
210#if RAPIDJSON_HAS_STDSTRING
211 bool String(
const std::basic_string<Ch>& str) {
212 return String(str.data(),
SizeType(str.size()));
218 new (level_stack_.template Push<Level>()) Level(
false);
219 return WriteStartObject();
222 bool Key(
const Ch* str,
SizeType length,
bool copy =
false) {
return String(str, length, copy); }
224#if RAPIDJSON_HAS_STDSTRING
225 bool Key(
const std::basic_string<Ch>& str)
227 return Key(str.data(),
SizeType(str.size()));
231 bool EndObject(
SizeType memberCount = 0) {
236 level_stack_.template Pop<Level>(1);
237 return EndValue(WriteEndObject());
242 new (level_stack_.template Push<Level>()) Level(
true);
243 return WriteStartArray();
246 bool EndArray(
SizeType elementCount = 0) {
250 level_stack_.template Pop<Level>(1);
251 return EndValue(WriteEndArray());
259 bool String(
const Ch*
const& str) {
return String(str, internal::StrLen(str)); }
260 bool Key(
const Ch*
const& str) {
return Key(str, internal::StrLen(str)); }
275 return EndValue(WriteRawValue(json, length));
286 static const size_t kDefaultLevelDepth = 32;
298 PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'u'); PutUnsafe(*os_,
'l'); PutUnsafe(*os_,
'l');
return true;
301 bool WriteBool(
bool b) {
304 PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'r'); PutUnsafe(*os_,
'u'); PutUnsafe(*os_,
'e');
308 PutUnsafe(*os_,
'f'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'l'); PutUnsafe(*os_,
's'); PutUnsafe(*os_,
'e');
313 bool WriteInt(
int i) {
315 const char* end = internal::i32toa(i, buffer);
316 PutReserve(*os_,
static_cast<size_t>(end - buffer));
317 for (
const char* p = buffer; p != end; ++p)
318 PutUnsafe(*os_,
static_cast<typename OutputStream::Ch
>(*p));
322 bool WriteUint(
unsigned u) {
324 const char* end = internal::u32toa(u, buffer);
325 PutReserve(*os_,
static_cast<size_t>(end - buffer));
326 for (
const char* p = buffer; p != end; ++p)
327 PutUnsafe(*os_,
static_cast<typename OutputStream::Ch
>(*p));
331 bool WriteInt64(int64_t i64) {
333 const char* end = internal::i64toa(i64, buffer);
334 PutReserve(*os_,
static_cast<size_t>(end - buffer));
335 for (
const char* p = buffer; p != end; ++p)
336 PutUnsafe(*os_,
static_cast<typename OutputStream::Ch
>(*p));
340 bool WriteUint64(uint64_t u64) {
342 char* end = internal::u64toa(u64, buffer);
343 PutReserve(*os_,
static_cast<size_t>(end - buffer));
344 for (
char* p = buffer; p != end; ++p)
345 PutUnsafe(*os_,
static_cast<typename OutputStream::Ch
>(*p));
349 bool WriteDouble(
double d) {
351 if (!(writeFlags & kWriteNanAndInfFlag))
355 PutUnsafe(*os_,
'N'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'N');
360 PutUnsafe(*os_,
'-');
364 PutUnsafe(*os_,
'I'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'f');
365 PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'y');
370 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
371 PutReserve(*os_,
static_cast<size_t>(end - buffer));
372 for (
char* p = buffer; p != end; ++p)
373 PutUnsafe(*os_,
static_cast<typename OutputStream::Ch
>(*p));
377 bool WriteString(
const Ch* str,
SizeType length) {
378 static const typename OutputStream::Ch hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
379 static const char escape[256] = {
380#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
382 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'b',
't',
'n',
'u',
'f',
'r',
'u',
'u',
383 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
384 0, 0,
'"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
386 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'\\', 0, 0, 0,
387 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
391 if (TargetEncoding::supportUnicode)
392 PutReserve(*os_, 2 + length * 6);
394 PutReserve(*os_, 2 + length * 12);
396 PutUnsafe(*os_,
'\"');
398 while (ScanWriteUnescapedString(is, length)) {
399 const Ch c = is.Peek();
400 if (!TargetEncoding::supportUnicode &&
static_cast<unsigned>(c) >= 0x80) {
405 PutUnsafe(*os_,
'\\');
406 PutUnsafe(*os_,
'u');
407 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
408 PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
409 PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
410 PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
411 PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
416 unsigned s = codepoint - 0x010000;
417 unsigned lead = (s >> 10) + 0xD800;
418 unsigned trail = (s & 0x3FF) + 0xDC00;
419 PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
420 PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
421 PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
422 PutUnsafe(*os_, hexDigits[(lead ) & 15]);
423 PutUnsafe(*os_,
'\\');
424 PutUnsafe(*os_,
'u');
425 PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
426 PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
427 PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
428 PutUnsafe(*os_, hexDigits[(trail ) & 15]);
431 else if ((
sizeof(Ch) == 1 ||
static_cast<unsigned>(c) < 256) &&
RAPIDJSON_UNLIKELY(escape[
static_cast<unsigned char>(c)])) {
433 PutUnsafe(*os_,
'\\');
434 PutUnsafe(*os_,
static_cast<typename OutputStream::Ch
>(escape[
static_cast<unsigned char>(c)]));
435 if (escape[
static_cast<unsigned char>(c)] ==
'u') {
436 PutUnsafe(*os_,
'0');
437 PutUnsafe(*os_,
'0');
438 PutUnsafe(*os_, hexDigits[
static_cast<unsigned char>(c) >> 4]);
439 PutUnsafe(*os_, hexDigits[
static_cast<unsigned char>(c) & 0xF]);
447 PutUnsafe(*os_,
'\"');
455 bool WriteStartObject() { os_->Put(
'{');
return true; }
456 bool WriteEndObject() { os_->Put(
'}');
return true; }
457 bool WriteStartArray() { os_->Put(
'[');
return true; }
458 bool WriteEndArray() { os_->Put(
']');
return true; }
460 bool WriteRawValue(
const Ch* json,
size_t length) {
461 PutReserve(*os_, length);
473 void Prefix(
Type type) {
476 Level* level = level_stack_.template Top<Level>();
477 if (level->valueCount > 0) {
481 os_->Put((level->valueCount % 2 == 0) ?
',' :
':');
483 if (!level->inArray && level->valueCount % 2 == 0)
494 bool EndValue(
bool ret) {
502 int maxDecimalPlaces_;
515 char *buffer = os_->Push(11);
516 const char* end = internal::i32toa(i, buffer);
517 os_->Pop(
static_cast<size_t>(11 - (end - buffer)));
523 char *buffer = os_->Push(10);
524 const char* end = internal::u32toa(u, buffer);
525 os_->Pop(
static_cast<size_t>(10 - (end - buffer)));
531 char *buffer = os_->Push(21);
532 const char* end = internal::i64toa(i64, buffer);
533 os_->Pop(
static_cast<size_t>(21 - (end - buffer)));
539 char *buffer = os_->Push(20);
540 const char* end = internal::u64toa(u, buffer);
541 os_->Pop(
static_cast<size_t>(20 - (end - buffer)));
549 if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
553 PutUnsafe(*os_,
'N'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'N');
558 PutUnsafe(*os_,
'-');
562 PutUnsafe(*os_,
'I'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'f');
563 PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'y');
567 char *buffer = os_->Push(25);
568 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
569 os_->Pop(
static_cast<size_t>(25 - (end - buffer)));
573#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
582 const char* p = is.
src_;
583 const char* end = is.
head_ + length;
584 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
585 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) &
static_cast<size_t>(~15));
586 if (nextAligned > end)
589 while (p != nextAligned)
590 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
595 os_->PutUnsafe(*p++);
598 static const char dquote[16] = {
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"' };
599 static const char bslash[16] = {
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\' };
600 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
601 const __m128i dq = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(dquote.data()));
602 const __m128i bs = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(bslash.data()));
603 const __m128i sp = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(space.data()));
605 for (; p != endAligned; p += 16) {
606 const __m128i s = _mm_load_si128(
reinterpret_cast<const __m128i *
>(p));
607 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
608 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
609 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp);
610 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
611 unsigned short r =
static_cast<unsigned short>(_mm_movemask_epi8(x));
615 unsigned long offset;
616 _BitScanForward(&offset, r);
619 len =
static_cast<SizeType>(__builtin_ffs(r) - 1);
621 char* q =
reinterpret_cast<char*
>(os_->PushUnsafe(len));
622 for (
size_t i = 0; i < len; i++)
628 _mm_storeu_si128(
reinterpret_cast<__m128i *
>(os_->PushUnsafe(16)), s);
634#elif defined(RAPIDJSON_NEON)
643 const char* p = is.
src_;
644 const char* end = is.
head_ + length;
645 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
646 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) &
static_cast<size_t>(~15));
647 if (nextAligned > end)
650 while (p != nextAligned)
651 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
656 os_->PutUnsafe(*p++);
659 const uint8x16_t s0 = vmovq_n_u8(
'"');
660 const uint8x16_t s1 = vmovq_n_u8(
'\\');
661 const uint8x16_t s2 = vmovq_n_u8(
'\b');
662 const uint8x16_t s3 = vmovq_n_u8(32);
664 for (; p != endAligned; p += 16) {
665 const uint8x16_t s = vld1q_u8(
reinterpret_cast<const uint8_t *
>(p));
666 uint8x16_t x = vceqq_u8(s, s0);
667 x = vorrq_u8(x, vceqq_u8(s, s1));
668 x = vorrq_u8(x, vceqq_u8(s, s2));
669 x = vorrq_u8(x, vcltq_u8(s, s3));
672 uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);
673 uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);
676 bool escaped =
false;
679 uint32_t lz = internal::clzll(high);
684 uint32_t lz = internal::clzll(low);
689 char* q =
reinterpret_cast<char*
>(os_->PushUnsafe(len));
690 for (
size_t i = 0; i < len; i++)
696 vst1q_u8(
reinterpret_cast<uint8_t *
>(os_->PushUnsafe(16)), s);
706#if defined(_MSC_VER) || defined(__clang__)
bool IsComplete() const
Checks whether the output is a complete JSON.
bool Double(double d)
Writes the given double value to the stream.
bool String(const Ch *const &str)
Simpler but slower overload.
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
void Reset(OutputStream &os)
Reset the writer with a new stream.
void Flush()
Flush the output stream.
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
A type-unsafe stack for storing different types of data.
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
#define RAPIDJSON_ASSERT(x)
Assertion.
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
const Ch * head_
Original head of the string.
const Ch * src_
Current read position.
Information for each nested level.
size_t valueCount
number of values in this level
bool inArray
true if in array, otherwise in object