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);
463  for (size_t i = 0; i < length; i++) {
464  RAPIDJSON_ASSERT(json[i] != '\0');
465  PutUnsafe(*os_, json[i]);
466  }
467  return true;
468  }
469 
470  void Prefix(Type type) {
471  (void)type;
472  if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
473  Level* level = level_stack_.template Top<Level>();
474  if (level->valueCount > 0) {
475  if (level->inArray)
476  os_->Put(','); // add comma if it is not the first element in array
477  else // in object
478  os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
479  }
480  if (!level->inArray && level->valueCount % 2 == 0)
481  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
482  level->valueCount++;
483  }
484  else {
485  RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
486  hasRoot_ = true;
487  }
488  }
489 
490  // Flush the value if it is the top level one.
491  bool EndValue(bool ret) {
492  if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
493  Flush();
494  return ret;
495  }
496 
497  OutputStream* os_;
498  internal::Stack<StackAllocator> level_stack_;
499  int maxDecimalPlaces_;
500  bool hasRoot_;
501 
502 private:
503  // Prohibit copy constructor & assignment operator.
504  Writer(const Writer&);
505  Writer& operator=(const Writer&);
506 };
507 
508 // Full specialization for StringStream to prevent memory copying
509 
510 template<>
511 inline bool Writer<StringBuffer>::WriteInt(int i) {
512  char *buffer = os_->Push(11);
513  const char* end = internal::i32toa(i, buffer);
514  os_->Pop(static_cast<size_t>(11 - (end - buffer)));
515  return true;
516 }
517 
518 template<>
519 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
520  char *buffer = os_->Push(10);
521  const char* end = internal::u32toa(u, buffer);
522  os_->Pop(static_cast<size_t>(10 - (end - buffer)));
523  return true;
524 }
525 
526 template<>
527 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
528  char *buffer = os_->Push(21);
529  const char* end = internal::i64toa(i64, buffer);
530  os_->Pop(static_cast<size_t>(21 - (end - buffer)));
531  return true;
532 }
533 
534 template<>
535 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
536  char *buffer = os_->Push(20);
537  const char* end = internal::u64toa(u, buffer);
538  os_->Pop(static_cast<size_t>(20 - (end - buffer)));
539  return true;
540 }
541 
542 template<>
543 inline bool Writer<StringBuffer>::WriteDouble(double d) {
544  if (internal::Double(d).IsNanOrInf()) {
545  // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
547  return false;
548  if (internal::Double(d).IsNan()) {
549  PutReserve(*os_, 3);
550  PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
551  return true;
552  }
553  if (internal::Double(d).Sign()) {
554  PutReserve(*os_, 9);
555  PutUnsafe(*os_, '-');
556  }
557  else
558  PutReserve(*os_, 8);
559  PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
560  PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
561  return true;
562  }
563 
564  char *buffer = os_->Push(25);
565  char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
566  os_->Pop(static_cast<size_t>(25 - (end - buffer)));
567  return true;
568 }
569 
570 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
571 template<>
572 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
573  if (length < 16)
574  return RAPIDJSON_LIKELY(is.Tell() < length);
575 
576  if (!RAPIDJSON_LIKELY(is.Tell() < length))
577  return false;
578 
579  const char* p = is.src_;
580  const char* end = is.head_ + length;
581  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
582  const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
583  if (nextAligned > end)
584  return true;
585 
586  while (p != nextAligned)
587  if (*p < 0x20 || *p == '\"' || *p == '\\') {
588  is.src_ = p;
589  return RAPIDJSON_LIKELY(is.Tell() < length);
590  }
591  else
592  os_->PutUnsafe(*p++);
593 
594  // The rest of string using SIMD
595  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
596  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
597  static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
598  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
599  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
600  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
601 
602  for (; p != endAligned; p += 16) {
603  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
604  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
605  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
606  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
607  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
608  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
609  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
610  SizeType len;
611 #ifdef _MSC_VER // Find the index of first escaped
612  unsigned long offset;
613  _BitScanForward(&offset, r);
614  len = offset;
615 #else
616  len = static_cast<SizeType>(__builtin_ffs(r) - 1);
617 #endif
618  char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
619  for (size_t i = 0; i < len; i++)
620  q[i] = p[i];
621 
622  p += len;
623  break;
624  }
625  _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
626  }
627 
628  is.src_ = p;
629  return RAPIDJSON_LIKELY(is.Tell() < length);
630 }
631 #elif defined(RAPIDJSON_NEON)
632 template<>
633 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
634  if (length < 16)
635  return RAPIDJSON_LIKELY(is.Tell() < length);
636 
637  if (!RAPIDJSON_LIKELY(is.Tell() < length))
638  return false;
639 
640  const char* p = is.src_;
641  const char* end = is.head_ + length;
642  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
643  const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
644  if (nextAligned > end)
645  return true;
646 
647  while (p != nextAligned)
648  if (*p < 0x20 || *p == '\"' || *p == '\\') {
649  is.src_ = p;
650  return RAPIDJSON_LIKELY(is.Tell() < length);
651  }
652  else
653  os_->PutUnsafe(*p++);
654 
655  // The rest of string using SIMD
656  const uint8x16_t s0 = vmovq_n_u8('"');
657  const uint8x16_t s1 = vmovq_n_u8('\\');
658  const uint8x16_t s2 = vmovq_n_u8('\b');
659  const uint8x16_t s3 = vmovq_n_u8(32);
660 
661  for (; p != endAligned; p += 16) {
662  const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
663  uint8x16_t x = vceqq_u8(s, s0);
664  x = vorrq_u8(x, vceqq_u8(s, s1));
665  x = vorrq_u8(x, vceqq_u8(s, s2));
666  x = vorrq_u8(x, vcltq_u8(s, s3));
667 
668  x = vrev64q_u8(x); // Rev in 64
669  uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
670  uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
671 
672  SizeType len = 0;
673  bool escaped = false;
674  if (low == 0) {
675  if (high != 0) {
676  unsigned lz = (unsigned)__builtin_clzll(high);
677  len = 8 + (lz >> 3);
678  escaped = true;
679  }
680  } else {
681  unsigned lz = (unsigned)__builtin_clzll(low);
682  len = lz >> 3;
683  escaped = true;
684  }
685  if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
686  char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
687  for (size_t i = 0; i < len; i++)
688  q[i] = p[i];
689 
690  p += len;
691  break;
692  }
693  vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
694  }
695 
696  is.src_ = p;
697  return RAPIDJSON_LIKELY(is.Tell() < length);
698 }
699 #endif // RAPIDJSON_NEON
700 
701 RAPIDJSON_NAMESPACE_END
702 
703 #ifdef _MSC_VER
704 RAPIDJSON_DIAG_POP
705 #endif
706 
707 #ifdef __clang__
708 RAPIDJSON_DIAG_POP
709 #endif
710 
711 #endif // RAPIDJSON_RAPIDJSON_H_
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