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)
47 RAPIDJSON_NAMESPACE_BEGIN
58 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
59 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
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) {
189 return EndValue(WriteString(str, length));
192 bool String(
const Ch* str,
SizeType length,
bool copy =
false) {
195 return EndValue(WriteString(str, length));
198 #if RAPIDJSON_HAS_STDSTRING
199 bool String(
const std::basic_string<Ch>& str) {
200 return String(str.data(),
SizeType(str.size()));
206 new (level_stack_.template Push<Level>()) Level(
false);
207 return WriteStartObject();
210 bool Key(
const Ch* str,
SizeType length,
bool copy =
false) {
return String(str, length, copy); }
212 bool EndObject(
SizeType memberCount = 0) {
216 level_stack_.template Pop<Level>(1);
217 return EndValue(WriteEndObject());
222 new (level_stack_.template Push<Level>()) Level(
true);
223 return WriteStartArray();
226 bool EndArray(
SizeType elementCount = 0) {
230 level_stack_.template Pop<Level>(1);
231 return EndValue(WriteEndArray());
239 bool String(
const Ch* str) {
return String(str, internal::StrLen(str)); }
240 bool Key(
const Ch* str) {
return Key(str, internal::StrLen(str)); }
252 bool RawValue(
const Ch* json,
size_t length,
Type type) { Prefix(type);
return EndValue(WriteRawValue(json, length)); }
257 Level(
bool inArray_) : valueCount(0), inArray(inArray_) {}
262 static const size_t kDefaultLevelDepth = 32;
269 bool WriteBool(
bool b) {
276 PutUnsafe(*os_,
'f'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'l'); PutUnsafe(*os_,
's'); PutUnsafe(*os_,
'e');
281 bool WriteInt(
int i) {
283 const char* end = internal::i32toa(i, buffer);
284 PutReserve(*os_,
static_cast<size_t>(end - buffer));
285 for (
const char* p = buffer; p != end; ++p)
286 PutUnsafe(*os_,
static_cast<typename TargetEncoding::Ch
>(*p));
290 bool WriteUint(
unsigned u) {
292 const char* end = internal::u32toa(u, buffer);
293 PutReserve(*os_,
static_cast<size_t>(end - buffer));
294 for (
const char* p = buffer; p != end; ++p)
295 PutUnsafe(*os_,
static_cast<typename TargetEncoding::Ch
>(*p));
299 bool WriteInt64(int64_t i64) {
301 const char* end = internal::i64toa(i64, buffer);
302 PutReserve(*os_,
static_cast<size_t>(end - buffer));
303 for (
const char* p = buffer; p != end; ++p)
304 PutUnsafe(*os_,
static_cast<typename TargetEncoding::Ch
>(*p));
308 bool WriteUint64(uint64_t u64) {
310 char* end = internal::u64toa(u64, buffer);
311 PutReserve(*os_,
static_cast<size_t>(end - buffer));
312 for (
char* p = buffer; p != end; ++p)
313 PutUnsafe(*os_,
static_cast<typename TargetEncoding::Ch
>(*p));
317 bool WriteDouble(
double d) {
318 if (internal::Double(d).IsNanOrInf()) {
319 if (!(writeFlags & kWriteNanAndInfFlag))
321 if (internal::Double(d).IsNan()) {
326 if (internal::Double(d).Sign()) {
338 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
339 PutReserve(*os_,
static_cast<size_t>(end - buffer));
340 for (
char* p = buffer; p != end; ++p)
341 PutUnsafe(*os_,
static_cast<typename TargetEncoding::Ch
>(*p));
345 bool WriteString(
const Ch* str,
SizeType length) {
346 static const typename TargetEncoding::Ch hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
347 static const char escape[256] = {
348 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
350 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'b',
't',
'n',
'u',
'f',
'r',
'u',
'u',
351 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
352 0, 0,
'"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
354 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'\\', 0, 0, 0,
355 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
359 if (TargetEncoding::supportUnicode)
365 GenericStringStream<SourceEncoding> is(str);
366 while (ScanWriteUnescapedString(is, length)) {
367 const Ch c = is.Peek();
368 if (!TargetEncoding::supportUnicode &&
static_cast<unsigned>(c) >= 0x80) {
375 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
376 PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
377 PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
378 PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
379 PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
384 unsigned s = codepoint - 0x010000;
385 unsigned lead = (s >> 10) + 0xD800;
386 unsigned trail = (s & 0x3FF) + 0xDC00;
387 PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
388 PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
389 PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
390 PutUnsafe(*os_, hexDigits[(lead ) & 15]);
393 PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
394 PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
395 PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
396 PutUnsafe(*os_, hexDigits[(trail ) & 15]);
399 else if ((
sizeof(Ch) == 1 ||
static_cast<unsigned>(c) < 256) &&
RAPIDJSON_UNLIKELY(escape[
static_cast<unsigned char>(c)])) {
402 PutUnsafe(*os_,
static_cast<typename TargetEncoding::Ch
>(escape[
static_cast<unsigned char>(c)]));
403 if (escape[
static_cast<unsigned char>(c)] ==
'u') {
406 PutUnsafe(*os_, hexDigits[
static_cast<unsigned char>(c) >> 4]);
407 PutUnsafe(*os_, hexDigits[
static_cast<unsigned char>(c) & 0xF]);
411 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
412 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
419 bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is,
size_t length) {
423 bool WriteStartObject() { os_->Put(
'{');
return true; }
424 bool WriteEndObject() { os_->Put(
'}');
return true; }
425 bool WriteStartArray() { os_->Put(
'[');
return true; }
426 bool WriteEndArray() { os_->Put(
']');
return true; }
428 bool WriteRawValue(
const Ch* json,
size_t length) {
430 for (
size_t i = 0; i < length; i++) {
437 void Prefix(
Type type) {
440 Level* level = level_stack_.template Top<Level>();
441 if (level->valueCount > 0) {
445 os_->Put((level->valueCount % 2 == 0) ?
',' :
':');
447 if (!level->inArray && level->valueCount % 2 == 0)
458 bool EndValue(
bool ret) {
465 internal::Stack<StackAllocator> level_stack_;
466 int maxDecimalPlaces_;
471 Writer(
const Writer&);
472 Writer& operator=(
const Writer&);
478 inline bool Writer<StringBuffer>::WriteInt(
int i) {
479 char *buffer = os_->Push(11);
480 const char* end = internal::i32toa(i, buffer);
481 os_->Pop(
static_cast<size_t>(11 - (end - buffer)));
486 inline bool Writer<StringBuffer>::WriteUint(
unsigned u) {
487 char *buffer = os_->Push(10);
488 const char* end = internal::u32toa(u, buffer);
489 os_->Pop(
static_cast<size_t>(10 - (end - buffer)));
494 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
495 char *buffer = os_->Push(21);
496 const char* end = internal::i64toa(i64, buffer);
497 os_->Pop(
static_cast<size_t>(21 - (end - buffer)));
502 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
503 char *buffer = os_->Push(20);
504 const char* end = internal::u64toa(u, buffer);
505 os_->Pop(
static_cast<size_t>(20 - (end - buffer)));
510 inline bool Writer<StringBuffer>::WriteDouble(
double d) {
511 if (internal::Double(d).IsNanOrInf()) {
513 if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
515 if (internal::Double(d).IsNan()) {
520 if (internal::Double(d).Sign()) {
531 char *buffer = os_->Push(25);
532 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
533 os_->Pop(
static_cast<size_t>(25 - (end - buffer)));
537 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
539 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is,
size_t length) {
546 const char* p = is.src_;
547 const char* end = is.head_ + length;
548 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
549 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) &
static_cast<size_t>(~15));
550 if (nextAligned > end)
553 while (p != nextAligned)
554 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
559 os_->PutUnsafe(*p++);
562 static const char dquote[16] = {
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"' };
563 static const char bslash[16] = {
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\' };
564 static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
565 const __m128i dq = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(&dquote[0]));
566 const __m128i bs = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(&bslash[0]));
567 const __m128i sp = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(&space[0]));
569 for (; p != endAligned; p += 16) {
570 const __m128i s = _mm_load_si128(
reinterpret_cast<const __m128i *
>(p));
571 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
572 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
573 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp);
574 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
575 unsigned short r =
static_cast<unsigned short>(_mm_movemask_epi8(x));
578 #ifdef _MSC_VER // Find the index of first escaped
579 unsigned long offset;
580 _BitScanForward(&offset, r);
583 len =
static_cast<SizeType>(__builtin_ffs(r) - 1);
585 char* q =
reinterpret_cast<char*
>(os_->PushUnsafe(len));
586 for (
size_t i = 0; i < len; i++)
592 _mm_storeu_si128(
reinterpret_cast<__m128i *
>(os_->PushUnsafe(16)), s);
598 #endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
600 RAPIDJSON_NAMESPACE_END
610 #endif // RAPIDJSON_RAPIDJSON_H_