writer.h
Go to the documentation of this file.
1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // http://opensource.org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #ifndef RAPIDJSON_WRITER_H_
16 #define RAPIDJSON_WRITER_H_
17 
18 #include "stream.h"
19 #include "internal/meta.h"
20 #include "internal/stack.h"
21 #include "internal/strfunc.h"
22 #include "internal/dtoa.h"
23 #include "internal/itoa.h"
24 #include "stringbuffer.h"
25 #include <new> // placement new
26 
27 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
28 #include <intrin.h>
29 #pragma intrinsic(_BitScanForward)
30 #endif
31 #ifdef RAPIDJSON_SSE42
32 #include <nmmintrin.h>
33 #elif defined(RAPIDJSON_SSE2)
34 #include <emmintrin.h>
35 #elif defined(RAPIDJSON_NEON)
36 #include <arm_neon.h>
37 #endif
38 
39 #ifdef _MSC_VER
40 RAPIDJSON_DIAG_PUSH
41 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
42 #endif
43 
44 #ifdef __clang__
45 RAPIDJSON_DIAG_PUSH
46 RAPIDJSON_DIAG_OFF(padded)
47 RAPIDJSON_DIAG_OFF(unreachable-code)
48 RAPIDJSON_DIAG_OFF(c++98-compat)
49 #endif
50 
52 
54 // WriteFlag
55 
62 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
63 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
64 #endif
65 
67 enum WriteFlag {
72 };
73 
75 
90 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
91 class Writer {
92 public:
93  typedef typename SourceEncoding::Ch Ch;
94 
95  static const int kDefaultMaxDecimalPlaces = 324;
96 
98 
102  explicit
103  Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
104  os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
105 
106  explicit
107  Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
108  os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
109 
110 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
111  Writer(Writer&& rhs) :
112  os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
113  rhs.os_ = 0;
114  }
115 #endif
116 
118 
135  void Reset(OutputStream& os) {
136  os_ = &os;
137  hasRoot_ = false;
139  }
140 
142 
145  bool IsComplete() const {
146  return hasRoot_ && level_stack_.Empty();
147  }
148 
149  int GetMaxDecimalPlaces() const {
150  return maxDecimalPlaces_;
151  }
152 
154 
174  void SetMaxDecimalPlaces(int maxDecimalPlaces) {
175  maxDecimalPlaces_ = maxDecimalPlaces;
176  }
177 
182 
183  bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
184  bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
185  bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
186  bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
187  bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
188  bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
189 
191 
195  bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
196 
197  bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
198  RAPIDJSON_ASSERT(str != 0);
199  (void)copy;
201  return EndValue(WriteString(str, length));
202  }
203 
204  bool String(const Ch* str, SizeType length, bool copy = false) {
205  RAPIDJSON_ASSERT(str != 0);
206  (void)copy;
208  return EndValue(WriteString(str, length));
209  }
210 
211 #if RAPIDJSON_HAS_STDSTRING
212  bool String(const std::basic_string<Ch>& str) {
213  return String(str.data(), SizeType(str.size()));
214  }
215 #endif
216 
217  bool StartObject() {
219  new (level_stack_.template Push<Level>()) Level(false);
220  return WriteStartObject();
221  }
222 
223  bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
224 
225 #if RAPIDJSON_HAS_STDSTRING
226  bool Key(const std::basic_string<Ch>& str)
227  {
228  return Key(str.data(), SizeType(str.size()));
229  }
230 #endif
231 
232  bool EndObject(SizeType memberCount = 0) {
233  (void)memberCount;
234  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
235  RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object
236  RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value
237  level_stack_.template Pop<Level>(1);
238  return EndValue(WriteEndObject());
239  }
240 
241  bool StartArray() {
243  new (level_stack_.template Push<Level>()) Level(true);
244  return WriteStartArray();
245  }
246 
247  bool EndArray(SizeType elementCount = 0) {
248  (void)elementCount;
250  RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
251  level_stack_.template Pop<Level>(1);
252  return EndValue(WriteEndArray());
253  }
255 
258 
260  bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }
261  bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }
262 
264 
266 
273  bool RawValue(const Ch* json, size_t length, Type type) {
274  RAPIDJSON_ASSERT(json != 0);
275  Prefix(type);
276  return EndValue(WriteRawValue(json, length));
277  }
278 
280 
283  void Flush() {
284  os_->Flush();
285  }
286 
287 protected:
289  struct Level {
290  Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
291  size_t valueCount;
292  bool inArray;
293  };
294 
295  static const size_t kDefaultLevelDepth = 32;
296 
297  bool WriteNull() {
298  PutReserve(*os_, 4);
299  PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
300  }
301 
302  bool WriteBool(bool b) {
303  if (b) {
304  PutReserve(*os_, 4);
305  PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
306  }
307  else {
308  PutReserve(*os_, 5);
309  PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
310  }
311  return true;
312  }
313 
314  bool WriteInt(int i) {
315  char buffer[11];
316  const char* end = internal::i32toa(i, buffer);
317  PutReserve(*os_, static_cast<size_t>(end - buffer));
318  for (const char* p = buffer; p != end; ++p)
319  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
320  return true;
321  }
322 
323  bool WriteUint(unsigned u) {
324  char buffer[10];
325  const char* end = internal::u32toa(u, buffer);
326  PutReserve(*os_, static_cast<size_t>(end - buffer));
327  for (const char* p = buffer; p != end; ++p)
328  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
329  return true;
330  }
331 
332  bool WriteInt64(int64_t i64) {
333  char buffer[21];
334  const char* end = internal::i64toa(i64, buffer);
335  PutReserve(*os_, static_cast<size_t>(end - buffer));
336  for (const char* p = buffer; p != end; ++p)
337  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
338  return true;
339  }
340 
341  bool WriteUint64(uint64_t u64) {
342  char buffer[20];
343  char* end = internal::u64toa(u64, buffer);
344  PutReserve(*os_, static_cast<size_t>(end - buffer));
345  for (char* p = buffer; p != end; ++p)
346  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
347  return true;
348  }
349 
350  bool WriteDouble(double d) {
351  if (internal::Double(d).IsNanOrInf()) {
352  if (!(writeFlags & kWriteNanAndInfFlag))
353  return false;
354  if (internal::Double(d).IsNan()) {
355  PutReserve(*os_, 3);
356  PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
357  return true;
358  }
359  if (internal::Double(d).Sign()) {
360  PutReserve(*os_, 9);
361  PutUnsafe(*os_, '-');
362  }
363  else
364  PutReserve(*os_, 8);
365  PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
366  PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
367  return true;
368  }
369 
370  char buffer[25];
371  char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
372  PutReserve(*os_, static_cast<size_t>(end - buffer));
373  for (char* p = buffer; p != end; ++p)
374  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
375  return true;
376  }
377 
378  bool WriteString(const Ch* str, SizeType length) {
379  static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
380  static const char escape[256] = {
381 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
382  //0 1 2 3 4 5 6 7 8 9 A B C D E F
383  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
384  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
385  0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
386  Z16, Z16, // 30~4F
387  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
388  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
389 #undef Z16
390  };
391 
392  if (TargetEncoding::supportUnicode)
393  PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
394  else
395  PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
396 
397  PutUnsafe(*os_, '\"');
399  while (ScanWriteUnescapedString(is, length)) {
400  const Ch c = is.Peek();
401  if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
402  // Unicode escaping
403  unsigned codepoint;
404  if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
405  return false;
406  PutUnsafe(*os_, '\\');
407  PutUnsafe(*os_, 'u');
408  if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
409  PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
410  PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
411  PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
412  PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
413  }
414  else {
415  RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
416  // Surrogate pair
417  unsigned s = codepoint - 0x010000;
418  unsigned lead = (s >> 10) + 0xD800;
419  unsigned trail = (s & 0x3FF) + 0xDC00;
420  PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
421  PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
422  PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
423  PutUnsafe(*os_, hexDigits[(lead ) & 15]);
424  PutUnsafe(*os_, '\\');
425  PutUnsafe(*os_, 'u');
426  PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
427  PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
428  PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
429  PutUnsafe(*os_, hexDigits[(trail ) & 15]);
430  }
431  }
432  else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
433  is.Take();
434  PutUnsafe(*os_, '\\');
435  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
436  if (escape[static_cast<unsigned char>(c)] == 'u') {
437  PutUnsafe(*os_, '0');
438  PutUnsafe(*os_, '0');
439  PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
440  PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
441  }
442  }
443  else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
446  return false;
447  }
448  PutUnsafe(*os_, '\"');
449  return true;
450  }
451 
453  return RAPIDJSON_LIKELY(is.Tell() < length);
454  }
455 
456  bool WriteStartObject() { os_->Put('{'); return true; }
457  bool WriteEndObject() { os_->Put('}'); return true; }
458  bool WriteStartArray() { os_->Put('['); return true; }
459  bool WriteEndArray() { os_->Put(']'); return true; }
460 
461  bool WriteRawValue(const Ch* json, size_t length) {
462  PutReserve(*os_, length);
463  for (size_t i = 0; i < length; i++) {
464  RAPIDJSON_ASSERT(json[i] != '\0');
465  PutUnsafe(*os_, json[i]);
466  }
467  return true;
468  }
469 
470  void Prefix(Type type) {
471  (void)type;
472  if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
473  Level* level = level_stack_.template Top<Level>();
474  if (level->valueCount > 0) {
475  if (level->inArray)
476  os_->Put(','); // add comma if it is not the first element in array
477  else // in object
478  os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
479  }
480  if (!level->inArray && level->valueCount % 2 == 0)
481  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
482  level->valueCount++;
483  }
484  else {
485  RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
486  hasRoot_ = true;
487  }
488  }
489 
490  // Flush the value if it is the top level one.
491  bool EndValue(bool ret) {
492  if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
493  Flush();
494  return ret;
495  }
496 
497  OutputStream* os_;
500  bool hasRoot_;
501 
502 private:
503  // Prohibit copy constructor & assignment operator.
504  Writer(const Writer&);
505  Writer& operator=(const Writer&);
506 };
507 
508 // Full specialization for StringStream to prevent memory copying
509 
510 template<>
511 inline bool Writer<StringBuffer>::WriteInt(int i) {
512  char *buffer = os_->Push(11);
513  const char* end = internal::i32toa(i, buffer);
514  os_->Pop(static_cast<size_t>(11 - (end - buffer)));
515  return true;
516 }
517 
518 template<>
519 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
520  char *buffer = os_->Push(10);
521  const char* end = internal::u32toa(u, buffer);
522  os_->Pop(static_cast<size_t>(10 - (end - buffer)));
523  return true;
524 }
525 
526 template<>
528  char *buffer = os_->Push(21);
529  const char* end = internal::i64toa(i64, buffer);
530  os_->Pop(static_cast<size_t>(21 - (end - buffer)));
531  return true;
532 }
533 
534 template<>
536  char *buffer = os_->Push(20);
537  const char* end = internal::u64toa(u, buffer);
538  os_->Pop(static_cast<size_t>(20 - (end - buffer)));
539  return true;
540 }
541 
542 template<>
543 inline bool Writer<StringBuffer>::WriteDouble(double d) {
544  if (internal::Double(d).IsNanOrInf()) {
545  // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
547  return false;
548  if (internal::Double(d).IsNan()) {
549  PutReserve(*os_, 3);
550  PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
551  return true;
552  }
553  if (internal::Double(d).Sign()) {
554  PutReserve(*os_, 9);
555  PutUnsafe(*os_, '-');
556  }
557  else
558  PutReserve(*os_, 8);
559  PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
560  PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
561  return true;
562  }
563 
564  char *buffer = os_->Push(25);
565  char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
566  os_->Pop(static_cast<size_t>(25 - (end - buffer)));
567  return true;
568 }
569 
570 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
571 template<>
572 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
573  if (length < 16)
574  return RAPIDJSON_LIKELY(is.Tell() < length);
575 
576  if (!RAPIDJSON_LIKELY(is.Tell() < length))
577  return false;
578 
579  const char* p = is.src_;
580  const char* end = is.head_ + length;
581  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
582  const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
583  if (nextAligned > end)
584  return true;
585 
586  while (p != nextAligned)
587  if (*p < 0x20 || *p == '\"' || *p == '\\') {
588  is.src_ = p;
589  return RAPIDJSON_LIKELY(is.Tell() < length);
590  }
591  else
592  os_->PutUnsafe(*p++);
593 
594  // The rest of string using SIMD
595  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
596  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
597  static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
598  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
599  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
600  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
601 
602  for (; p != endAligned; p += 16) {
603  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
604  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
605  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
606  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
607  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
608  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
609  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
610  SizeType len;
611 #ifdef _MSC_VER // Find the index of first escaped
612  unsigned long offset;
613  _BitScanForward(&offset, r);
614  len = offset;
615 #else
616  len = static_cast<SizeType>(__builtin_ffs(r) - 1);
617 #endif
618  char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
619  for (size_t i = 0; i < len; i++)
620  q[i] = p[i];
621 
622  p += len;
623  break;
624  }
625  _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
626  }
627 
628  is.src_ = p;
629  return RAPIDJSON_LIKELY(is.Tell() < length);
630 }
631 #elif defined(RAPIDJSON_NEON)
632 template<>
633 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
634  if (length < 16)
635  return RAPIDJSON_LIKELY(is.Tell() < length);
636 
637  if (!RAPIDJSON_LIKELY(is.Tell() < length))
638  return false;
639 
640  const char* p = is.src_;
641  const char* end = is.head_ + length;
642  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
643  const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
644  if (nextAligned > end)
645  return true;
646 
647  while (p != nextAligned)
648  if (*p < 0x20 || *p == '\"' || *p == '\\') {
649  is.src_ = p;
650  return RAPIDJSON_LIKELY(is.Tell() < length);
651  }
652  else
653  os_->PutUnsafe(*p++);
654 
655  // The rest of string using SIMD
656  const uint8x16_t s0 = vmovq_n_u8('"');
657  const uint8x16_t s1 = vmovq_n_u8('\\');
658  const uint8x16_t s2 = vmovq_n_u8('\b');
659  const uint8x16_t s3 = vmovq_n_u8(32);
660 
661  for (; p != endAligned; p += 16) {
662  const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
663  uint8x16_t x = vceqq_u8(s, s0);
664  x = vorrq_u8(x, vceqq_u8(s, s1));
665  x = vorrq_u8(x, vceqq_u8(s, s2));
666  x = vorrq_u8(x, vcltq_u8(s, s3));
667 
668  x = vrev64q_u8(x); // Rev in 64
669  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
670  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
671 
672  SizeType len = 0;
673  bool escaped = false;
674  if (low == 0) {
675  if (high != 0) {
676  unsigned lz = (unsigned)__builtin_clzll(high);
677  len = 8 + (lz >> 3);
678  escaped = true;
679  }
680  } else {
681  unsigned lz = (unsigned)__builtin_clzll(low);
682  len = lz >> 3;
683  escaped = true;
684  }
685  if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
686  char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
687  for (size_t i = 0; i < len; i++)
688  q[i] = p[i];
689 
690  p += len;
691  break;
692  }
693  vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
694  }
695 
696  is.src_ = p;
697  return RAPIDJSON_LIKELY(is.Tell() < length);
698 }
699 #endif // RAPIDJSON_NEON
700 
702 
703 #ifdef _MSC_VER
704 RAPIDJSON_DIAG_POP
705 #endif
706 
707 #ifdef __clang__
708 RAPIDJSON_DIAG_POP
709 #endif
710 
711 #endif // RAPIDJSON_RAPIDJSON_H_
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
Definition: writer.h:63
bool Bool(bool b)
Definition: writer.h:184
No flags are set.
Definition: writer.h:68
char * u64toa(uint64_t value, char *buffer)
Definition: itoa.h:123
bool EndValue(bool ret)
Definition: writer.h:491
Encoding conversion.
Definition: encodings.h:658
bool EndArray(SizeType elementCount=0)
Definition: writer.h:247
bool EndObject(SizeType memberCount=0)
Definition: writer.h:232
size_t valueCount
number of values in this level
Definition: writer.h:291
void Flush()
Flush the output stream.
Definition: writer.h:283
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:389
bool inArray
true if in array, otherwise in object
Definition: writer.h:292
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:411
bool WriteInt64(int64_t i64)
Definition: writer.h:332
bool String(const Ch *const &str)
Simpler but slower overload.
Definition: writer.h:260
JSON writer.
Definition: fwd.h:95
object
Definition: rapidjson.h:620
Read-only string stream.
Definition: fwd.h:47
bool WriteUint64(uint64_t u64)
Definition: writer.h:341
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:124
static const size_t kDefaultLevelDepth
Definition: writer.h:295
Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS. ...
Definition: writer.h:71
array
Definition: rapidjson.h:621
bool Int64(int64_t i64)
Definition: writer.h:187
XmlRpcServer s
Writer(StackAllocator *allocator=0, size_t levelDepth=kDefaultLevelDepth)
Definition: writer.h:107
const Ch * src_
Current read position.
Definition: stream.h:124
bool WriteRawValue(const Ch *json, size_t length)
Definition: writer.h:461
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:273
bool Uint64(uint64_t u64)
Definition: writer.h:188
int GetMaxDecimalPlaces() const
Definition: writer.h:149
bool hasRoot_
Definition: writer.h:500
false
Definition: rapidjson.h:618
bool Int(int i)
Definition: writer.h:185
bool WriteStartObject()
Definition: writer.h:456
bool Empty() const
Definition: stack.h:176
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:195
Validate encoding of JSON strings.
Definition: writer.h:69
Ch Peek() const
Definition: stream.h:115
void Clear()
Definition: stack.h:98
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:121
bool ScanWriteUnescapedString(GenericStringStream< SourceEncoding > &is, size_t length)
Definition: writer.h:452
bool String(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:204
bool WriteUint(unsigned u)
Definition: writer.h:323
OutputStream * os_
Definition: writer.h:497
SourceEncoding::Ch Ch
Definition: writer.h:93
Information for each nested level.
Definition: writer.h:289
string
Definition: rapidjson.h:622
bool Null()
Definition: writer.h:183
static const char json[]
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
Definition: stream.h:84
bool WriteNull()
Definition: writer.h:297
unsigned __int64 uint64_t
Definition: stdint.h:136
number
Definition: rapidjson.h:623
size_t GetSize() const
Definition: stack.h:177
Level(bool inArray_)
Definition: writer.h:290
bool Key(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:223
char * u32toa(uint32_t value, char *buffer)
Definition: itoa.h:39
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:468
void Prefix(Type type)
Definition: writer.h:470
bool WriteEndObject()
Definition: writer.h:457
#define Z16
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:103
Level
bool WriteString(const Ch *str, SizeType length)
Definition: writer.h:378
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:145
signed __int64 int64_t
Definition: stdint.h:135
bool WriteEndArray()
Definition: writer.h:459
WriteFlag
Combination of writeFlags.
Definition: writer.h:67
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition: writer.h:174
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
Definition: stream.h:91
bool Key(const Ch *const &str)
Definition: writer.h:261
int maxDecimalPlaces_
Definition: writer.h:499
true
Definition: rapidjson.h:619
bool WriteStartArray()
Definition: writer.h:458
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:135
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
Definition: strfunc.h:31
bool StartObject()
Definition: writer.h:217
Allow writing of Infinity, -Infinity and NaN.
Definition: writer.h:70
internal::Stack< StackAllocator > level_stack_
Definition: writer.h:498
bool StartArray()
Definition: writer.h:241
bool WriteDouble(double d)
Definition: writer.h:350
bool Uint(unsigned u)
Definition: writer.h:186
Type
Type of JSON value.
Definition: rapidjson.h:616
size_t Tell() const
Definition: stream.h:117
char * i64toa(int64_t value, char *buffer)
Definition: itoa.h:291
bool RawNumber(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:197
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:481
char * i32toa(int32_t value, char *buffer)
Definition: itoa.h:113
bool WriteInt(int i)
Definition: writer.h:314
char * dtoa(double value, char *buffer, int maxDecimalPlaces=324)
Definition: dtoa.h:216
static const int kDefaultMaxDecimalPlaces
Definition: writer.h:95
Writer & operator=(const Writer &)
null
Definition: rapidjson.h:617
bool WriteBool(bool b)
Definition: writer.h:302
const Ch * head_
Original head of the string.
Definition: stream.h:125


choreo_rapidjson
Author(s):
autogenerated on Thu Jul 18 2019 03:59:09