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)
61 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS 62 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags 68 kWriteValidateEncodingFlag = 1,
69 kWriteNanAndInfFlag = 2,
70 kWriteNanAndInfNullFlag = 4,
71 kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS
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 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;
299 PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'u'); PutUnsafe(*os_,
'l'); PutUnsafe(*os_,
'l');
return true;
302 bool WriteBool(
bool b) {
305 PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'r'); PutUnsafe(*os_,
'u'); PutUnsafe(*os_,
'e');
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) {
352 if (!(writeFlags & kWriteNanAndInfFlag))
354 if (writeFlags & kWriteNanAndInfNullFlag) {
356 PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'u'); PutUnsafe(*os_,
'l'); PutUnsafe(*os_,
'l');
361 PutUnsafe(*os_,
'N'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'N');
366 PutUnsafe(*os_,
'-');
370 PutUnsafe(*os_,
'I'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'f');
371 PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'y');
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)
398 PutReserve(*os_, 2 + length * 6);
400 PutReserve(*os_, 2 + length * 12);
402 PutUnsafe(*os_,
'\"');
404 while (ScanWriteUnescapedString(is, length)) {
405 const Ch c = is.Peek();
406 if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
411 PutUnsafe(*os_,
'\\');
412 PutUnsafe(*os_,
'u');
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]);
429 PutUnsafe(*os_,
'\\');
430 PutUnsafe(*os_,
'u');
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)])) {
439 PutUnsafe(*os_,
'\\');
440 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
441 if (escape[static_cast<unsigned char>(c)] ==
'u') {
442 PutUnsafe(*os_,
'0');
443 PutUnsafe(*os_,
'0');
444 PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
445 PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
453 PutUnsafe(*os_,
'\"');
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) {
467 PutReserve(*os_, length);
479 void Prefix(
Type type) {
482 Level* level = level_stack_.template Top<Level>();
487 os_->Put((level->
valueCount % 2 == 0) ?
',' :
':');
500 bool EndValue(
bool ret) {
508 int maxDecimalPlaces_;
521 char *buffer = os_->Push(11);
522 const char* end = internal::i32toa(i, buffer);
523 os_->Pop(static_cast<size_t>(11 - (end - buffer)));
529 char *buffer = os_->Push(10);
530 const char* end = internal::u32toa(u, buffer);
531 os_->Pop(static_cast<size_t>(10 - (end - buffer)));
537 char *buffer = os_->Push(21);
538 const char* end = internal::i64toa(i64, buffer);
539 os_->Pop(static_cast<size_t>(21 - (end - buffer)));
545 char *buffer = os_->Push(20);
546 const char* end = internal::u64toa(u, buffer);
547 os_->Pop(static_cast<size_t>(20 - (end - buffer)));
555 if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
557 if (kWriteDefaultFlags & kWriteNanAndInfNullFlag) {
559 PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'u'); PutUnsafe(*os_,
'l'); PutUnsafe(*os_,
'l');
564 PutUnsafe(*os_,
'N'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'N');
569 PutUnsafe(*os_,
'-');
573 PutUnsafe(*os_,
'I'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'f');
574 PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'y');
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) 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) 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 717 #if defined(_MSC_VER) || defined(__clang__) 721 #endif // RAPIDJSON_RAPIDJSON_H_ Encoding conversion.
Definition: encodings.h:658
size_t valueCount
number of values in this level
Definition: writer.h:293
void Flush()
Flush the output stream.
Definition: writer.h:283
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:415
bool inArray
true if in array, otherwise in object
Definition: writer.h:294
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:437
bool String(const Ch *const &str)
Simpler but slower overload.
Definition: writer.h:260
JSON writer.
Definition: fwd.h:95
object
Definition: rapidjson.h:733
Read-only string stream.
Definition: fwd.h:47
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:124
array
Definition: rapidjson.h:734
const Ch * src_
Current read position.
Definition: stream.h:168
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:273
false
Definition: rapidjson.h:731
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:195
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:121
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:145
Information for each nested level.
Definition: writer.h:291
string
Definition: rapidjson.h:735
number
Definition: rapidjson.h:736
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:494
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
true
Definition: rapidjson.h:732
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:135
Type
Type of JSON value.
Definition: rapidjson.h:729
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:507
null
Definition: rapidjson.h:730
const Ch * head_
Original head of the string.
Definition: stream.h:169