/home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-composable-kernel/checkouts/develop/include/rapidjson/writer.h Source File

/home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-composable-kernel/checkouts/develop/include/rapidjson/writer.h Source File#

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