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