writer.h
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 
51 RAPIDJSON_NAMESPACE_BEGIN
52 
53 ///////////////////////////////////////////////////////////////////////////////
54 // WriteFlag
55 
56 /*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS
57  \ingroup RAPIDJSON_CONFIG
58  \brief User-defined kWriteDefaultFlags definition.
59 
60  User can define this as any \c WriteFlag combinations.
61 */
62 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
63 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
64 #endif
65 
66 //! Combination of writeFlags
67 enum WriteFlag {
68  kWriteNoFlags = 0, //!< No flags are set.
69  kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
70  kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN.
71  kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
72 };
73 
74 //! JSON writer
75 /*! Writer implements the concept Handler.
76  It generates JSON text by events to an output os.
77 
78  User may programmatically calls the functions of a writer to generate JSON text.
79 
80  On the other side, a writer can also be passed to objects that generates events,
81 
82  for example Reader::Parse() and Document::Accept().
83 
84  \tparam OutputStream Type of output stream.
85  \tparam SourceEncoding Encoding of source string.
86  \tparam TargetEncoding Encoding of output stream.
87  \tparam StackAllocator Type of allocator for allocating memory of stack.
88  \note implements Handler concept
89 */
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 
97  //! Constructor
98  /*! \param os Output stream.
99  \param stackAllocator User supplied allocator. If it is null, it will create a private one.
100  \param levelDepth Initial capacity of stack.
101  */
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 
117  //! Reset the writer with a new stream.
118  /*!
119  This function reset the writer with a new stream and default settings,
120  in order to make a Writer object reusable for output multiple JSONs.
121 
122  \param os New output stream.
123  \code
124  Writer<OutputStream> writer(os1);
125  writer.StartObject();
126  // ...
127  writer.EndObject();
128 
129  writer.Reset(os2);
130  writer.StartObject();
131  // ...
132  writer.EndObject();
133  \endcode
134  */
135  void Reset(OutputStream& os) {
136  os_ = &os;
137  hasRoot_ = false;
138  level_stack_.Clear();
139  }
140 
141  //! Checks whether the output is a complete JSON.
142  /*!
143  A complete JSON has a complete root object or array.
144  */
145  bool IsComplete() const {
146  return hasRoot_ && level_stack_.Empty();
147  }
148 
149  int GetMaxDecimalPlaces() const {
150  return maxDecimalPlaces_;
151  }
152 
153  //! Sets the maximum number of decimal places for double output.
154  /*!
155  This setting truncates the output with specified number of decimal places.
156 
157  For example,
158 
159  \code
160  writer.SetMaxDecimalPlaces(3);
161  writer.StartArray();
162  writer.Double(0.12345); // "0.123"
163  writer.Double(0.0001); // "0.0"
164  writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent)
165  writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent)
166  writer.EndArray();
167  \endcode
168 
169  The default setting does not truncate any decimal places. You can restore to this setting by calling
170  \code
171  writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
172  \endcode
173  */
174  void SetMaxDecimalPlaces(int maxDecimalPlaces) {
175  maxDecimalPlaces_ = maxDecimalPlaces;
176  }
177 
178  /*!@name Implementation of Handler
179  \see Handler
180  */
181  //@{
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 
190  //! Writes the given \c double value to the stream
191  /*!
192  \param d The value to be written.
193  \return Whether it is succeed.
194  */
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;
200  Prefix(kNumberType);
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;
207  Prefix(kStringType);
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() {
218  Prefix(kObjectType);
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() {
242  Prefix(kArrayType);
243  new (level_stack_.template Push<Level>()) Level(true);
244  return WriteStartArray();
245  }
246 
247  bool EndArray(SizeType elementCount = 0) {
248  (void)elementCount;
249  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
250  RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
251  level_stack_.template Pop<Level>(1);
252  return EndValue(WriteEndArray());
253  }
254  //@}
255 
256  /*! @name Convenience extensions */
257  //@{
258 
259  //! Simpler but slower overload.
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 
263  //@}
264 
265  //! Write a raw JSON value.
266  /*!
267  For user to write a stringified JSON as a value.
268 
269  \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
270  \param length Length of the json.
271  \param type Type of the root of json.
272  */
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 
279  //! Flush the output stream.
280  /*!
281  Allows the user to flush the output stream immediately.
282  */
283  void Flush() {
284  os_->Flush();
285  }
286 
287 protected:
288  //! Information for each nested level
289  struct Level {
290  Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
291  size_t valueCount; //!< number of values in this level
292  bool inArray; //!< true if in array, otherwise in object
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 
452  bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
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);
464  while (RAPIDJSON_LIKELY(is.Tell() < length)) {
465  const Ch c = is.Peek();
466  RAPIDJSON_ASSERT(c != '\0');
467  if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
470  return false;
471  }
472  return true;
473  }
474 
475  void Prefix(Type type) {
476  (void)type;
477  if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
478  Level* level = level_stack_.template Top<Level>();
479  if (level->valueCount > 0) {
480  if (level->inArray)
481  os_->Put(','); // add comma if it is not the first element in array
482  else // in object
483  os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
484  }
485  if (!level->inArray && level->valueCount % 2 == 0)
486  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
487  level->valueCount++;
488  }
489  else {
490  RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
491  hasRoot_ = true;
492  }
493  }
494 
495  // Flush the value if it is the top level one.
496  bool EndValue(bool ret) {
497  if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
498  Flush();
499  return ret;
500  }
501 
502  OutputStream* os_;
503  internal::Stack<StackAllocator> level_stack_;
504  int maxDecimalPlaces_;
505  bool hasRoot_;
506 
507 private:
508  // Prohibit copy constructor & assignment operator.
509  Writer(const Writer&);
510  Writer& operator=(const Writer&);
511 };
512 
513 // Full specialization for StringStream to prevent memory copying
514 
515 template<>
516 inline bool Writer<StringBuffer>::WriteInt(int i) {
517  char *buffer = os_->Push(11);
518  const char* end = internal::i32toa(i, buffer);
519  os_->Pop(static_cast<size_t>(11 - (end - buffer)));
520  return true;
521 }
522 
523 template<>
524 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
525  char *buffer = os_->Push(10);
526  const char* end = internal::u32toa(u, buffer);
527  os_->Pop(static_cast<size_t>(10 - (end - buffer)));
528  return true;
529 }
530 
531 template<>
532 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
533  char *buffer = os_->Push(21);
534  const char* end = internal::i64toa(i64, buffer);
535  os_->Pop(static_cast<size_t>(21 - (end - buffer)));
536  return true;
537 }
538 
539 template<>
540 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
541  char *buffer = os_->Push(20);
542  const char* end = internal::u64toa(u, buffer);
543  os_->Pop(static_cast<size_t>(20 - (end - buffer)));
544  return true;
545 }
546 
547 template<>
548 inline bool Writer<StringBuffer>::WriteDouble(double d) {
549  if (internal::Double(d).IsNanOrInf()) {
550  // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
552  return false;
553  if (internal::Double(d).IsNan()) {
554  PutReserve(*os_, 3);
555  PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
556  return true;
557  }
558  if (internal::Double(d).Sign()) {
559  PutReserve(*os_, 9);
560  PutUnsafe(*os_, '-');
561  }
562  else
563  PutReserve(*os_, 8);
564  PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
565  PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
566  return true;
567  }
568 
569  char *buffer = os_->Push(25);
570  char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
571  os_->Pop(static_cast<size_t>(25 - (end - buffer)));
572  return true;
573 }
574 
575 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
576 template<>
577 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
578  if (length < 16)
579  return RAPIDJSON_LIKELY(is.Tell() < length);
580 
581  if (!RAPIDJSON_LIKELY(is.Tell() < length))
582  return false;
583 
584  const char* p = is.src_;
585  const char* end = is.head_ + length;
586  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
587  const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
588  if (nextAligned > end)
589  return true;
590 
591  while (p != nextAligned)
592  if (*p < 0x20 || *p == '\"' || *p == '\\') {
593  is.src_ = p;
594  return RAPIDJSON_LIKELY(is.Tell() < length);
595  }
596  else
597  os_->PutUnsafe(*p++);
598 
599  // The rest of string using SIMD
600  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
601  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
602  static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
603  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
604  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
605  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
606 
607  for (; p != endAligned; p += 16) {
608  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
609  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
610  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
611  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
612  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
613  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
614  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
615  SizeType len;
616 #ifdef _MSC_VER // Find the index of first escaped
617  unsigned long offset;
618  _BitScanForward(&offset, r);
619  len = offset;
620 #else
621  len = static_cast<SizeType>(__builtin_ffs(r) - 1);
622 #endif
623  char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
624  for (size_t i = 0; i < len; i++)
625  q[i] = p[i];
626 
627  p += len;
628  break;
629  }
630  _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
631  }
632 
633  is.src_ = p;
634  return RAPIDJSON_LIKELY(is.Tell() < length);
635 }
636 #elif defined(RAPIDJSON_NEON)
637 template<>
638 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
639  if (length < 16)
640  return RAPIDJSON_LIKELY(is.Tell() < length);
641 
642  if (!RAPIDJSON_LIKELY(is.Tell() < length))
643  return false;
644 
645  const char* p = is.src_;
646  const char* end = is.head_ + length;
647  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
648  const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
649  if (nextAligned > end)
650  return true;
651 
652  while (p != nextAligned)
653  if (*p < 0x20 || *p == '\"' || *p == '\\') {
654  is.src_ = p;
655  return RAPIDJSON_LIKELY(is.Tell() < length);
656  }
657  else
658  os_->PutUnsafe(*p++);
659 
660  // The rest of string using SIMD
661  const uint8x16_t s0 = vmovq_n_u8('"');
662  const uint8x16_t s1 = vmovq_n_u8('\\');
663  const uint8x16_t s2 = vmovq_n_u8('\b');
664  const uint8x16_t s3 = vmovq_n_u8(32);
665 
666  for (; p != endAligned; p += 16) {
667  const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
668  uint8x16_t x = vceqq_u8(s, s0);
669  x = vorrq_u8(x, vceqq_u8(s, s1));
670  x = vorrq_u8(x, vceqq_u8(s, s2));
671  x = vorrq_u8(x, vcltq_u8(s, s3));
672 
673  x = vrev64q_u8(x); // Rev in 64
674  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
675  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
676 
677  SizeType len = 0;
678  bool escaped = false;
679  if (low == 0) {
680  if (high != 0) {
681  unsigned lz = (unsigned)__builtin_clzll(high);
682  len = 8 + (lz >> 3);
683  escaped = true;
684  }
685  } else {
686  unsigned lz = (unsigned)__builtin_clzll(low);
687  len = lz >> 3;
688  escaped = true;
689  }
690  if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
691  char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
692  for (size_t i = 0; i < len; i++)
693  q[i] = p[i];
694 
695  p += len;
696  break;
697  }
698  vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
699  }
700 
701  is.src_ = p;
702  return RAPIDJSON_LIKELY(is.Tell() < length);
703 }
704 #endif // RAPIDJSON_NEON
705 
706 RAPIDJSON_NAMESPACE_END
707 
708 #ifdef _MSC_VER
709 RAPIDJSON_DIAG_POP
710 #endif
711 
712 #ifdef __clang__
713 RAPIDJSON_DIAG_POP
714 #endif
715 
716 #endif // RAPIDJSON_RAPIDJSON_H_
true
Definition: rapidjson.h:619
bool inArray
true if in array, otherwise in object
Definition: writer.h:292
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition: writer.h:174
Read-only string stream.
Definition: fwd.h:47
No flags are set.
Definition: writer.h:68
Encoding conversion.
Definition: encodings.h:658
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:145
Validate encoding of JSON strings.
Definition: writer.h:69
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
Definition: stream.h:84
unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:389
bool String(const Ch *const &str)
Simpler but slower overload.
Definition: writer.h:260
WriteFlag
Combination of writeFlags.
Definition: writer.h:67
false
Definition: rapidjson.h:618
const Ch * head_
Original head of the string.
Definition: stream.h:169
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:273
const Ch * src_
Current read position.
Definition: stream.h:168
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:468
Information for each nested level.
Definition: writer.h:289
size_t valueCount
number of values in this level
Definition: writer.h:291
Type
Type of JSON value.
Definition: rapidjson.h:616
object
Definition: rapidjson.h:620
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:481
array
Definition: rapidjson.h:621
JSON writer.
Definition: fwd.h:95
null
Definition: rapidjson.h:617
string
Definition: rapidjson.h:622
Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS. ...
Definition: writer.h:71
void Flush()
Flush the output stream.
Definition: writer.h:283
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
User-defined kWriteDefaultFlags definition.
Definition: writer.h:63
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:195
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
Definition: stream.h:91
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:103
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:411
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:135
number
Definition: rapidjson.h:623
Allow writing of Infinity, -Infinity and NaN.
Definition: writer.h:70