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) {
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()) {
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)
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]);
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>();
445 os_->Put((level->
valueCount % 2 == 0) ?
',' :
':');
458 bool EndValue(
bool ret) {
465 internal::Stack<StackAllocator> level_stack_;
466 int maxDecimalPlaces_;
479 char *buffer = os_->Push(11);
480 const char* end = internal::i32toa(i, buffer);
481 os_->Pop(static_cast<size_t>(11 - (end - buffer)));
487 char *buffer = os_->Push(10);
488 const char* end = internal::u32toa(u, buffer);
489 os_->Pop(static_cast<size_t>(10 - (end - buffer)));
495 char *buffer = os_->Push(21);
496 const char* end = internal::i64toa(i64, buffer);
497 os_->Pop(static_cast<size_t>(21 - (end - buffer)));
503 char *buffer = os_->Push(20);
504 const char* end = internal::u64toa(u, buffer);
505 os_->Pop(static_cast<size_t>(20 - (end - buffer)));
511 if (internal::Double(d).IsNanOrInf()) {
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) 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_ true
Definition: rapidjson.h:606
bool inArray
true if in array, otherwise in object
Definition: writer.h:259
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition: writer.h:163
Read-only string stream.
Definition: fwd.h:47
No flags are set.
Definition: writer.h:64
Encoding conversion.
Definition: encodings.h:658
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:134
Validate encoding of JSON strings.
Definition: writer.h:65
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
Definition: stream.h:84
unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:380
WriteFlag
Combination of writeFlags
Definition: writer.h:63
false
Definition: rapidjson.h:605
const Ch * head_
Original head of the string.
Definition: stream.h:125
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:252
const Ch * src_
Current read position.
Definition: stream.h:124
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:455
Information for each nested level
Definition: writer.h:256
size_t valueCount
number of values in this level
Definition: writer.h:258
Type
Type of JSON value
Definition: rapidjson.h:603
object
Definition: rapidjson.h:607
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:468
array
Definition: rapidjson.h:608
JSON writer
Definition: fwd.h:95
null
Definition: rapidjson.h:604
string
Definition: rapidjson.h:609
Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
Definition: writer.h:67
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
User-defined kWriteDefaultFlags definition.
Definition: writer.h:59
bool Double(double d)
Writes the given double value to the stream
Definition: writer.h:184
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
Definition: stream.h:91
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor
Definition: writer.h:99
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:402
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:124
number
Definition: rapidjson.h:610
Allow writing of Infinity, -Infinity and NaN.
Definition: writer.h:66
bool String(const Ch *str)
Simpler but slower overload.
Definition: writer.h:239