writer.h
Go to the documentation of this file.
1 // Tencent is pleased to support the open source community by making RapidJSON
2 // available.
3 //
4 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All
5 // rights reserved.
6 //
7 // Licensed under the MIT License (the "License"); you may not use this file
8 // except in compliance with the License. You may obtain a copy of the License
9 // at
10 //
11 // http://opensource.org/licenses/MIT
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 // License for the specific language governing permissions and limitations under
17 // the License.
18 
19 #ifndef RAPIDJSON_WRITER_H_
20 #define RAPIDJSON_WRITER_H_
21 
22 #include <new> // placement new
23 #include "internal/clzll.h"
24 #include "internal/dtoa.h"
25 #include "internal/itoa.h"
26 #include "internal/meta.h"
27 #include "internal/stack.h"
28 #include "internal/strfunc.h"
29 #include "stream.h"
30 #include "stringbuffer.h"
31 
32 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
33 #include <intrin.h>
34 #pragma intrinsic(_BitScanForward)
35 #endif
36 #ifdef RAPIDJSON_SSE42
37 #include <nmmintrin.h>
38 #elif defined(RAPIDJSON_SSE2)
39 #include <emmintrin.h>
40 #elif defined(RAPIDJSON_NEON)
41 #include <arm_neon.h>
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 #elif defined(_MSC_VER)
50 RAPIDJSON_DIAG_PUSH
51 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
52 #endif
53 
55 
57 // WriteFlag
58 
65 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
66 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
67 #endif
68 
70 enum WriteFlag {
76 };
79 
81 
98 template <typename OutputStream, typename SourceEncoding = UTF8<>,
99  typename TargetEncoding = UTF8<>,
100  typename StackAllocator = CrtAllocator,
101  unsigned writeFlags = kWriteDefaultFlags>
102 class Writer {
103  public:
104  typedef typename SourceEncoding::Ch Ch;
105 
106  static const int kDefaultMaxDecimalPlaces = 324;
107 
109 
113  explicit Writer(OutputStream &os, StackAllocator *stackAllocator = 0,
114  size_t levelDepth = kDefaultLevelDepth)
115  : os_(&os),
116  level_stack_(stackAllocator, levelDepth * sizeof(Level)),
117  maxDecimalPlaces_(kDefaultMaxDecimalPlaces),
118  hasRoot_(false) {}
119 
120  explicit Writer(StackAllocator *allocator = 0,
121  size_t levelDepth = kDefaultLevelDepth)
122  : os_(0),
123  level_stack_(allocator, levelDepth * sizeof(Level)),
124  maxDecimalPlaces_(kDefaultMaxDecimalPlaces),
125  hasRoot_(false) {}
126 
127 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
128  Writer(Writer &&rhs)
129  : os_(rhs.os_),
130  level_stack_(std::move(rhs.level_stack_)),
131  maxDecimalPlaces_(rhs.maxDecimalPlaces_),
132  hasRoot_(rhs.hasRoot_) {
133  rhs.os_ = 0;
134  }
135 #endif
136 
138 
155  void Reset(OutputStream &os) {
156  os_ = &os;
157  hasRoot_ = false;
159  }
160 
162 
165  bool IsComplete() const { return hasRoot_ && level_stack_.Empty(); }
166 
167  int GetMaxDecimalPlaces() const { return maxDecimalPlaces_; }
168 
170 
191  void SetMaxDecimalPlaces(int maxDecimalPlaces) {
192  maxDecimalPlaces_ = maxDecimalPlaces;
193  }
194 
199 
200  bool Null() {
201  Prefix(kNullType);
202  return EndValue(WriteNull());
203  }
204  bool Bool(bool b) {
205  Prefix(b ? kTrueType : kFalseType);
206  return EndValue(WriteBool(b));
207  }
208  bool Int(int i) {
210  return EndValue(WriteInt(i));
211  }
212  bool Uint(unsigned u) {
214  return EndValue(WriteUint(u));
215  }
216  bool Int64(int64_t i64) {
218  return EndValue(WriteInt64(i64));
219  }
220  bool Uint64(uint64_t u64) {
222  return EndValue(WriteUint64(u64));
223  }
224 
226 
230  bool Double(double d) {
232  return EndValue(WriteDouble(d));
233  }
234 
235  bool RawNumber(const Ch *str, SizeType length, bool copy = false) {
236  RAPIDJSON_ASSERT(str != 0);
237  (void)copy;
239  return EndValue(WriteString(str, length));
240  }
241 
242  bool String(const Ch *str, SizeType length, bool copy = false) {
243  RAPIDJSON_ASSERT(str != 0);
244  (void)copy;
246  return EndValue(WriteString(str, length));
247  }
248 
249 #if RAPIDJSON_HAS_STDSTRING
250  bool String(const std::basic_string<Ch> &str) {
251  return String(str.data(), SizeType(str.size()));
252  }
253 #endif
254 
255  bool StartObject() {
257  new (level_stack_.template Push<Level>()) Level(false);
258  return WriteStartObject();
259  }
260 
261  bool Key(const Ch *str, SizeType length, bool copy = false) {
262  return String(str, length, copy);
263  }
264 
265 #if RAPIDJSON_HAS_STDSTRING
266  bool Key(const std::basic_string<Ch> &str) {
267  return Key(str.data(), SizeType(str.size()));
268  }
269 #endif
270 
271  bool EndObject(SizeType memberCount = 0) {
272  (void)memberCount;
274  sizeof(Level)); // not inside an Object
275  RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()
276  ->inArray); // currently inside an Array, not Object
277  RAPIDJSON_ASSERT(0 ==
278  level_stack_.template Top<Level>()->valueCount %
279  2); // Object has a Key without a Value
280  level_stack_.template Pop<Level>(1);
281  return EndValue(WriteEndObject());
282  }
283 
284  bool StartArray() {
286  new (level_stack_.template Push<Level>()) Level(true);
287  return WriteStartArray();
288  }
289 
290  bool EndArray(SizeType elementCount = 0) {
291  (void)elementCount;
293  RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
294  level_stack_.template Pop<Level>(1);
295  return EndValue(WriteEndArray());
296  }
298 
301 
303  bool String(const Ch *const &str) {
304  return String(str, internal::StrLen(str));
305  }
306  bool Key(const Ch *const &str) { return Key(str, internal::StrLen(str)); }
307 
309 
311 
318  bool RawValue(const Ch *json, size_t length, Type type) {
319  RAPIDJSON_ASSERT(json != 0);
320  Prefix(type);
321  return EndValue(WriteRawValue(json, length));
322  }
323 
325 
328  void Flush() { os_->Flush(); }
329 
330  protected:
332  struct Level {
333  Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
334  size_t valueCount;
335  bool inArray;
336  };
337 
338  static const size_t kDefaultLevelDepth = 32;
339 
340  bool WriteNull() {
341  PutReserve(*os_, 4);
342  PutUnsafe(*os_, 'n');
343  PutUnsafe(*os_, 'u');
344  PutUnsafe(*os_, 'l');
345  PutUnsafe(*os_, 'l');
346  return true;
347  }
348 
349  bool WriteBool(bool b) {
350  if (b) {
351  PutReserve(*os_, 4);
352  PutUnsafe(*os_, 't');
353  PutUnsafe(*os_, 'r');
354  PutUnsafe(*os_, 'u');
355  PutUnsafe(*os_, 'e');
356  } else {
357  PutReserve(*os_, 5);
358  PutUnsafe(*os_, 'f');
359  PutUnsafe(*os_, 'a');
360  PutUnsafe(*os_, 'l');
361  PutUnsafe(*os_, 's');
362  PutUnsafe(*os_, 'e');
363  }
364  return true;
365  }
366 
367  bool WriteInt(int i) {
368  char buffer[11];
369  const char *end = internal::i32toa(i, buffer);
370  PutReserve(*os_, static_cast<size_t>(end - buffer));
371  for (const char *p = buffer; p != end; ++p)
372  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
373  return true;
374  }
375 
376  bool WriteUint(unsigned u) {
377  char buffer[10];
378  const char *end = internal::u32toa(u, buffer);
379  PutReserve(*os_, static_cast<size_t>(end - buffer));
380  for (const char *p = buffer; p != end; ++p)
381  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
382  return true;
383  }
384 
385  bool WriteInt64(int64_t i64) {
386  char buffer[21];
387  const char *end = internal::i64toa(i64, buffer);
388  PutReserve(*os_, static_cast<size_t>(end - buffer));
389  for (const char *p = buffer; p != end; ++p)
390  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
391  return true;
392  }
393 
394  bool WriteUint64(uint64_t u64) {
395  char buffer[20];
396  char *end = internal::u64toa(u64, buffer);
397  PutReserve(*os_, static_cast<size_t>(end - buffer));
398  for (char *p = buffer; p != end; ++p)
399  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
400  return true;
401  }
402 
403  bool WriteDouble(double d) {
404  if (internal::Double(d).IsNanOrInf()) {
405  if (!(writeFlags & kWriteNanAndInfFlag)) return false;
406  if (internal::Double(d).IsNan()) {
407  PutReserve(*os_, 3);
408  PutUnsafe(*os_, 'N');
409  PutUnsafe(*os_, 'a');
410  PutUnsafe(*os_, 'N');
411  return true;
412  }
413  if (internal::Double(d).Sign()) {
414  PutReserve(*os_, 9);
415  PutUnsafe(*os_, '-');
416  } else
417  PutReserve(*os_, 8);
418  PutUnsafe(*os_, 'I');
419  PutUnsafe(*os_, 'n');
420  PutUnsafe(*os_, 'f');
421  PutUnsafe(*os_, 'i');
422  PutUnsafe(*os_, 'n');
423  PutUnsafe(*os_, 'i');
424  PutUnsafe(*os_, 't');
425  PutUnsafe(*os_, 'y');
426  return true;
427  }
428 
429  char buffer[25];
430  char *end = internal::dtoa(d, buffer, maxDecimalPlaces_);
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 WriteString(const Ch *str, SizeType length) {
438  static const typename OutputStream::Ch hexDigits[16] = {
439  '0', '1', '2', '3', '4', '5', '6', '7',
440  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
441  static const char escape[256] = {
442 #define Z16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
443  // 0 1 2 3 4 5 6 7 8 9 A B C D E
444  // F
445  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't',
446  'n', 'u', 'f', 'r', 'u', 'u', // 00
447  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
448  'u', 'u', 'u', 'u', 'u', 'u', // 10
449  0, 0, '"', 0, 0, 0, 0, 0, 0, 0,
450  0, 0, 0, 0, 0, 0, // 20
451  Z16, Z16, // 30~4F
452  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
453  0, 0, '\\', 0, 0, 0, // 50
454  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
455 #undef Z16
456  };
457 
458  if (TargetEncoding::supportUnicode)
459  PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
460  else
461  PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
462 
463  PutUnsafe(*os_, '\"');
465  while (ScanWriteUnescapedString(is, length)) {
466  const Ch c = is.Peek();
467  if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
468  // Unicode escaping
469  unsigned codepoint;
470  if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
471  return false;
472  PutUnsafe(*os_, '\\');
473  PutUnsafe(*os_, 'u');
474  if (codepoint <= 0xD7FF ||
475  (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
476  PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
477  PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
478  PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
479  PutUnsafe(*os_, hexDigits[(codepoint)&15]);
480  } else {
481  RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
482  // Surrogate pair
483  unsigned s = codepoint - 0x010000;
484  unsigned lead = (s >> 10) + 0xD800;
485  unsigned trail = (s & 0x3FF) + 0xDC00;
486  PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
487  PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
488  PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
489  PutUnsafe(*os_, hexDigits[(lead)&15]);
490  PutUnsafe(*os_, '\\');
491  PutUnsafe(*os_, 'u');
492  PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
493  PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
494  PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
495  PutUnsafe(*os_, hexDigits[(trail)&15]);
496  }
497  } else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) &&
498  RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
499  is.Take();
500  PutUnsafe(*os_, '\\');
501  PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(
502  escape[static_cast<unsigned char>(c)]));
503  if (escape[static_cast<unsigned char>(c)] == 'u') {
504  PutUnsafe(*os_, '0');
505  PutUnsafe(*os_, '0');
506  PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
507  PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
508  }
509  } else if (RAPIDJSON_UNLIKELY(!(
510  writeFlags & kWriteValidateEncodingFlag
512  is, *os_)
513  : Transcoder<SourceEncoding,
514  TargetEncoding>::TranscodeUnsafe(is,
515  *os_))))
516  return false;
517  }
518  PutUnsafe(*os_, '\"');
519  return true;
520  }
521 
523  size_t length) {
524  return RAPIDJSON_LIKELY(is.Tell() < length);
525  }
526 
528  os_->Put('{');
529  return true;
530  }
531  bool WriteEndObject() {
532  os_->Put('}');
533  return true;
534  }
536  os_->Put('[');
537  return true;
538  }
539  bool WriteEndArray() {
540  os_->Put(']');
541  return true;
542  }
543 
544  bool WriteRawValue(const Ch *json, size_t length) {
545  PutReserve(*os_, length);
547  while (RAPIDJSON_LIKELY(is.Tell() < length)) {
548  RAPIDJSON_ASSERT(is.Peek() != '\0');
549  if (RAPIDJSON_UNLIKELY(!(
550  writeFlags & kWriteValidateEncodingFlag
552  *os_)
554  is, *os_))))
555  return false;
556  }
557  return true;
558  }
559 
560  void Prefix(Type type) {
561  (void)type;
563  0)) { // this value is not at root
564  Level *level = level_stack_.template Top<Level>();
565  if (level->valueCount > 0) {
566  if (level->inArray)
567  os_->Put(','); // add comma if it is not the first element in array
568  else // in object
569  os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
570  }
571  if (!level->inArray && level->valueCount % 2 == 0)
572  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even
573  // number should be a name
574  level->valueCount++;
575  } else {
576  RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
577  hasRoot_ = true;
578  }
579  }
580 
581  // Flush the value if it is the top level one.
582  bool EndValue(bool ret) {
583  if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
584  Flush();
585  return ret;
586  }
587 
588  OutputStream *os_;
591  bool hasRoot_;
592 
593  private:
594  // Prohibit copy constructor & assignment operator.
595  Writer(const Writer &);
596  Writer &operator=(const Writer &);
597 };
598 
599 // Full specialization for StringStream to prevent memory copying
600 
601 template <>
602 inline bool Writer<StringBuffer>::WriteInt(int i) {
603  char *buffer = os_->Push(11);
604  const char *end = internal::i32toa(i, buffer);
605  os_->Pop(static_cast<size_t>(11 - (end - buffer)));
606  return true;
607 }
608 
609 template <>
610 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
611  char *buffer = os_->Push(10);
612  const char *end = internal::u32toa(u, buffer);
613  os_->Pop(static_cast<size_t>(10 - (end - buffer)));
614  return true;
615 }
616 
617 template <>
619  char *buffer = os_->Push(21);
620  const char *end = internal::i64toa(i64, buffer);
621  os_->Pop(static_cast<size_t>(21 - (end - buffer)));
622  return true;
623 }
624 
625 template <>
627  char *buffer = os_->Push(20);
628  const char *end = internal::u64toa(u, buffer);
629  os_->Pop(static_cast<size_t>(20 - (end - buffer)));
630  return true;
631 }
632 
633 template <>
634 inline bool Writer<StringBuffer>::WriteDouble(double d) {
635  if (internal::Double(d).IsNanOrInf()) {
636  // Note: This code path can only be reached if
637  // (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
638  if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) return false;
639  if (internal::Double(d).IsNan()) {
640  PutReserve(*os_, 3);
641  PutUnsafe(*os_, 'N');
642  PutUnsafe(*os_, 'a');
643  PutUnsafe(*os_, 'N');
644  return true;
645  }
646  if (internal::Double(d).Sign()) {
647  PutReserve(*os_, 9);
648  PutUnsafe(*os_, '-');
649  } else
650  PutReserve(*os_, 8);
651  PutUnsafe(*os_, 'I');
652  PutUnsafe(*os_, 'n');
653  PutUnsafe(*os_, 'f');
654  PutUnsafe(*os_, 'i');
655  PutUnsafe(*os_, 'n');
656  PutUnsafe(*os_, 'i');
657  PutUnsafe(*os_, 't');
658  PutUnsafe(*os_, 'y');
659  return true;
660  }
661 
662  char *buffer = os_->Push(25);
663  char *end = internal::dtoa(d, buffer, maxDecimalPlaces_);
664  os_->Pop(static_cast<size_t>(25 - (end - buffer)));
665  return true;
666 }
667 
668 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
669 template <>
671  size_t length) {
672  if (length < 16) return RAPIDJSON_LIKELY(is.Tell() < length);
673 
674  if (!RAPIDJSON_LIKELY(is.Tell() < length)) return false;
675 
676  const char *p = is.src_;
677  const char *end = is.head_ + length;
678  const char *nextAligned = reinterpret_cast<const char *>(
679  (reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
680  const char *endAligned = reinterpret_cast<const char *>(
681  reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
682  if (nextAligned > end) return true;
683 
684  while (p != nextAligned)
685  if (*p < 0x20 || *p == '\"' || *p == '\\') {
686  is.src_ = p;
687  return RAPIDJSON_LIKELY(is.Tell() < length);
688  } else
689  os_->PutUnsafe(*p++);
690 
691  // The rest of string using SIMD
692  static const char dquote[16] = {'\"', '\"', '\"', '\"', '\"', '\"',
693  '\"', '\"', '\"', '\"', '\"', '\"',
694  '\"', '\"', '\"', '\"'};
695  static const char bslash[16] = {'\\', '\\', '\\', '\\', '\\', '\\',
696  '\\', '\\', '\\', '\\', '\\', '\\',
697  '\\', '\\', '\\', '\\'};
698  static const char space[16] = {0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
699  0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
700  0x1F, 0x1F, 0x1F, 0x1F};
701  const __m128i dq =
702  _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
703  const __m128i bs =
704  _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
705  const __m128i sp =
706  _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
707 
708  for (; p != endAligned; p += 16) {
709  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
710  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
711  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
712  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp),
713  sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
714  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
715  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
716  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
717  SizeType len;
718 #ifdef _MSC_VER // Find the index of first escaped
719  unsigned long offset;
720  _BitScanForward(&offset, r);
721  len = offset;
722 #else
723  len = static_cast<SizeType>(__builtin_ffs(r) - 1);
724 #endif
725  char *q = reinterpret_cast<char *>(os_->PushUnsafe(len));
726  for (size_t i = 0; i < len; i++) q[i] = p[i];
727 
728  p += len;
729  break;
730  }
731  _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
732  }
733 
734  is.src_ = p;
735  return RAPIDJSON_LIKELY(is.Tell() < length);
736 }
737 #elif defined(RAPIDJSON_NEON)
738 template <>
740  size_t length) {
741  if (length < 16) return RAPIDJSON_LIKELY(is.Tell() < length);
742 
743  if (!RAPIDJSON_LIKELY(is.Tell() < length)) return false;
744 
745  const char *p = is.src_;
746  const char *end = is.head_ + length;
747  const char *nextAligned = reinterpret_cast<const char *>(
748  (reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
749  const char *endAligned = reinterpret_cast<const char *>(
750  reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
751  if (nextAligned > end) return true;
752 
753  while (p != nextAligned)
754  if (*p < 0x20 || *p == '\"' || *p == '\\') {
755  is.src_ = p;
756  return RAPIDJSON_LIKELY(is.Tell() < length);
757  } else
758  os_->PutUnsafe(*p++);
759 
760  // The rest of string using SIMD
761  const uint8x16_t s0 = vmovq_n_u8('"');
762  const uint8x16_t s1 = vmovq_n_u8('\\');
763  const uint8x16_t s2 = vmovq_n_u8('\b');
764  const uint8x16_t s3 = vmovq_n_u8(32);
765 
766  for (; p != endAligned; p += 16) {
767  const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
768  uint8x16_t x = vceqq_u8(s, s0);
769  x = vorrq_u8(x, vceqq_u8(s, s1));
770  x = vorrq_u8(x, vceqq_u8(s, s2));
771  x = vorrq_u8(x, vcltq_u8(s, s3));
772 
773  x = vrev64q_u8(x); // Rev in 64
774  uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
775  uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
776 
777  SizeType len = 0;
778  bool escaped = false;
779  if (low == 0) {
780  if (high != 0) {
781  uint32_t lz = RAPIDJSON_CLZLL(high);
782  len = 8 + (lz >> 3);
783  escaped = true;
784  }
785  } else {
786  uint32_t lz = RAPIDJSON_CLZLL(low);
787  len = lz >> 3;
788  escaped = true;
789  }
790  if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
791  char *q = reinterpret_cast<char *>(os_->PushUnsafe(len));
792  for (size_t i = 0; i < len; i++) q[i] = p[i];
793 
794  p += len;
795  break;
796  }
797  vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
798  }
799 
800  is.src_ = p;
801  return RAPIDJSON_LIKELY(is.Tell() < length);
802 }
803 #endif // RAPIDJSON_NEON
804 
806 
807 #if defined(_MSC_VER) || defined(__clang__)
808 RAPIDJSON_DIAG_POP
809 #endif
810 
811 #endif // RAPIDJSON_RAPIDJSON_H_
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
Definition: writer.h:66
bool Bool(bool b)
Definition: writer.h:204
No flags are set.
Definition: writer.h:71
char * u64toa(uint64_t value, char *buffer)
Definition: itoa.h:124
bool EndValue(bool ret)
Definition: writer.h:582
Encoding conversion.
Definition: encodings.h:750
bool EndArray(SizeType elementCount=0)
Definition: writer.h:290
bool EndObject(SizeType memberCount=0)
Definition: writer.h:271
size_t valueCount
number of values in this level
Definition: writer.h:334
void Flush()
Flush the output stream.
Definition: writer.h:328
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:411
bool inArray
true if in array, otherwise in object
Definition: writer.h:335
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:433
bool WriteInt64(int64_t i64)
Definition: writer.h:385
bool String(const Ch *const &str)
Simpler but slower overload.
Definition: writer.h:303
JSON writer.
Definition: fwd.h:110
object
Definition: rapidjson.h:711
Read-only string stream.
Definition: fwd.h:60
bool WriteUint64(uint64_t u64)
Definition: writer.h:394
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:131
static const size_t kDefaultLevelDepth
Definition: writer.h:338
array
Definition: rapidjson.h:712
bool Int64(int64_t i64)
Definition: writer.h:216
XmlRpcServer s
Writer(StackAllocator *allocator=0, size_t levelDepth=kDefaultLevelDepth)
Definition: writer.h:120
const Ch * src_
Current read position.
Definition: stream.h:180
bool WriteRawValue(const Ch *json, size_t length)
Definition: writer.h:544
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:318
bool Uint64(uint64_t u64)
Definition: writer.h:220
int GetMaxDecimalPlaces() const
Definition: writer.h:167
bool hasRoot_
Definition: writer.h:591
false
Definition: rapidjson.h:709
bool Int(int i)
Definition: writer.h:208
bool WriteStartObject()
Definition: writer.h:527
bool Empty() const
Definition: stack.h:190
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:230
Validate encoding of JSON strings.
Definition: writer.h:72
Ch Peek() const
Definition: stream.h:165
void Clear()
Definition: stack.h:104
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:128
bool ScanWriteUnescapedString(GenericStringStream< SourceEncoding > &is, size_t length)
Definition: writer.h:522
bool String(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:242
bool WriteUint(unsigned u)
Definition: writer.h:376
OutputStream * os_
Definition: writer.h:588
SourceEncoding::Ch Ch
Definition: writer.h:104
Information for each nested level.
Definition: writer.h:332
string
Definition: rapidjson.h:713
bool Null()
Definition: writer.h:200
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
Definition: stream.h:91
unsigned int uint32_t
Definition: stdint.h:127
bool WriteNull()
Definition: writer.h:340
unsigned __int64 uint64_t
Definition: stdint.h:137
number
Definition: rapidjson.h:714
size_t GetSize() const
Definition: stack.h:191
TFSIMD_FORCE_INLINE const tfScalar & x() const
Level(bool inArray_)
Definition: writer.h:333
bool Key(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:261
char * u32toa(uint32_t value, char *buffer)
Definition: itoa.h:46
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:495
void Prefix(Type type)
Definition: writer.h:560
bool WriteEndObject()
Definition: writer.h:531
#define Z16
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:113
#define RAPIDJSON_CLZLL
Definition: clzll.h:70
bool WriteString(const Ch *str, SizeType length)
Definition: writer.h:437
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:165
signed __int64 int64_t
Definition: stdint.h:136
bool WriteEndArray()
Definition: writer.h:539
WriteFlag
Combination of writeFlags.
Definition: writer.h:70
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition: writer.h:191
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
Definition: stream.h:98
bool Key(const Ch *const &str)
Definition: writer.h:306
int maxDecimalPlaces_
Definition: writer.h:590
true
Definition: rapidjson.h:710
bool WriteStartArray()
Definition: writer.h:535
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:155
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
Definition: strfunc.h:36
bool StartObject()
Definition: writer.h:255
Allow writing of Infinity, -Infinity and NaN.
Definition: writer.h:73
internal::Stack< StackAllocator > level_stack_
Definition: writer.h:589
bool StartArray()
Definition: writer.h:284
bool WriteDouble(double d)
Definition: writer.h:403
bool Uint(unsigned u)
Definition: writer.h:212
Type
Type of JSON value.
Definition: rapidjson.h:707
size_t Tell() const
Definition: stream.h:167
char * i64toa(int64_t value, char *buffer)
Definition: itoa.h:274
bool RawNumber(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:235
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:508
char * i32toa(int32_t value, char *buffer)
Definition: itoa.h:113
bool WriteInt(int i)
Definition: writer.h:367
char * dtoa(double value, char *buffer, int maxDecimalPlaces=324)
Definition: dtoa.h:242
static const int kDefaultMaxDecimalPlaces
Definition: writer.h:106
Writer & operator=(const Writer &)
null
Definition: rapidjson.h:708
bool WriteBool(bool b)
Definition: writer.h:349
const Ch * head_
Original head of the string.
Definition: stream.h:181


livox_ros_driver
Author(s): Livox Dev Team
autogenerated on Mon Mar 15 2021 02:40:46