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/stack.h"
20 #include "internal/strfunc.h"
21 #include "internal/dtoa.h"
22 #include "internal/itoa.h"
23 #include "stringbuffer.h"
24 #include <new> // placement new
25 
26 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
27 #include <intrin.h>
28 #pragma intrinsic(_BitScanForward)
29 #endif
30 #ifdef RAPIDJSON_SSE42
31 #include <nmmintrin.h>
32 #elif defined(RAPIDJSON_SSE2)
33 #include <emmintrin.h>
34 #endif
35 
36 #ifdef _MSC_VER
37 RAPIDJSON_DIAG_PUSH
38 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
39 #endif
40 
41 #ifdef __clang__
42 RAPIDJSON_DIAG_PUSH
43 RAPIDJSON_DIAG_OFF(padded)
44 RAPIDJSON_DIAG_OFF(unreachable-code)
45 #endif
46 
47 RAPIDJSON_NAMESPACE_BEGIN
48 
49 ///////////////////////////////////////////////////////////////////////////////
50 // WriteFlag
51 
52 /*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS
53  \ingroup RAPIDJSON_CONFIG
54  \brief User-defined kWriteDefaultFlags definition.
55 
56  User can define this as any \c WriteFlag combinations.
57 */
58 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
59 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
60 #endif
61 
62 //! Combination of writeFlags
63 enum WriteFlag {
64  kWriteNoFlags = 0, //!< No flags are set.
65  kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
66  kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN.
67  kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
68 };
69 
70 //! JSON writer
71 /*! Writer implements the concept Handler.
72  It generates JSON text by events to an output os.
73 
74  User may programmatically calls the functions of a writer to generate JSON text.
75 
76  On the other side, a writer can also be passed to objects that generates events,
77 
78  for example Reader::Parse() and Document::Accept().
79 
80  \tparam OutputStream Type of output stream.
81  \tparam SourceEncoding Encoding of source string.
82  \tparam TargetEncoding Encoding of output stream.
83  \tparam StackAllocator Type of allocator for allocating memory of stack.
84  \note implements Handler concept
85 */
86 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
87 class Writer {
88 public:
89  typedef typename SourceEncoding::Ch Ch;
90 
91  static const int kDefaultMaxDecimalPlaces = 324;
92 
93  //! Constructor
94  /*! \param os Output stream.
95  \param stackAllocator User supplied allocator. If it is null, it will create a private one.
96  \param levelDepth Initial capacity of stack.
97  */
98  explicit
99  Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
100  os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
101 
102  explicit
103  Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
104  os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
105 
106  //! Reset the writer with a new stream.
107  /*!
108  This function reset the writer with a new stream and default settings,
109  in order to make a Writer object reusable for output multiple JSONs.
110 
111  \param os New output stream.
112  \code
113  Writer<OutputStream> writer(os1);
114  writer.StartObject();
115  // ...
116  writer.EndObject();
117 
118  writer.Reset(os2);
119  writer.StartObject();
120  // ...
121  writer.EndObject();
122  \endcode
123  */
124  void Reset(OutputStream& os) {
125  os_ = &os;
126  hasRoot_ = false;
127  level_stack_.Clear();
128  }
129 
130  //! Checks whether the output is a complete JSON.
131  /*!
132  A complete JSON has a complete root object or array.
133  */
134  bool IsComplete() const {
135  return hasRoot_ && level_stack_.Empty();
136  }
137 
138  int GetMaxDecimalPlaces() const {
139  return maxDecimalPlaces_;
140  }
141 
142  //! Sets the maximum number of decimal places for double output.
143  /*!
144  This setting truncates the output with specified number of decimal places.
145 
146  For example,
147 
148  \code
149  writer.SetMaxDecimalPlaces(3);
150  writer.StartArray();
151  writer.Double(0.12345); // "0.123"
152  writer.Double(0.0001); // "0.0"
153  writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent)
154  writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent)
155  writer.EndArray();
156  \endcode
157 
158  The default setting does not truncate any decimal places. You can restore to this setting by calling
159  \code
160  writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
161  \endcode
162  */
163  void SetMaxDecimalPlaces(int maxDecimalPlaces) {
164  maxDecimalPlaces_ = maxDecimalPlaces;
165  }
166 
167  /*!@name Implementation of Handler
168  \see Handler
169  */
170  //@{
171 
172  bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
173  bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
174  bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
175  bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
176  bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
177  bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
178 
179  //! Writes the given \c double value to the stream
180  /*!
181  \param d The value to be written.
182  \return Whether it is succeed.
183  */
184  bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
185 
186  bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
187  (void)copy;
188  Prefix(kNumberType);
189  return EndValue(WriteString(str, length));
190  }
191 
192  bool String(const Ch* str, SizeType length, bool copy = false) {
193  (void)copy;
194  Prefix(kStringType);
195  return EndValue(WriteString(str, length));
196  }
197 
198 #if RAPIDJSON_HAS_STDSTRING
199  bool String(const std::basic_string<Ch>& str) {
200  return String(str.data(), SizeType(str.size()));
201  }
202 #endif
203 
204  bool StartObject() {
205  Prefix(kObjectType);
206  new (level_stack_.template Push<Level>()) Level(false);
207  return WriteStartObject();
208  }
209 
210  bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
211 
212  bool EndObject(SizeType memberCount = 0) {
213  (void)memberCount;
214  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
215  RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
216  level_stack_.template Pop<Level>(1);
217  return EndValue(WriteEndObject());
218  }
219 
220  bool StartArray() {
221  Prefix(kArrayType);
222  new (level_stack_.template Push<Level>()) Level(true);
223  return WriteStartArray();
224  }
225 
226  bool EndArray(SizeType elementCount = 0) {
227  (void)elementCount;
228  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
229  RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
230  level_stack_.template Pop<Level>(1);
231  return EndValue(WriteEndArray());
232  }
233  //@}
234 
235  /*! @name Convenience extensions */
236  //@{
237 
238  //! Simpler but slower overload.
239  bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
240  bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
241 
242  //@}
243 
244  //! Write a raw JSON value.
245  /*!
246  For user to write a stringified JSON as a value.
247 
248  \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
249  \param length Length of the json.
250  \param type Type of the root of json.
251  */
252  bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); }
253 
254 protected:
255  //! Information for each nested level
256  struct Level {
257  Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
258  size_t valueCount; //!< number of values in this level
259  bool inArray; //!< true if in array, otherwise in object
260  };
261 
262  static const size_t kDefaultLevelDepth = 32;
263 
264  bool WriteNull() {
265  PutReserve(*os_, 4);
266  PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
267  }
268 
269  bool WriteBool(bool b) {
270  if (b) {
271  PutReserve(*os_, 4);
272  PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
273  }
274  else {
275  PutReserve(*os_, 5);
276  PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
277  }
278  return true;
279  }
280 
281  bool WriteInt(int i) {
282  char buffer[11];
283  const char* end = internal::i32toa(i, buffer);
284  PutReserve(*os_, static_cast<size_t>(end - buffer));
285  for (const char* p = buffer; p != end; ++p)
286  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
287  return true;
288  }
289 
290  bool WriteUint(unsigned u) {
291  char buffer[10];
292  const char* end = internal::u32toa(u, buffer);
293  PutReserve(*os_, static_cast<size_t>(end - buffer));
294  for (const char* p = buffer; p != end; ++p)
295  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
296  return true;
297  }
298 
299  bool WriteInt64(int64_t i64) {
300  char buffer[21];
301  const char* end = internal::i64toa(i64, buffer);
302  PutReserve(*os_, static_cast<size_t>(end - buffer));
303  for (const char* p = buffer; p != end; ++p)
304  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
305  return true;
306  }
307 
308  bool WriteUint64(uint64_t u64) {
309  char buffer[20];
310  char* end = internal::u64toa(u64, buffer);
311  PutReserve(*os_, static_cast<size_t>(end - buffer));
312  for (char* p = buffer; p != end; ++p)
313  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
314  return true;
315  }
316 
317  bool WriteDouble(double d) {
318  if (internal::Double(d).IsNanOrInf()) {
319  if (!(writeFlags & kWriteNanAndInfFlag))
320  return false;
321  if (internal::Double(d).IsNan()) {
322  PutReserve(*os_, 3);
323  PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
324  return true;
325  }
326  if (internal::Double(d).Sign()) {
327  PutReserve(*os_, 9);
328  PutUnsafe(*os_, '-');
329  }
330  else
331  PutReserve(*os_, 8);
332  PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
333  PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
334  return true;
335  }
336 
337  char buffer[25];
338  char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
339  PutReserve(*os_, static_cast<size_t>(end - buffer));
340  for (char* p = buffer; p != end; ++p)
341  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
342  return true;
343  }
344 
345  bool WriteString(const Ch* str, SizeType length) {
346  static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
347  static const char escape[256] = {
348 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
349  //0 1 2 3 4 5 6 7 8 9 A B C D E F
350  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
351  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
352  0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
353  Z16, Z16, // 30~4F
354  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
355  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
356 #undef Z16
357  };
358 
359  if (TargetEncoding::supportUnicode)
360  PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
361  else
362  PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
363 
364  PutUnsafe(*os_, '\"');
365  GenericStringStream<SourceEncoding> is(str);
366  while (ScanWriteUnescapedString(is, length)) {
367  const Ch c = is.Peek();
368  if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
369  // Unicode escaping
370  unsigned codepoint;
371  if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
372  return false;
373  PutUnsafe(*os_, '\\');
374  PutUnsafe(*os_, 'u');
375  if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
376  PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
377  PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
378  PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
379  PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
380  }
381  else {
382  RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
383  // Surrogate pair
384  unsigned s = codepoint - 0x010000;
385  unsigned lead = (s >> 10) + 0xD800;
386  unsigned trail = (s & 0x3FF) + 0xDC00;
387  PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
388  PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
389  PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
390  PutUnsafe(*os_, hexDigits[(lead ) & 15]);
391  PutUnsafe(*os_, '\\');
392  PutUnsafe(*os_, 'u');
393  PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
394  PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
395  PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
396  PutUnsafe(*os_, hexDigits[(trail ) & 15]);
397  }
398  }
399  else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
400  is.Take();
401  PutUnsafe(*os_, '\\');
402  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
403  if (escape[static_cast<unsigned char>(c)] == 'u') {
404  PutUnsafe(*os_, '0');
405  PutUnsafe(*os_, '0');
406  PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
407  PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
408  }
409  }
410  else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
411  Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
412  Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
413  return false;
414  }
415  PutUnsafe(*os_, '\"');
416  return true;
417  }
418 
419  bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
420  return RAPIDJSON_LIKELY(is.Tell() < length);
421  }
422 
423  bool WriteStartObject() { os_->Put('{'); return true; }
424  bool WriteEndObject() { os_->Put('}'); return true; }
425  bool WriteStartArray() { os_->Put('['); return true; }
426  bool WriteEndArray() { os_->Put(']'); return true; }
427 
428  bool WriteRawValue(const Ch* json, size_t length) {
429  PutReserve(*os_, length);
430  for (size_t i = 0; i < length; i++) {
431  RAPIDJSON_ASSERT(json[i] != '\0');
432  PutUnsafe(*os_, json[i]);
433  }
434  return true;
435  }
436 
437  void Prefix(Type type) {
438  (void)type;
439  if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
440  Level* level = level_stack_.template Top<Level>();
441  if (level->valueCount > 0) {
442  if (level->inArray)
443  os_->Put(','); // add comma if it is not the first element in array
444  else // in object
445  os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
446  }
447  if (!level->inArray && level->valueCount % 2 == 0)
448  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
449  level->valueCount++;
450  }
451  else {
452  RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
453  hasRoot_ = true;
454  }
455  }
456 
457  // Flush the value if it is the top level one.
458  bool EndValue(bool ret) {
459  if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
460  os_->Flush();
461  return ret;
462  }
463 
464  OutputStream* os_;
465  internal::Stack<StackAllocator> level_stack_;
466  int maxDecimalPlaces_;
467  bool hasRoot_;
468 
469 private:
470  // Prohibit copy constructor & assignment operator.
471  Writer(const Writer&);
472  Writer& operator=(const Writer&);
473 };
474 
475 // Full specialization for StringStream to prevent memory copying
476 
477 template<>
478 inline bool Writer<StringBuffer>::WriteInt(int i) {
479  char *buffer = os_->Push(11);
480  const char* end = internal::i32toa(i, buffer);
481  os_->Pop(static_cast<size_t>(11 - (end - buffer)));
482  return true;
483 }
484 
485 template<>
486 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
487  char *buffer = os_->Push(10);
488  const char* end = internal::u32toa(u, buffer);
489  os_->Pop(static_cast<size_t>(10 - (end - buffer)));
490  return true;
491 }
492 
493 template<>
494 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
495  char *buffer = os_->Push(21);
496  const char* end = internal::i64toa(i64, buffer);
497  os_->Pop(static_cast<size_t>(21 - (end - buffer)));
498  return true;
499 }
500 
501 template<>
502 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
503  char *buffer = os_->Push(20);
504  const char* end = internal::u64toa(u, buffer);
505  os_->Pop(static_cast<size_t>(20 - (end - buffer)));
506  return true;
507 }
508 
509 template<>
510 inline bool Writer<StringBuffer>::WriteDouble(double d) {
511  if (internal::Double(d).IsNanOrInf()) {
512  // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
513  if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
514  return false;
515  if (internal::Double(d).IsNan()) {
516  PutReserve(*os_, 3);
517  PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
518  return true;
519  }
520  if (internal::Double(d).Sign()) {
521  PutReserve(*os_, 9);
522  PutUnsafe(*os_, '-');
523  }
524  else
525  PutReserve(*os_, 8);
526  PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
527  PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
528  return true;
529  }
530 
531  char *buffer = os_->Push(25);
532  char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
533  os_->Pop(static_cast<size_t>(25 - (end - buffer)));
534  return true;
535 }
536 
537 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
538 template<>
539 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
540  if (length < 16)
541  return RAPIDJSON_LIKELY(is.Tell() < length);
542 
543  if (!RAPIDJSON_LIKELY(is.Tell() < length))
544  return false;
545 
546  const char* p = is.src_;
547  const char* end = is.head_ + length;
548  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
549  const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
550  if (nextAligned > end)
551  return true;
552 
553  while (p != nextAligned)
554  if (*p < 0x20 || *p == '\"' || *p == '\\') {
555  is.src_ = p;
556  return RAPIDJSON_LIKELY(is.Tell() < length);
557  }
558  else
559  os_->PutUnsafe(*p++);
560 
561  // The rest of string using SIMD
562  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
563  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
564  static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
565  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
566  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
567  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
568 
569  for (; p != endAligned; p += 16) {
570  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
571  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
572  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
573  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
574  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
575  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
576  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
577  SizeType len;
578 #ifdef _MSC_VER // Find the index of first escaped
579  unsigned long offset;
580  _BitScanForward(&offset, r);
581  len = offset;
582 #else
583  len = static_cast<SizeType>(__builtin_ffs(r) - 1);
584 #endif
585  char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
586  for (size_t i = 0; i < len; i++)
587  q[i] = p[i];
588 
589  p += len;
590  break;
591  }
592  _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
593  }
594 
595  is.src_ = p;
596  return RAPIDJSON_LIKELY(is.Tell() < length);
597 }
598 #endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
599 
600 RAPIDJSON_NAMESPACE_END
601 
602 #ifdef _MSC_VER
603 RAPIDJSON_DIAG_POP
604 #endif
605 
606 #ifdef __clang__
607 RAPIDJSON_DIAG_POP
608 #endif
609 
610 #endif // RAPIDJSON_RAPIDJSON_H_
RAPIDJSON_WRITE_DEFAULT_FLAGS
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
User-defined kWriteDefaultFlags definition.
Definition: writer.h:59
rapidjson::Type
Type
Type of JSON value.
Definition: rapidjson.h:603
rapidjson::WriteFlag
WriteFlag
Combination of writeFlags.
Definition: writer.h:63
rapidjson::kTrueType
@ kTrueType
true
Definition: rapidjson.h:606
rapidjson::Writer::IsComplete
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:134
rapidjson::kWriteValidateEncodingFlag
@ kWriteValidateEncodingFlag
Validate encoding of JSON strings.
Definition: writer.h:65
rapidjson::kWriteNoFlags
@ kWriteNoFlags
No flags are set.
Definition: writer.h:64
rapidjson::Writer::Double
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:184
rapidjson::kFalseType
@ kFalseType
false
Definition: rapidjson.h:605
rapidjson::Writer::SetMaxDecimalPlaces
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition: writer.h:163
rapidjson::kObjectType
@ kObjectType
object
Definition: rapidjson.h:607
rapidjson::SizeType
unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:380
rapidjson::Writer::Level
Information for each nested level.
Definition: writer.h:256
RAPIDJSON_ASSERT
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:402
rapidjson::Writer::Level::valueCount
size_t valueCount
number of values in this level
Definition: writer.h:258
rapidjson::kArrayType
@ kArrayType
array
Definition: rapidjson.h:608
rapidjson::PutUnsafe
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
Definition: stream.h:91
rapidjson::kNullType
@ kNullType
null
Definition: rapidjson.h:604
rapidjson::kWriteDefaultFlags
@ kWriteDefaultFlags
Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS.
Definition: writer.h:67
rapidjson::Writer::Writer
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:99
rapidjson::kStringType
@ kStringType
string
Definition: rapidjson.h:609
rapidjson::Writer
JSON writer.
Definition: fwd.h:95
rapidjson::Writer::String
bool String(const Ch *str)
Simpler but slower overload.
Definition: writer.h:239
rapidjson::Writer::RawValue
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:252
rapidjson::Writer::Level::inArray
bool inArray
true if in array, otherwise in object
Definition: writer.h:259
rapidjson::PutReserve
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
Definition: stream.h:84
rapidjson::kNumberType
@ kNumberType
number
Definition: rapidjson.h:610
RAPIDJSON_LIKELY
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:455
rapidjson::Writer::Reset
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:124
rapidjson::kWriteNanAndInfFlag
@ kWriteNanAndInfFlag
Allow writing of Infinity, -Infinity and NaN.
Definition: writer.h:66
RAPIDJSON_UNLIKELY
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:468