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 #if 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 #if __clang__
40 RAPIDJSON_DIAG_PUSH
41 RAPIDJSON_DIAG_OFF(padded)
42 RAPIDJSON_DIAG_OFF(unreachable - code)
43 RAPIDJSON_DIAG_OFF(c++ 98 - compat)
44 #elif defined(_MSC_VER)
45 RAPIDJSON_DIAG_PUSH
46 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
47 #endif
48 
50 
52 // WriteFlag
53 
60 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
61 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
62 #endif
63 
66 {
71 };
73 
75 
90 template <typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>,
91  typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
92 class Writer
93 {
94 public:
95  typedef typename SourceEncoding::Ch Ch;
96 
97  static const int kDefaultMaxDecimalPlaces = 324;
98 
100 
104  explicit Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth)
105  : os_(&os)
106  , level_stack_(stackAllocator, levelDepth * sizeof(Level))
107  , maxDecimalPlaces_(kDefaultMaxDecimalPlaces)
108  , hasRoot_(false)
109  {
110  }
111 
112  explicit Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth)
113  : os_(0)
114  , level_stack_(allocator, levelDepth * sizeof(Level))
115  , maxDecimalPlaces_(kDefaultMaxDecimalPlaces)
116  , hasRoot_(false)
117  {
118  }
119 
120 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
121  Writer(Writer&& rhs)
122  : os_(rhs.os_)
123  , level_stack_(std::move(rhs.level_stack_))
124  , maxDecimalPlaces_(rhs.maxDecimalPlaces_)
125  , hasRoot_(rhs.hasRoot_)
126  {
127  rhs.os_ = 0;
128  }
129 #endif
130 
132 
149  void Reset(OutputStream& os)
150  {
151  os_ = &os;
152  hasRoot_ = false;
154  }
155 
157 
160  bool IsComplete() const
161  {
162  return hasRoot_ && level_stack_.Empty();
163  }
164 
166  {
167  return maxDecimalPlaces_;
168  }
169 
171 
192  void SetMaxDecimalPlaces(int maxDecimalPlaces)
193  {
194  maxDecimalPlaces_ = maxDecimalPlaces;
195  }
196 
201 
202  bool Null()
203  {
204  Prefix(kNullType);
205  return EndValue(WriteNull());
206  }
207  bool Bool(bool b)
208  {
209  Prefix(b ? kTrueType : kFalseType);
210  return EndValue(WriteBool(b));
211  }
212  bool Int(int i)
213  {
215  return EndValue(WriteInt(i));
216  }
217  bool Uint(unsigned u)
218  {
220  return EndValue(WriteUint(u));
221  }
222  bool Int64(int64_t i64)
223  {
225  return EndValue(WriteInt64(i64));
226  }
227  bool Uint64(uint64_t u64)
228  {
230  return EndValue(WriteUint64(u64));
231  }
232 
234 
238  bool Double(double d)
239  {
241  return EndValue(WriteDouble(d));
242  }
243 
244  bool RawNumber(const Ch* str, SizeType length, bool copy = false)
245  {
246  RAPIDJSON_ASSERT(str != 0);
247  (void)copy;
249  return EndValue(WriteString(str, length));
250  }
251 
252  bool String(const Ch* str, SizeType length, bool copy = false)
253  {
254  RAPIDJSON_ASSERT(str != 0);
255  (void)copy;
257  return EndValue(WriteString(str, length));
258  }
259 
260 #if RAPIDJSON_HAS_STDSTRING
261  bool String(const std::basic_string<Ch>& str)
262  {
263  return String(str.data(), SizeType(str.size()));
264  }
265 #endif
266 
267  bool StartObject()
268  {
270  new (level_stack_.template Push<Level>()) Level(false);
271  return WriteStartObject();
272  }
273 
274  bool Key(const Ch* str, SizeType length, bool copy = false)
275  {
276  return String(str, length, copy);
277  }
278 
279 #if RAPIDJSON_HAS_STDSTRING
280  bool Key(const std::basic_string<Ch>& str)
281  {
282  return Key(str.data(), SizeType(str.size()));
283  }
284 #endif
285 
286  bool EndObject(SizeType memberCount = 0)
287  {
288  (void)memberCount;
289  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
290  RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object
291  RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value
292  level_stack_.template Pop<Level>(1);
293  return EndValue(WriteEndObject());
294  }
295 
296  bool StartArray()
297  {
299  new (level_stack_.template Push<Level>()) Level(true);
300  return WriteStartArray();
301  }
302 
303  bool EndArray(SizeType elementCount = 0)
304  {
305  (void)elementCount;
307  RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
308  level_stack_.template Pop<Level>(1);
309  return EndValue(WriteEndArray());
310  }
312 
315 
317  bool String(const Ch* const& str)
318  {
319  return String(str, internal::StrLen(str));
320  }
321  bool Key(const Ch* const& str)
322  {
323  return Key(str, internal::StrLen(str));
324  }
325 
327 
329 
336  bool RawValue(const Ch* json, size_t length, Type type)
337  {
338  RAPIDJSON_ASSERT(json != 0);
339  Prefix(type);
340  return EndValue(WriteRawValue(json, length));
341  }
342 
344 
347  void Flush()
348  {
349  os_->Flush();
350  }
351 
352 protected:
354  struct Level
355  {
356  Level(bool inArray_) : valueCount(0), inArray(inArray_)
357  {
358  }
359  size_t valueCount;
360  bool inArray;
361  };
362 
363  static const size_t kDefaultLevelDepth = 32;
364 
365  bool WriteNull()
366  {
367  PutReserve(*os_, 4);
368  PutUnsafe(*os_, 'n');
369  PutUnsafe(*os_, 'u');
370  PutUnsafe(*os_, 'l');
371  PutUnsafe(*os_, 'l');
372  return true;
373  }
374 
375  bool WriteBool(bool b)
376  {
377  if (b)
378  {
379  PutReserve(*os_, 4);
380  PutUnsafe(*os_, 't');
381  PutUnsafe(*os_, 'r');
382  PutUnsafe(*os_, 'u');
383  PutUnsafe(*os_, 'e');
384  }
385  else
386  {
387  PutReserve(*os_, 5);
388  PutUnsafe(*os_, 'f');
389  PutUnsafe(*os_, 'a');
390  PutUnsafe(*os_, 'l');
391  PutUnsafe(*os_, 's');
392  PutUnsafe(*os_, 'e');
393  }
394  return true;
395  }
396 
397  bool WriteInt(int i)
398  {
399  char buffer[11];
400  const char* end = internal::i32toa(i, buffer);
401  PutReserve(*os_, static_cast<size_t>(end - buffer));
402  for (const char* p = buffer; p != end; ++p)
403  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
404  return true;
405  }
406 
407  bool WriteUint(unsigned u)
408  {
409  char buffer[10];
410  const char* end = internal::u32toa(u, buffer);
411  PutReserve(*os_, static_cast<size_t>(end - buffer));
412  for (const char* p = buffer; p != end; ++p)
413  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
414  return true;
415  }
416 
417  bool WriteInt64(int64_t i64)
418  {
419  char buffer[21];
420  const char* end = internal::i64toa(i64, buffer);
421  PutReserve(*os_, static_cast<size_t>(end - buffer));
422  for (const char* p = buffer; p != end; ++p)
423  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
424  return true;
425  }
426 
428  {
429  char buffer[20];
430  char* end = internal::u64toa(u64, buffer);
431  PutReserve(*os_, static_cast<size_t>(end - buffer));
432  for (char* p = buffer; p != end; ++p)
433  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
434  return true;
435  }
436 
437  bool WriteDouble(double d)
438  {
439  if (internal::Double(d).IsNanOrInf())
440  {
441  if (!(writeFlags & kWriteNanAndInfFlag))
442  return false;
443  if (internal::Double(d).IsNan())
444  {
445  PutReserve(*os_, 3);
446  PutUnsafe(*os_, 'N');
447  PutUnsafe(*os_, 'a');
448  PutUnsafe(*os_, 'N');
449  return true;
450  }
451  if (internal::Double(d).Sign())
452  {
453  PutReserve(*os_, 9);
454  PutUnsafe(*os_, '-');
455  }
456  else
457  PutReserve(*os_, 8);
458  PutUnsafe(*os_, 'I');
459  PutUnsafe(*os_, 'n');
460  PutUnsafe(*os_, 'f');
461  PutUnsafe(*os_, 'i');
462  PutUnsafe(*os_, 'n');
463  PutUnsafe(*os_, 'i');
464  PutUnsafe(*os_, 't');
465  PutUnsafe(*os_, 'y');
466  return true;
467  }
468 
469  char buffer[25];
470  char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
471  PutReserve(*os_, static_cast<size_t>(end - buffer));
472  for (char* p = buffer; p != end; ++p)
473  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
474  return true;
475  }
476 
477  bool WriteString(const Ch* str, SizeType length)
478  {
479  static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
480  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
481  static const char escape[256] = {
482 #define Z16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
483  // 0 1 2 3 4 5 6 7 8 9 A B C D E F
484  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
485  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
486  0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
487  Z16, Z16, // 30~4F
488  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, // 50
489  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
490 #undef Z16
491  };
492 
493  if (TargetEncoding::supportUnicode)
494  PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
495  else
496  PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
497 
498  PutUnsafe(*os_, '\"');
500  while (ScanWriteUnescapedString(is, length))
501  {
502  const Ch c = is.Peek();
503  if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80)
504  {
505  // Unicode escaping
506  unsigned codepoint;
507  if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
508  return false;
509  PutUnsafe(*os_, '\\');
510  PutUnsafe(*os_, 'u');
511  if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF))
512  {
513  PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
514  PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
515  PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
516  PutUnsafe(*os_, hexDigits[(codepoint)&15]);
517  }
518  else
519  {
520  RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
521  // Surrogate pair
522  unsigned s = codepoint - 0x010000;
523  unsigned lead = (s >> 10) + 0xD800;
524  unsigned trail = (s & 0x3FF) + 0xDC00;
525  PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
526  PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
527  PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
528  PutUnsafe(*os_, hexDigits[(lead)&15]);
529  PutUnsafe(*os_, '\\');
530  PutUnsafe(*os_, 'u');
531  PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
532  PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
533  PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
534  PutUnsafe(*os_, hexDigits[(trail)&15]);
535  }
536  }
537  else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) &&
538  RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)]))
539  {
540  is.Take();
541  PutUnsafe(*os_, '\\');
542  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
543  if (escape[static_cast<unsigned char>(c)] == 'u')
544  {
545  PutUnsafe(*os_, '0');
546  PutUnsafe(*os_, '0');
547  PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
548  PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
549  }
550  }
551  else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
554  return false;
555  }
556  PutUnsafe(*os_, '\"');
557  return true;
558  }
559 
561  {
562  return RAPIDJSON_LIKELY(is.Tell() < length);
563  }
564 
566  {
567  os_->Put('{');
568  return true;
569  }
571  {
572  os_->Put('}');
573  return true;
574  }
576  {
577  os_->Put('[');
578  return true;
579  }
581  {
582  os_->Put(']');
583  return true;
584  }
585 
586  bool WriteRawValue(const Ch* json, size_t length)
587  {
588  PutReserve(*os_, length);
590  while (RAPIDJSON_LIKELY(is.Tell() < length))
591  {
592  RAPIDJSON_ASSERT(is.Peek() != '\0');
596  return false;
597  }
598  return true;
599  }
600 
601  void Prefix(Type type)
602  {
603  (void)type;
605  { // this value is not at root
606  Level* level = level_stack_.template Top<Level>();
607  if (level->valueCount > 0)
608  {
609  if (level->inArray)
610  os_->Put(','); // add comma if it is not the first element in array
611  else // in object
612  os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
613  }
614  if (!level->inArray && level->valueCount % 2 == 0)
615  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
616  level->valueCount++;
617  }
618  else
619  {
620  RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
621  hasRoot_ = true;
622  }
623  }
624 
625  // Flush the value if it is the top level one.
626  bool EndValue(bool ret)
627  {
628  if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
629  Flush();
630  return ret;
631  }
632 
633  OutputStream* os_;
636  bool hasRoot_;
637 
638 private:
639  // Prohibit copy constructor & assignment operator.
640  Writer(const Writer&);
641  Writer& operator=(const Writer&);
642 };
643 
644 // Full specialization for StringStream to prevent memory copying
645 
646 template <>
648 {
649  char* buffer = os_->Push(11);
650  const char* end = internal::i32toa(i, buffer);
651  os_->Pop(static_cast<size_t>(11 - (end - buffer)));
652  return true;
653 }
654 
655 template <>
656 inline bool Writer<StringBuffer>::WriteUint(unsigned u)
657 {
658  char* buffer = os_->Push(10);
659  const char* end = internal::u32toa(u, buffer);
660  os_->Pop(static_cast<size_t>(10 - (end - buffer)));
661  return true;
662 }
663 
664 template <>
666 {
667  char* buffer = os_->Push(21);
668  const char* end = internal::i64toa(i64, buffer);
669  os_->Pop(static_cast<size_t>(21 - (end - buffer)));
670  return true;
671 }
672 
673 template <>
675 {
676  char* buffer = os_->Push(20);
677  const char* end = internal::u64toa(u, buffer);
678  os_->Pop(static_cast<size_t>(20 - (end - buffer)));
679  return true;
680 }
681 
682 template <>
684 {
685  if (internal::Double(d).IsNanOrInf())
686  {
687  // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
689  return false;
690  if (internal::Double(d).IsNan())
691  {
692  PutReserve(*os_, 3);
693  PutUnsafe(*os_, 'N');
694  PutUnsafe(*os_, 'a');
695  PutUnsafe(*os_, 'N');
696  return true;
697  }
698  if (internal::Double(d).Sign())
699  {
700  PutReserve(*os_, 9);
701  PutUnsafe(*os_, '-');
702  }
703  else
704  PutReserve(*os_, 8);
705  PutUnsafe(*os_, 'I');
706  PutUnsafe(*os_, 'n');
707  PutUnsafe(*os_, 'f');
708  PutUnsafe(*os_, 'i');
709  PutUnsafe(*os_, 'n');
710  PutUnsafe(*os_, 'i');
711  PutUnsafe(*os_, 't');
712  PutUnsafe(*os_, 'y');
713  return true;
714  }
715 
716  char* buffer = os_->Push(25);
717  char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
718  os_->Pop(static_cast<size_t>(25 - (end - buffer)));
719  return true;
720 }
721 
722 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
723 template <>
724 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length)
725 {
726  if (length < 16)
727  return RAPIDJSON_LIKELY(is.Tell() < length);
728 
729  if (!RAPIDJSON_LIKELY(is.Tell() < length))
730  return false;
731 
732  const char* p = is.src_;
733  const char* end = is.head_ + length;
734  const char* nextAligned =
735  reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
736  const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
737  if (nextAligned > end)
738  return true;
739 
740  while (p != nextAligned)
741  if (*p < 0x20 || *p == '\"' || *p == '\\')
742  {
743  is.src_ = p;
744  return RAPIDJSON_LIKELY(is.Tell() < length);
745  }
746  else
747  os_->PutUnsafe(*p++);
748 
749  // The rest of string using SIMD
750  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"',
751  '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
752  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\',
753  '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
754  static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
755  0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
756  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0]));
757  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0]));
758  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0]));
759 
760  for (; p != endAligned; p += 16)
761  {
762  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
763  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
764  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
765  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
766  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
767  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
768  if (RAPIDJSON_UNLIKELY(r != 0))
769  { // some of characters is escaped
770  SizeType len;
771 #if _MSC_VER // Find the index of first escaped
772  unsigned long offset;
773  _BitScanForward(&offset, r);
774  len = offset;
775 #else
776  len = static_cast<SizeType>(__builtin_ffs(r) - 1);
777 #endif
778  char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
779  for (size_t i = 0; i < len; i++)
780  q[i] = p[i];
781 
782  p += len;
783  break;
784  }
785  _mm_storeu_si128(reinterpret_cast<__m128i*>(os_->PushUnsafe(16)), s);
786  }
787 
788  is.src_ = p;
789  return RAPIDJSON_LIKELY(is.Tell() < length);
790 }
791 #elif defined(RAPIDJSON_NEON)
792 template <>
793 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length)
794 {
795  if (length < 16)
796  return RAPIDJSON_LIKELY(is.Tell() < length);
797 
798  if (!RAPIDJSON_LIKELY(is.Tell() < length))
799  return false;
800 
801  const char* p = is.src_;
802  const char* end = is.head_ + length;
803  const char* nextAligned =
804  reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
805  const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
806  if (nextAligned > end)
807  return true;
808 
809  while (p != nextAligned)
810  if (*p < 0x20 || *p == '\"' || *p == '\\')
811  {
812  is.src_ = p;
813  return RAPIDJSON_LIKELY(is.Tell() < length);
814  }
815  else
816  os_->PutUnsafe(*p++);
817 
818  // The rest of string using SIMD
819  const uint8x16_t s0 = vmovq_n_u8('"');
820  const uint8x16_t s1 = vmovq_n_u8('\\');
821  const uint8x16_t s2 = vmovq_n_u8('\b');
822  const uint8x16_t s3 = vmovq_n_u8(32);
823 
824  for (; p != endAligned; p += 16)
825  {
826  const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p));
827  uint8x16_t x = vceqq_u8(s, s0);
828  x = vorrq_u8(x, vceqq_u8(s, s1));
829  x = vorrq_u8(x, vceqq_u8(s, s2));
830  x = vorrq_u8(x, vcltq_u8(s, s3));
831 
832  x = vrev64q_u8(x); // Rev in 64
833  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
834  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
835 
836  SizeType len = 0;
837  bool escaped = false;
838  if (low == 0)
839  {
840  if (high != 0)
841  {
842  unsigned lz = (unsigned)__builtin_clzll(high);
843  len = 8 + (lz >> 3);
844  escaped = true;
845  }
846  }
847  else
848  {
849  unsigned lz = (unsigned)__builtin_clzll(low);
850  len = lz >> 3;
851  escaped = true;
852  }
853  if (RAPIDJSON_UNLIKELY(escaped))
854  { // some of characters is escaped
855  char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
856  for (size_t i = 0; i < len; i++)
857  q[i] = p[i];
858 
859  p += len;
860  break;
861  }
862  vst1q_u8(reinterpret_cast<uint8_t*>(os_->PushUnsafe(16)), s);
863  }
864 
865  is.src_ = p;
866  return RAPIDJSON_LIKELY(is.Tell() < length);
867 }
868 #endif // RAPIDJSON_NEON
869 
871 
872 #if defined(_MSC_VER) || defined(__clang__)
873 RAPIDJSON_DIAG_POP
874 #endif
875 
876 #endif // RAPIDJSON_RAPIDJSON_H_
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
Definition: writer.h:61
bool Bool(bool b)
Definition: writer.h:207
No flags are set.
Definition: writer.h:67
char * u64toa(uint64_t value, char *buffer)
Definition: itoa.h:133
bool EndValue(bool ret)
Definition: writer.h:626
Encoding conversion.
Definition: encodings.h:817
bool EndArray(SizeType elementCount=0)
Definition: writer.h:303
bool EndObject(SizeType memberCount=0)
Definition: writer.h:286
size_t valueCount
number of values in this level
Definition: writer.h:359
void Flush()
Flush the output stream.
Definition: writer.h:347
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:394
bool inArray
true if in array, otherwise in object
Definition: writer.h:360
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:416
bool WriteInt64(int64_t i64)
Definition: writer.h:417
bool String(const Ch *const &str)
Simpler but slower overload.
Definition: writer.h:317
JSON writer.
Definition: fwd.h:105
object
Definition: rapidjson.h:671
Read-only string stream.
Definition: fwd.h:56
bool WriteUint64(uint64_t u64)
Definition: writer.h:427
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:126
static const size_t kDefaultLevelDepth
Definition: writer.h:363
array
Definition: rapidjson.h:672
bool Int64(int64_t i64)
Definition: writer.h:222
XmlRpcServer s
Writer(StackAllocator *allocator=0, size_t levelDepth=kDefaultLevelDepth)
Definition: writer.h:112
const Ch * src_
Current read position.
Definition: stream.h:234
bool WriteRawValue(const Ch *json, size_t length)
Definition: writer.h:586
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:336
bool Uint64(uint64_t u64)
Definition: writer.h:227
int GetMaxDecimalPlaces() const
Definition: writer.h:165
bool hasRoot_
Definition: writer.h:636
false
Definition: rapidjson.h:669
bool Int(int i)
Definition: writer.h:212
bool WriteStartObject()
Definition: writer.h:565
bool Empty() const
Definition: stack.h:208
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:238
Validate encoding of JSON strings.
Definition: writer.h:68
Ch Peek() const
Definition: stream.h:202
void Clear()
Definition: stack.h:105
#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:560
bool String(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:252
bool WriteUint(unsigned u)
Definition: writer.h:407
OutputStream * os_
Definition: writer.h:633
SourceEncoding::Ch Ch
Definition: writer.h:95
Information for each nested level.
Definition: writer.h:354
string
Definition: rapidjson.h:673
bool Null()
Definition: writer.h:202
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
Definition: stream.h:88
bool WriteNull()
Definition: writer.h:365
unsigned __int64 uint64_t
Definition: stdint.h:136
number
Definition: rapidjson.h:674
size_t GetSize() const
Definition: stack.h:212
Level(bool inArray_)
Definition: writer.h:356
bool Key(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:274
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:482
void Prefix(Type type)
Definition: writer.h:601
bool WriteEndObject()
Definition: writer.h:570
#define Z16
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:104
bool WriteString(const Ch *str, SizeType length)
Definition: writer.h:477
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:160
signed __int64 int64_t
Definition: stdint.h:135
bool WriteEndArray()
Definition: writer.h:580
WriteFlag
Combination of writeFlags.
Definition: writer.h:65
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition: writer.h:192
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
Definition: stream.h:96
bool Key(const Ch *const &str)
Definition: writer.h:321
int maxDecimalPlaces_
Definition: writer.h:635
true
Definition: rapidjson.h:670
bool WriteStartArray()
Definition: writer.h:575
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:149
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
Definition: strfunc.h:31
bool StartObject()
Definition: writer.h:267
Allow writing of Infinity, -Infinity and NaN.
Definition: writer.h:69
internal::Stack< StackAllocator > level_stack_
Definition: writer.h:634
bool StartArray()
Definition: writer.h:296
bool WriteDouble(double d)
Definition: writer.h:437
bool Uint(unsigned u)
Definition: writer.h:217
Type
Type of JSON value.
Definition: rapidjson.h:666
size_t Tell() const
Definition: stream.h:210
char * i64toa(int64_t value, char *buffer)
Definition: itoa.h:310
bool RawNumber(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:244
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:495
char * i32toa(int32_t value, char *buffer)
Definition: itoa.h:120
bool WriteInt(int i)
Definition: writer.h:397
char * dtoa(double value, char *buffer, int maxDecimalPlaces=324)
Definition: dtoa.h:274
static const int kDefaultMaxDecimalPlaces
Definition: writer.h:97
Writer & operator=(const Writer &)
null
Definition: rapidjson.h:668
bool WriteBool(bool b)
Definition: writer.h:375
const Ch * head_
Original head of the string.
Definition: stream.h:235


xbot_talker
Author(s): wangxiaoyun
autogenerated on Sat Oct 10 2020 03:27:54