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)
45 RAPIDJSON_DIAG_OFF(c++98-compat)
59 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS 60 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags 66 kWriteValidateEncodingFlag = 1,
67 kWriteNanAndInfFlag = 2,
68 kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS
87 template<
typename OutputStream,
typename SourceEncoding = UTF8<>,
typename TargetEncoding = UTF8<>,
typename StackAllocator = CrtAllocator,
unsigned writeFlags = kWriteDefaultFlags>
90 typedef typename SourceEncoding::Ch Ch;
92 static const int kDefaultMaxDecimalPlaces = 324;
100 Writer(OutputStream& os, StackAllocator* stackAllocator = 0,
size_t levelDepth = kDefaultLevelDepth) :
101 os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(
Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
104 Writer(StackAllocator* allocator = 0,
size_t levelDepth = kDefaultLevelDepth) :
105 os_(0), level_stack_(allocator, levelDepth *
sizeof(
Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(
false) {}
107 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 109 os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
135 level_stack_.Clear();
143 return hasRoot_ && level_stack_.Empty();
146 int GetMaxDecimalPlaces()
const {
147 return maxDecimalPlaces_;
172 maxDecimalPlaces_ = maxDecimalPlaces;
180 bool Null() { Prefix(
kNullType);
return EndValue(WriteNull()); }
182 bool Int(
int i) { Prefix(
kNumberType);
return EndValue(WriteInt(i)); }
183 bool Uint(
unsigned u) { Prefix(
kNumberType);
return EndValue(WriteUint(u)); }
184 bool Int64(int64_t i64) { Prefix(
kNumberType);
return EndValue(WriteInt64(i64)); }
185 bool Uint64(uint64_t u64) { Prefix(
kNumberType);
return EndValue(WriteUint64(u64)); }
194 bool RawNumber(
const Ch* str,
SizeType length,
bool copy =
false) {
198 return EndValue(WriteString(str, length));
201 bool String(
const Ch* str,
SizeType length,
bool copy =
false) {
205 return EndValue(WriteString(str, length));
208 #if RAPIDJSON_HAS_STDSTRING 209 bool String(
const std::basic_string<Ch>& str) {
210 return String(str.data(),
SizeType(str.size()));
216 new (level_stack_.template Push<Level>())
Level(
false);
217 return WriteStartObject();
220 bool Key(
const Ch* str,
SizeType length,
bool copy =
false) {
return String(str, length, copy); }
222 bool EndObject(
SizeType memberCount = 0) {
226 level_stack_.template Pop<Level>(1);
227 return EndValue(WriteEndObject());
232 new (level_stack_.template Push<Level>())
Level(
true);
233 return WriteStartArray();
236 bool EndArray(
SizeType elementCount = 0) {
240 level_stack_.template Pop<Level>(1);
241 return EndValue(WriteEndArray());
249 bool String(
const Ch* str) {
return String(str, internal::StrLen(str)); }
250 bool Key(
const Ch* str) {
return Key(str, internal::StrLen(str)); }
265 return EndValue(WriteRawValue(json, length));
276 static const size_t kDefaultLevelDepth = 32;
280 PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'u'); PutUnsafe(*os_,
'l'); PutUnsafe(*os_,
'l');
return true;
283 bool WriteBool(
bool b) {
286 PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'r'); PutUnsafe(*os_,
'u'); PutUnsafe(*os_,
'e');
290 PutUnsafe(*os_,
'f'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'l'); PutUnsafe(*os_,
's'); PutUnsafe(*os_,
'e');
295 bool WriteInt(
int i) {
297 const char* end = internal::i32toa(i, buffer);
298 PutReserve(*os_, static_cast<size_t>(end - buffer));
299 for (
const char* p = buffer; p != end; ++p)
300 PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
304 bool WriteUint(
unsigned u) {
306 const char* end = internal::u32toa(u, buffer);
307 PutReserve(*os_, static_cast<size_t>(end - buffer));
308 for (
const char* p = buffer; p != end; ++p)
309 PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
313 bool WriteInt64(int64_t i64) {
315 const char* end = internal::i64toa(i64, 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 TargetEncoding::Ch>(*p));
322 bool WriteUint64(uint64_t u64) {
324 char* end = internal::u64toa(u64, buffer);
325 PutReserve(*os_, static_cast<size_t>(end - buffer));
326 for (
char* p = buffer; p != end; ++p)
327 PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
331 bool WriteDouble(
double d) {
333 if (!(writeFlags & kWriteNanAndInfFlag))
337 PutUnsafe(*os_,
'N'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'N');
342 PutUnsafe(*os_,
'-');
346 PutUnsafe(*os_,
'I'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'f');
347 PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'y');
352 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
353 PutReserve(*os_, static_cast<size_t>(end - buffer));
354 for (
char* p = buffer; p != end; ++p)
355 PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
359 bool WriteString(
const Ch* str,
SizeType length) {
360 static const typename TargetEncoding::Ch hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
361 static const char escape[256] = {
362 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 364 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'b',
't',
'n',
'u',
'f',
'r',
'u',
'u',
365 'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
'u',
366 0, 0,
'"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
368 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'\\', 0, 0, 0,
369 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
373 if (TargetEncoding::supportUnicode)
374 PutReserve(*os_, 2 + length * 6);
376 PutReserve(*os_, 2 + length * 12);
378 PutUnsafe(*os_,
'\"');
380 while (ScanWriteUnescapedString(is, length)) {
381 const Ch c = is.Peek();
382 if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
387 PutUnsafe(*os_,
'\\');
388 PutUnsafe(*os_,
'u');
389 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
390 PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
391 PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
392 PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
393 PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
398 unsigned s = codepoint - 0x010000;
399 unsigned lead = (s >> 10) + 0xD800;
400 unsigned trail = (s & 0x3FF) + 0xDC00;
401 PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
402 PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
403 PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
404 PutUnsafe(*os_, hexDigits[(lead ) & 15]);
405 PutUnsafe(*os_,
'\\');
406 PutUnsafe(*os_,
'u');
407 PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
408 PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
409 PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
410 PutUnsafe(*os_, hexDigits[(trail ) & 15]);
413 else if ((
sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) &&
RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
415 PutUnsafe(*os_,
'\\');
416 PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
417 if (escape[static_cast<unsigned char>(c)] ==
'u') {
418 PutUnsafe(*os_,
'0');
419 PutUnsafe(*os_,
'0');
420 PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
421 PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
429 PutUnsafe(*os_,
'\"');
437 bool WriteStartObject() { os_->Put(
'{');
return true; }
438 bool WriteEndObject() { os_->Put(
'}');
return true; }
439 bool WriteStartArray() { os_->Put(
'[');
return true; }
440 bool WriteEndArray() { os_->Put(
']');
return true; }
442 bool WriteRawValue(
const Ch* json,
size_t length) {
443 PutReserve(*os_, length);
444 for (
size_t i = 0; i < length; i++) {
446 PutUnsafe(*os_, json[i]);
451 void Prefix(
Type type) {
454 Level* level = level_stack_.template Top<Level>();
459 os_->Put((level->
valueCount % 2 == 0) ?
',' :
':');
472 bool EndValue(
bool ret) {
480 int maxDecimalPlaces_;
493 char *buffer = os_->Push(11);
494 const char* end = internal::i32toa(i, buffer);
495 os_->Pop(static_cast<size_t>(11 - (end - buffer)));
501 char *buffer = os_->Push(10);
502 const char* end = internal::u32toa(u, buffer);
503 os_->Pop(static_cast<size_t>(10 - (end - buffer)));
509 char *buffer = os_->Push(21);
510 const char* end = internal::i64toa(i64, buffer);
511 os_->Pop(static_cast<size_t>(21 - (end - buffer)));
517 char *buffer = os_->Push(20);
518 const char* end = internal::u64toa(u, buffer);
519 os_->Pop(static_cast<size_t>(20 - (end - buffer)));
527 if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
531 PutUnsafe(*os_,
'N'); PutUnsafe(*os_,
'a'); PutUnsafe(*os_,
'N');
536 PutUnsafe(*os_,
'-');
540 PutUnsafe(*os_,
'I'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'f');
541 PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
'n'); PutUnsafe(*os_,
'i'); PutUnsafe(*os_,
't'); PutUnsafe(*os_,
'y');
545 char *buffer = os_->Push(25);
546 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
547 os_->Pop(static_cast<size_t>(25 - (end - buffer)));
551 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) 560 const char* p = is.
src_;
561 const char* end = is.
head_ + length;
562 const char* nextAligned =
reinterpret_cast<const char*
>((
reinterpret_cast<size_t>(p) + 15) &
static_cast<size_t>(~15));
563 const char* endAligned =
reinterpret_cast<const char*
>(
reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
564 if (nextAligned > end)
567 while (p != nextAligned)
568 if (*p < 0x20 || *p ==
'\"' || *p ==
'\\') {
573 os_->PutUnsafe(*p++);
576 static const char dquote[16] = {
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"',
'\"' };
577 static const char bslash[16] = {
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\',
'\\' };
578 static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
579 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
580 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
581 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
583 for (; p != endAligned; p += 16) {
584 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
585 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
586 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
587 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp);
588 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
589 unsigned short r =
static_cast<unsigned short>(_mm_movemask_epi8(x));
592 #ifdef _MSC_VER // Find the index of first escaped 593 unsigned long offset;
594 _BitScanForward(&offset, r);
597 len =
static_cast<SizeType>(__builtin_ffs(r) - 1);
599 char* q =
reinterpret_cast<char*
>(os_->PushUnsafe(len));
600 for (
size_t i = 0; i < len; i++)
606 _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
612 #endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) 624 #endif // RAPIDJSON_RAPIDJSON_H_ Encoding conversion.
Definition: encodings.h:658
size_t valueCount
number of values in this level
Definition: writer.h:272
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:380
bool inArray
true if in array, otherwise in object
Definition: writer.h:273
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:402
JSON writer.
Definition: fwd.h:95
object
Definition: rapidjson.h:607
Read-only string stream.
Definition: fwd.h:47
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:119
array
Definition: rapidjson.h:608
const Ch * src_
Current read position.
Definition: stream.h:124
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:262
false
Definition: rapidjson.h:605
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:192
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:116
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:142
Information for each nested level.
Definition: writer.h:270
string
Definition: rapidjson.h:609
number
Definition: rapidjson.h:610
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:455
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:100
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition: writer.h:171
true
Definition: rapidjson.h:606
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:132
Type
Type of JSON value.
Definition: rapidjson.h:603
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:468
bool String(const Ch *str)
Simpler but slower overload.
Definition: writer.h:249
null
Definition: rapidjson.h:604
const Ch * head_
Original head of the string.
Definition: stream.h:125