File indexing completed on 2025-01-18 10:10:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef RAPIDJSON_WRITER_H_
0016 #define RAPIDJSON_WRITER_H_
0017
0018 #include "stream.h"
0019 #include "internal/clzll.h"
0020 #include "internal/meta.h"
0021 #include "internal/stack.h"
0022 #include "internal/strfunc.h"
0023 #include "internal/dtoa.h"
0024 #include "internal/itoa.h"
0025 #include "stringbuffer.h"
0026 #include <new> // placement new
0027
0028 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
0029 #include <intrin.h>
0030 #pragma intrinsic(_BitScanForward)
0031 #endif
0032 #ifdef RAPIDJSON_SSE42
0033 #include <nmmintrin.h>
0034 #elif defined(RAPIDJSON_SSE2)
0035 #include <emmintrin.h>
0036 #elif defined(RAPIDJSON_NEON)
0037 #include <arm_neon.h>
0038 #endif
0039
0040 #ifdef __clang__
0041 RAPIDJSON_DIAG_PUSH
0042 RAPIDJSON_DIAG_OFF(padded)
0043 RAPIDJSON_DIAG_OFF(unreachable-code)
0044 RAPIDJSON_DIAG_OFF(c++98-compat)
0045 #elif defined(_MSC_VER)
0046 RAPIDJSON_DIAG_PUSH
0047 RAPIDJSON_DIAG_OFF(4127)
0048 #endif
0049
0050 RAPIDJSON_NAMESPACE_BEGIN
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
0062 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
0063 #endif
0064
0065
0066 enum WriteFlag {
0067 kWriteNoFlags = 0,
0068 kWriteValidateEncodingFlag = 1,
0069 kWriteNanAndInfFlag = 2,
0070 kWriteNanAndInfNullFlag = 4,
0071 kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS
0072 };
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
0091 class Writer {
0092 public:
0093 typedef typename SourceEncoding::Ch Ch;
0094
0095 static const int kDefaultMaxDecimalPlaces = 324;
0096
0097
0098
0099
0100
0101
0102 explicit
0103 Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
0104 os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
0105
0106 explicit
0107 Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
0108 os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
0109
0110 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
0111 Writer(Writer&& rhs) :
0112 os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
0113 rhs.os_ = 0;
0114 }
0115 #endif
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135 void Reset(OutputStream& os) {
0136 os_ = &os;
0137 hasRoot_ = false;
0138 level_stack_.Clear();
0139 }
0140
0141
0142
0143
0144
0145 bool IsComplete() const {
0146 return hasRoot_ && level_stack_.Empty();
0147 }
0148
0149 int GetMaxDecimalPlaces() const {
0150 return maxDecimalPlaces_;
0151 }
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 void SetMaxDecimalPlaces(int maxDecimalPlaces) {
0175 maxDecimalPlaces_ = maxDecimalPlaces;
0176 }
0177
0178
0179
0180
0181
0182
0183 bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
0184 bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
0185 bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
0186 bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
0187 bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
0188 bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
0189
0190
0191
0192
0193
0194
0195 bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
0196
0197 bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
0198 RAPIDJSON_ASSERT(str != 0);
0199 (void)copy;
0200 Prefix(kNumberType);
0201 return EndValue(WriteString(str, length));
0202 }
0203
0204 bool String(const Ch* str, SizeType length, bool copy = false) {
0205 RAPIDJSON_ASSERT(str != 0);
0206 (void)copy;
0207 Prefix(kStringType);
0208 return EndValue(WriteString(str, length));
0209 }
0210
0211 #if RAPIDJSON_HAS_STDSTRING
0212 bool String(const std::basic_string<Ch>& str) {
0213 return String(str.data(), SizeType(str.size()));
0214 }
0215 #endif
0216
0217 bool StartObject() {
0218 Prefix(kObjectType);
0219 new (level_stack_.template Push<Level>()) Level(false);
0220 return WriteStartObject();
0221 }
0222
0223 bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
0224
0225 #if RAPIDJSON_HAS_STDSTRING
0226 bool Key(const std::basic_string<Ch>& str)
0227 {
0228 return Key(str.data(), SizeType(str.size()));
0229 }
0230 #endif
0231
0232 bool EndObject(SizeType memberCount = 0) {
0233 (void)memberCount;
0234 RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
0235 RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
0236 RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2);
0237 level_stack_.template Pop<Level>(1);
0238 return EndValue(WriteEndObject());
0239 }
0240
0241 bool StartArray() {
0242 Prefix(kArrayType);
0243 new (level_stack_.template Push<Level>()) Level(true);
0244 return WriteStartArray();
0245 }
0246
0247 bool EndArray(SizeType elementCount = 0) {
0248 (void)elementCount;
0249 RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
0250 RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
0251 level_stack_.template Pop<Level>(1);
0252 return EndValue(WriteEndArray());
0253 }
0254
0255
0256
0257
0258
0259
0260 bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }
0261 bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273 bool RawValue(const Ch* json, size_t length, Type type) {
0274 RAPIDJSON_ASSERT(json != 0);
0275 Prefix(type);
0276 return EndValue(WriteRawValue(json, length));
0277 }
0278
0279
0280
0281
0282
0283 void Flush() {
0284 os_->Flush();
0285 }
0286
0287 static const size_t kDefaultLevelDepth = 32;
0288
0289 protected:
0290
0291 struct Level {
0292 Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
0293 size_t valueCount;
0294 bool inArray;
0295 };
0296
0297 bool WriteNull() {
0298 PutReserve(*os_, 4);
0299 PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
0300 }
0301
0302 bool WriteBool(bool b) {
0303 if (b) {
0304 PutReserve(*os_, 4);
0305 PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
0306 }
0307 else {
0308 PutReserve(*os_, 5);
0309 PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
0310 }
0311 return true;
0312 }
0313
0314 bool WriteInt(int i) {
0315 char buffer[11];
0316 const char* end = internal::i32toa(i, buffer);
0317 PutReserve(*os_, static_cast<size_t>(end - buffer));
0318 for (const char* p = buffer; p != end; ++p)
0319 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
0320 return true;
0321 }
0322
0323 bool WriteUint(unsigned u) {
0324 char buffer[10];
0325 const char* end = internal::u32toa(u, buffer);
0326 PutReserve(*os_, static_cast<size_t>(end - buffer));
0327 for (const char* p = buffer; p != end; ++p)
0328 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
0329 return true;
0330 }
0331
0332 bool WriteInt64(int64_t i64) {
0333 char buffer[21];
0334 const char* end = internal::i64toa(i64, buffer);
0335 PutReserve(*os_, static_cast<size_t>(end - buffer));
0336 for (const char* p = buffer; p != end; ++p)
0337 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
0338 return true;
0339 }
0340
0341 bool WriteUint64(uint64_t u64) {
0342 char buffer[20];
0343 char* end = internal::u64toa(u64, buffer);
0344 PutReserve(*os_, static_cast<size_t>(end - buffer));
0345 for (char* p = buffer; p != end; ++p)
0346 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
0347 return true;
0348 }
0349
0350 bool WriteDouble(double d) {
0351 if (internal::Double(d).IsNanOrInf()) {
0352 if (!(writeFlags & kWriteNanAndInfFlag) && !(writeFlags & kWriteNanAndInfNullFlag))
0353 return false;
0354 if (writeFlags & kWriteNanAndInfNullFlag) {
0355 PutReserve(*os_, 4);
0356 PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l');
0357 return true;
0358 }
0359 if (internal::Double(d).IsNan()) {
0360 PutReserve(*os_, 3);
0361 PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
0362 return true;
0363 }
0364 if (internal::Double(d).Sign()) {
0365 PutReserve(*os_, 9);
0366 PutUnsafe(*os_, '-');
0367 }
0368 else
0369 PutReserve(*os_, 8);
0370 PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
0371 PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
0372 return true;
0373 }
0374
0375 char buffer[25];
0376 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
0377 PutReserve(*os_, static_cast<size_t>(end - buffer));
0378 for (char* p = buffer; p != end; ++p)
0379 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
0380 return true;
0381 }
0382
0383 bool WriteString(const Ch* str, SizeType length) {
0384 static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
0385 static const char escape[256] = {
0386 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0387
0388 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u',
0389 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
0390 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0391 Z16, Z16,
0392 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
0393 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
0394 #undef Z16
0395 };
0396
0397 if (TargetEncoding::supportUnicode)
0398 PutReserve(*os_, 2 + length * 6);
0399 else
0400 PutReserve(*os_, 2 + length * 12);
0401
0402 PutUnsafe(*os_, '\"');
0403 GenericStringStream<SourceEncoding> is(str);
0404 while (ScanWriteUnescapedString(is, length)) {
0405 const Ch c = is.Peek();
0406 if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
0407
0408 unsigned codepoint;
0409 if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
0410 return false;
0411 PutUnsafe(*os_, '\\');
0412 PutUnsafe(*os_, 'u');
0413 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
0414 PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
0415 PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
0416 PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
0417 PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
0418 }
0419 else {
0420 RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
0421
0422 unsigned s = codepoint - 0x010000;
0423 unsigned lead = (s >> 10) + 0xD800;
0424 unsigned trail = (s & 0x3FF) + 0xDC00;
0425 PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
0426 PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
0427 PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
0428 PutUnsafe(*os_, hexDigits[(lead ) & 15]);
0429 PutUnsafe(*os_, '\\');
0430 PutUnsafe(*os_, 'u');
0431 PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
0432 PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
0433 PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
0434 PutUnsafe(*os_, hexDigits[(trail ) & 15]);
0435 }
0436 }
0437 else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
0438 is.Take();
0439 PutUnsafe(*os_, '\\');
0440 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
0441 if (escape[static_cast<unsigned char>(c)] == 'u') {
0442 PutUnsafe(*os_, '0');
0443 PutUnsafe(*os_, '0');
0444 PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
0445 PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
0446 }
0447 }
0448 else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
0449 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
0450 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
0451 return false;
0452 }
0453 PutUnsafe(*os_, '\"');
0454 return true;
0455 }
0456
0457 bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
0458 return RAPIDJSON_LIKELY(is.Tell() < length);
0459 }
0460
0461 bool WriteStartObject() { os_->Put('{'); return true; }
0462 bool WriteEndObject() { os_->Put('}'); return true; }
0463 bool WriteStartArray() { os_->Put('['); return true; }
0464 bool WriteEndArray() { os_->Put(']'); return true; }
0465
0466 bool WriteRawValue(const Ch* json, size_t length) {
0467 PutReserve(*os_, length);
0468 GenericStringStream<SourceEncoding> is(json);
0469 while (RAPIDJSON_LIKELY(is.Tell() < length)) {
0470 RAPIDJSON_ASSERT(is.Peek() != '\0');
0471 if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
0472 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
0473 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
0474 return false;
0475 }
0476 return true;
0477 }
0478
0479 void Prefix(Type type) {
0480 (void)type;
0481 if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) {
0482 Level* level = level_stack_.template Top<Level>();
0483 if (level->valueCount > 0) {
0484 if (level->inArray)
0485 os_->Put(',');
0486 else
0487 os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
0488 }
0489 if (!level->inArray && level->valueCount % 2 == 0)
0490 RAPIDJSON_ASSERT(type == kStringType);
0491 level->valueCount++;
0492 }
0493 else {
0494 RAPIDJSON_ASSERT(!hasRoot_);
0495 hasRoot_ = true;
0496 }
0497 }
0498
0499
0500 bool EndValue(bool ret) {
0501 if (RAPIDJSON_UNLIKELY(level_stack_.Empty()))
0502 Flush();
0503 return ret;
0504 }
0505
0506 OutputStream* os_;
0507 internal::Stack<StackAllocator> level_stack_;
0508 int maxDecimalPlaces_;
0509 bool hasRoot_;
0510
0511 private:
0512
0513 Writer(const Writer&);
0514 Writer& operator=(const Writer&);
0515 };
0516
0517
0518
0519 template<>
0520 inline bool Writer<StringBuffer>::WriteInt(int i) {
0521 char *buffer = os_->Push(11);
0522 const char* end = internal::i32toa(i, buffer);
0523 os_->Pop(static_cast<size_t>(11 - (end - buffer)));
0524 return true;
0525 }
0526
0527 template<>
0528 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
0529 char *buffer = os_->Push(10);
0530 const char* end = internal::u32toa(u, buffer);
0531 os_->Pop(static_cast<size_t>(10 - (end - buffer)));
0532 return true;
0533 }
0534
0535 template<>
0536 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
0537 char *buffer = os_->Push(21);
0538 const char* end = internal::i64toa(i64, buffer);
0539 os_->Pop(static_cast<size_t>(21 - (end - buffer)));
0540 return true;
0541 }
0542
0543 template<>
0544 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
0545 char *buffer = os_->Push(20);
0546 const char* end = internal::u64toa(u, buffer);
0547 os_->Pop(static_cast<size_t>(20 - (end - buffer)));
0548 return true;
0549 }
0550
0551 template<>
0552 inline bool Writer<StringBuffer>::WriteDouble(double d) {
0553 if (internal::Double(d).IsNanOrInf()) {
0554
0555 if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
0556 return false;
0557 if (kWriteDefaultFlags & kWriteNanAndInfNullFlag) {
0558 PutReserve(*os_, 4);
0559 PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l');
0560 return true;
0561 }
0562 if (internal::Double(d).IsNan()) {
0563 PutReserve(*os_, 3);
0564 PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
0565 return true;
0566 }
0567 if (internal::Double(d).Sign()) {
0568 PutReserve(*os_, 9);
0569 PutUnsafe(*os_, '-');
0570 }
0571 else
0572 PutReserve(*os_, 8);
0573 PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
0574 PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
0575 return true;
0576 }
0577
0578 char *buffer = os_->Push(25);
0579 char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
0580 os_->Pop(static_cast<size_t>(25 - (end - buffer)));
0581 return true;
0582 }
0583
0584 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
0585 template<>
0586 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
0587 if (length < 16)
0588 return RAPIDJSON_LIKELY(is.Tell() < length);
0589
0590 if (!RAPIDJSON_LIKELY(is.Tell() < length))
0591 return false;
0592
0593 const char* p = is.src_;
0594 const char* end = is.head_ + length;
0595 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
0596 const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
0597 if (nextAligned > end)
0598 return true;
0599
0600 while (p != nextAligned)
0601 if (*p < 0x20 || *p == '\"' || *p == '\\') {
0602 is.src_ = p;
0603 return RAPIDJSON_LIKELY(is.Tell() < length);
0604 }
0605 else
0606 os_->PutUnsafe(*p++);
0607
0608
0609 static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
0610 static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
0611 static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
0612 const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
0613 const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
0614 const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
0615
0616 for (; p != endAligned; p += 16) {
0617 const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
0618 const __m128i t1 = _mm_cmpeq_epi8(s, dq);
0619 const __m128i t2 = _mm_cmpeq_epi8(s, bs);
0620 const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp);
0621 const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
0622 unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
0623 if (RAPIDJSON_UNLIKELY(r != 0)) {
0624 SizeType len;
0625 #ifdef _MSC_VER
0626 unsigned long offset;
0627 _BitScanForward(&offset, r);
0628 len = offset;
0629 #else
0630 len = static_cast<SizeType>(__builtin_ffs(r) - 1);
0631 #endif
0632 char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
0633 for (size_t i = 0; i < len; i++)
0634 q[i] = p[i];
0635
0636 p += len;
0637 break;
0638 }
0639 _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
0640 }
0641
0642 is.src_ = p;
0643 return RAPIDJSON_LIKELY(is.Tell() < length);
0644 }
0645 #elif defined(RAPIDJSON_NEON)
0646 template<>
0647 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
0648 if (length < 16)
0649 return RAPIDJSON_LIKELY(is.Tell() < length);
0650
0651 if (!RAPIDJSON_LIKELY(is.Tell() < length))
0652 return false;
0653
0654 const char* p = is.src_;
0655 const char* end = is.head_ + length;
0656 const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
0657 const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
0658 if (nextAligned > end)
0659 return true;
0660
0661 while (p != nextAligned)
0662 if (*p < 0x20 || *p == '\"' || *p == '\\') {
0663 is.src_ = p;
0664 return RAPIDJSON_LIKELY(is.Tell() < length);
0665 }
0666 else
0667 os_->PutUnsafe(*p++);
0668
0669
0670 const uint8x16_t s0 = vmovq_n_u8('"');
0671 const uint8x16_t s1 = vmovq_n_u8('\\');
0672 const uint8x16_t s2 = vmovq_n_u8('\b');
0673 const uint8x16_t s3 = vmovq_n_u8(32);
0674
0675 for (; p != endAligned; p += 16) {
0676 const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
0677 uint8x16_t x = vceqq_u8(s, s0);
0678 x = vorrq_u8(x, vceqq_u8(s, s1));
0679 x = vorrq_u8(x, vceqq_u8(s, s2));
0680 x = vorrq_u8(x, vcltq_u8(s, s3));
0681
0682 x = vrev64q_u8(x);
0683 uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);
0684 uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);
0685
0686 SizeType len = 0;
0687 bool escaped = false;
0688 if (low == 0) {
0689 if (high != 0) {
0690 uint32_t lz = internal::clzll(high);
0691 len = 8 + (lz >> 3);
0692 escaped = true;
0693 }
0694 } else {
0695 uint32_t lz = internal::clzll(low);
0696 len = lz >> 3;
0697 escaped = true;
0698 }
0699 if (RAPIDJSON_UNLIKELY(escaped)) {
0700 char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
0701 for (size_t i = 0; i < len; i++)
0702 q[i] = p[i];
0703
0704 p += len;
0705 break;
0706 }
0707 vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
0708 }
0709
0710 is.src_ = p;
0711 return RAPIDJSON_LIKELY(is.Tell() < length);
0712 }
0713 #endif
0714
0715 RAPIDJSON_NAMESPACE_END
0716
0717 #if defined(_MSC_VER) || defined(__clang__)
0718 RAPIDJSON_DIAG_POP
0719 #endif
0720
0721 #endif