15 #ifndef RAPIDJSON_WRITER_H_
16 #define RAPIDJSON_WRITER_H_
19 #include "internal/stack.h"
20 #include "internal/strfunc.h"
21 #include "internal/dtoa.h"
22 #include "internal/itoa.h"
23 #include "stringbuffer.h"
26 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
28 #pragma intrinsic(_BitScanForward)
30 #ifdef RAPIDJSON_SSE42
31 #include <nmmintrin.h>
32 #elif defined(RAPIDJSON_SSE2)
33 #include <emmintrin.h>
38 RAPIDJSON_DIAG_OFF(4127)
43 RAPIDJSON_DIAG_OFF(padded)
44 RAPIDJSON_DIAG_OFF(unreachable-code)
58 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
59 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
65 kWriteValidateEncodingFlag = 1,
66 kWriteNanAndInfFlag = 2,
67 kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS
86 template<
typename OutputStream,
typename SourceEncoding = UTF8<>,
typename TargetEncoding = UTF8<>,
typename StackAllocator = CrtAllocator,
unsigned writeFlags = kWriteDefaultFlags>
89 typedef typename SourceEncoding::Ch Ch;
91 static const int kDefaultMaxDecimalPlaces = 324;
99 Writer(OutputStream& os, StackAllocator* stackAllocator = 0,
size_t levelDepth = kDefaultLevelDepth) :
100 os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(
Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
103 Writer(StackAllocator* allocator = 0,
size_t levelDepth = kDefaultLevelDepth) :
104 os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
127 level_stack_.Clear();
135 return hasRoot_ && level_stack_.Empty();
138 int GetMaxDecimalPlaces()
const {
139 return maxDecimalPlaces_;
164 maxDecimalPlaces_ = maxDecimalPlaces;
172 bool Null() { Prefix(
kNullType);
return EndValue(WriteNull()); }
174 bool Int(
int i) { Prefix(
kNumberType);
return EndValue(WriteInt(i)); }
175 bool Uint(
unsigned u) { Prefix(
kNumberType);
return EndValue(WriteUint(u)); }
176 bool Int64(int64_t i64) { Prefix(
kNumberType);
return EndValue(WriteInt64(i64)); }
177 bool Uint64(uint64_t u64) { Prefix(
kNumberType);
return EndValue(WriteUint64(u64)); }
186 bool RawNumber(
const Ch* str,
SizeType length,
bool copy =
false) {
190 return EndValue(WriteString(str, length));
193 bool String(
const Ch* str,
SizeType length,
bool copy =
false) {
197 return EndValue(WriteString(str, length));
200 #if RAPIDJSON_HAS_STDSTRING
201 bool String(
const std::basic_string<Ch>& str) {
202 return String(str.data(),
SizeType(str.size()));
208 new (level_stack_.template Push<Level>()) Level(
false);
209 return WriteStartObject();
212 bool Key(
const Ch* str,
SizeType length,
bool copy =
false) {
return String(str, length, copy); }
214 bool EndObject(
SizeType memberCount = 0) {
218 level_stack_.template Pop<Level>(1);
219 return EndValue(WriteEndObject());
224 new (level_stack_.template Push<Level>()) Level(
true);
225 return WriteStartArray();
228 bool EndArray(
SizeType elementCount = 0) {
232 level_stack_.template Pop<Level>(1);
233 return EndValue(WriteEndArray());
241 bool String(
const Ch* str) {
return String(str, internal::StrLen(str)); }
242 bool Key(
const Ch* str) {
return Key(str, internal::StrLen(str)); }
257 return EndValue(WriteRawValue(json, length));
268 static const size_t kDefaultLevelDepth = 32;
272 PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'u'); PutUnsafe(*os_,
'l'); PutUnsafe(*os_,
'l');
return true;
275 bool WriteBool(
bool b) {
278 PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'r'); PutUnsafe(*os_,
'u'); PutUnsafe(*os_,
'e');
282 PutUnsafe(*os_,
'f'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'l'); PutUnsafe(*os_,
's'); PutUnsafe(*os_,
'e');
287 bool WriteInt(
int i) {
289 const char* end = internal::i32toa(i, buffer);
290 PutReserve(*os_,
static_cast<size_t>(end - buffer));
291 for (
const char* p = buffer; p != end; ++p)
292 PutUnsafe(*os_,
static_cast<typename TargetEncoding::Ch
>(*p));
296 bool WriteUint(
unsigned u) {
298 const char* end = internal::u32toa(u, buffer);
299 PutReserve(*os_,
static_cast<size_t>(end - buffer));
300 for (
const char* p = buffer; p != end; ++p)
301 PutUnsafe(*os_,
static_cast<typename TargetEncoding::Ch
>(*p));
305 bool WriteInt64(int64_t i64) {
307 const char* end = internal::i64toa(i64, buffer);
308 PutReserve(*os_,
static_cast<size_t>(end - buffer));
309 for (
const char* p = buffer; p != end; ++p)
310 PutUnsafe(*os_,
static_cast<typename TargetEncoding::Ch
>(*p));
314 bool WriteUint64(uint64_t u64) {
316 char* end = internal::u64toa(u64, buffer);
317 PutReserve(*os_,
static_cast<size_t>(end - buffer));
318 for (
char* p = buffer; p != end; ++p)
319 PutUnsafe(*os_,
static_cast<typename TargetEncoding::Ch
>(*p));
323 bool WriteDouble(
double d) {
325 if (!(writeFlags & kWriteNanAndInfFlag))
329 PutUnsafe(*os_,
'N'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'N');
334 PutUnsafe(*os_,
'-');
338 PutUnsafe(*os_,
'I'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'f');
339 PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'y');
344 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
345 PutReserve(*os_,
static_cast<size_t>(end - buffer));
346 for (
char* p = buffer; p != end; ++p)
347 PutUnsafe(*os_,
static_cast<typename TargetEncoding::Ch
>(*p));
351 bool WriteString(
const Ch* str,
SizeType length) {
352 static const typename TargetEncoding::Ch hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
353 static const char escape[256] = {
354 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
356 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'b',
't',
'n',
'u',
'f',
'r',
'u',
'u',
357 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
358 0, 0,
'"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
360 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'\\', 0, 0, 0,
361 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
365 if (TargetEncoding::supportUnicode)
366 PutReserve(*os_, 2 + length * 6);
368 PutReserve(*os_, 2 + length * 12);
370 PutUnsafe(*os_,
'\"');
372 while (ScanWriteUnescapedString(is, length)) {
373 const Ch c = is.Peek();
374 if (!TargetEncoding::supportUnicode &&
static_cast<unsigned>(c) >= 0x80) {
379 PutUnsafe(*os_,
'\\');
380 PutUnsafe(*os_,
'u');
381 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
382 PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
383 PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
384 PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
385 PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
390 unsigned s = codepoint - 0x010000;
391 unsigned lead = (s >> 10) + 0xD800;
392 unsigned trail = (s & 0x3FF) + 0xDC00;
393 PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
394 PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
395 PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
396 PutUnsafe(*os_, hexDigits[(lead ) & 15]);
397 PutUnsafe(*os_,
'\\');
398 PutUnsafe(*os_,
'u');
399 PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
400 PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
401 PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
402 PutUnsafe(*os_, hexDigits[(trail ) & 15]);
405 else if ((
sizeof(Ch) == 1 ||
static_cast<unsigned>(c) < 256) &&
RAPIDJSON_UNLIKELY(escape[
static_cast<unsigned char>(c)])) {
407 PutUnsafe(*os_,
'\\');
408 PutUnsafe(*os_,
static_cast<typename TargetEncoding::Ch
>(escape[
static_cast<unsigned char>(c)]));
409 if (escape[
static_cast<unsigned char>(c)] ==
'u') {
410 PutUnsafe(*os_,
'0');
411 PutUnsafe(*os_,
'0');
412 PutUnsafe(*os_, hexDigits[
static_cast<unsigned char>(c) >> 4]);
413 PutUnsafe(*os_, hexDigits[
static_cast<unsigned char>(c) & 0xF]);
421 PutUnsafe(*os_,
'\"');
429 bool WriteStartObject() { os_->Put(
'{');
return true; }
430 bool WriteEndObject() { os_->Put(
'}');
return true; }
431 bool WriteStartArray() { os_->Put(
'[');
return true; }
432 bool WriteEndArray() { os_->Put(
']');
return true; }
434 bool WriteRawValue(
const Ch* json,
size_t length) {
435 PutReserve(*os_, length);
436 for (
size_t i = 0; i < length; i++) {
438 PutUnsafe(*os_, json[i]);
443 void Prefix(
Type type) {
446 Level* level = level_stack_.template Top<Level>();
447 if (level->valueCount > 0) {
451 os_->Put((level->valueCount % 2 == 0) ?
',' :
':');
453 if (!level->inArray && level->valueCount % 2 == 0)
464 bool EndValue(
bool ret) {
472 int maxDecimalPlaces_;
485 char *buffer = os_->Push(11);
486 const char* end = internal::i32toa(i, buffer);
487 os_->Pop(
static_cast<size_t>(11 - (end - buffer)));
493 char *buffer = os_->Push(10);
494 const char* end = internal::u32toa(u, buffer);
495 os_->Pop(
static_cast<size_t>(10 - (end - buffer)));
501 char *buffer = os_->Push(21);
502 const char* end = internal::i64toa(i64, buffer);
503 os_->Pop(
static_cast<size_t>(21 - (end - buffer)));
509 char *buffer = os_->Push(20);
510 const char* end = internal::u64toa(u, buffer);
511 os_->Pop(
static_cast<size_t>(20 - (end - buffer)));
519 if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
523 PutUnsafe(*os_,
'N'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'N');
528 PutUnsafe(*os_,
'-');
532 PutUnsafe(*os_,
'I'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'f');
533 PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'y');
537 char *buffer = os_->Push(25);
538 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
539 os_->Pop(
static_cast<size_t>(25 - (end - buffer)));
543 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
552 const char* p = is.
src_;
553 const char* end = is.
head_ + length;
554 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
555 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) &
static_cast<size_t>(~15));
556 if (nextAligned > end)
559 while (p != nextAligned)
560 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
565 os_->PutUnsafe(*p++);
568 static const char dquote[16] = {
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"' };
569 static const char bslash[16] = {
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\' };
570 static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
571 const __m128i dq = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(&dquote[0]));
572 const __m128i bs = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(&bslash[0]));
573 const __m128i sp = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(&space[0]));
575 for (; p != endAligned; p += 16) {
576 const __m128i s = _mm_load_si128(
reinterpret_cast<const __m128i *
>(p));
577 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
578 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
579 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp);
580 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
581 unsigned short r =
static_cast<unsigned short>(_mm_movemask_epi8(x));
584 #ifdef _MSC_VER // Find the index of first escaped
585 unsigned long offset;
586 _BitScanForward(&offset, r);
589 len =
static_cast<SizeType>(__builtin_ffs(r) - 1);
591 char* q =
reinterpret_cast<char*
>(os_->PushUnsafe(len));
592 for (
size_t i = 0; i < len; i++)
598 _mm_storeu_si128(
reinterpret_cast<__m128i *
>(os_->PushUnsafe(16)), s);
604 #endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
616 #endif // RAPIDJSON_RAPIDJSON_H_