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 kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS
89 template<
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()); }
183 bool Bool(
bool b) { Prefix(b ? kTrueType : kFalseType);
return EndValue(WriteBool(b)); }
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)); }
194 bool Double(
double d) { Prefix(kNumberType);
return EndValue(WriteDouble(d)); }
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,
bool raw =
false) {
207 return EndValue(WriteString(str, length, raw));
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)); }
272 bool RawValue(
const Ch* json,
size_t length, Type type) {
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,
bool raw) {
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);
398 PutUnsafe(*os_,
'\"');
401 while (ScanWriteUnescapedString(is, length)) {
402 const Ch c = is.Peek();
403 if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
408 PutUnsafe(*os_,
'\\');
409 PutUnsafe(*os_,
'u');
410 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
411 PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
412 PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
413 PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
414 PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
419 unsigned s = codepoint - 0x010000;
420 unsigned lead = (s >> 10) + 0xD800;
421 unsigned trail = (s & 0x3FF) + 0xDC00;
422 PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
423 PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
424 PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
425 PutUnsafe(*os_, hexDigits[(lead ) & 15]);
426 PutUnsafe(*os_,
'\\');
427 PutUnsafe(*os_,
'u');
428 PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
429 PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
430 PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
431 PutUnsafe(*os_, hexDigits[(trail ) & 15]);
434 else if ((
sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) &&
RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
436 PutUnsafe(*os_,
'\\');
437 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
438 if (escape[static_cast<unsigned char>(c)] ==
'u') {
439 PutUnsafe(*os_,
'0');
440 PutUnsafe(*os_,
'0');
441 PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
442 PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
452 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))
559 PutUnsafe(*os_,
'N'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'N');
564 PutUnsafe(*os_,
'-');
568 PutUnsafe(*os_,
'I'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'f');
569 PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'y');
573 char *
buffer = os_->Push(25);
574 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
575 os_->Pop(static_cast<size_t>(25 - (end - buffer)));
579 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) 588 const char* p = is.
src_;
589 const char* end = is.
head_ + length;
590 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
591 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
592 if (nextAligned > end)
595 while (p != nextAligned)
596 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
601 os_->PutUnsafe(*p++);
604 static const char dquote[16] = {
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"' };
605 static const char bslash[16] = {
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\' };
606 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
607 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
608 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
609 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
611 for (; p != endAligned; p += 16) {
612 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
613 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
614 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
615 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp);
616 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
617 unsigned short r =
static_cast<unsigned short>(_mm_movemask_epi8(x));
620 #ifdef _MSC_VER // Find the index of first escaped 621 unsigned long offset;
622 _BitScanForward(&offset, r);
625 len =
static_cast<SizeType
>(__builtin_ffs(r) - 1);
627 char* q =
reinterpret_cast<char*
>(os_->PushUnsafe(len));
628 for (
size_t i = 0; i < len; i++)
634 _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
640 #elif defined(RAPIDJSON_NEON) 649 const char* p = is.
src_;
650 const char* end = is.
head_ + length;
651 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
652 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
653 if (nextAligned > end)
656 while (p != nextAligned)
657 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
662 os_->PutUnsafe(*p++);
665 const uint8x16_t s0 = vmovq_n_u8(
'"');
666 const uint8x16_t s1 = vmovq_n_u8(
'\\');
667 const uint8x16_t s2 = vmovq_n_u8(
'\b');
668 const uint8x16_t s3 = vmovq_n_u8(32);
670 for (; p != endAligned; p += 16) {
671 const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
672 uint8x16_t x = vceqq_u8(s, s0);
673 x = vorrq_u8(x, vceqq_u8(s, s1));
674 x = vorrq_u8(x, vceqq_u8(s, s2));
675 x = vorrq_u8(x, vcltq_u8(s, s3));
678 uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);
679 uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);
682 bool escaped =
false;
685 uint32_t lz = internal::clzll(high);
690 uint32_t lz = internal::clzll(low);
695 char* q =
reinterpret_cast<char*
>(os_->PushUnsafe(len));
696 for (
size_t i = 0; i < len; i++)
702 vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
708 #endif // RAPIDJSON_NEON 712 #if defined(_MSC_VER) || defined(__clang__) 716 #endif // RAPIDJSON_RAPIDJSON_H_ size_t valueCount
number of values in this level
Definition: writer.h:292
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:121
JSON writer.
Definition: fwd.h:95
void Flush()
Flush the output stream.
Definition: writer.h:282
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:494
Encoding conversion.
Definition: encodings.h:658
A contiguous memory buffer with an optional growing ability.
Definition: core.h:778
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:102
const Ch * src_
Current read position.
Definition: stream.h:168
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:144
Read-only string stream.
Definition: fwd.h:47
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:507
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:124
const Ch * head_
Original head of the string.
Definition: stream.h:169
Information for each nested level.
Definition: writer.h:290
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:134
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition: writer.h:173
bool String(const Ch *const &str)
Simpler but slower overload.
Definition: writer.h:259
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:272
bool inArray
true if in array, otherwise in object
Definition: writer.h:293
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:437
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:194