cphot 0.1
A C++ tool for computing photometry from spectra.
writer.h
Go to the documentation of this file.
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 
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;
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  RAPIDJSON_ASSERT(str != 0);
188  (void)copy;
190  return EndValue(WriteString(str, length));
191  }
192 
193  bool String(const Ch* str, SizeType length, bool copy = false) {
194  RAPIDJSON_ASSERT(str != 0);
195  (void)copy;
197  return EndValue(WriteString(str, length));
198  }
199 
200 #if RAPIDJSON_HAS_STDSTRING
201  bool String(const std::basic_string<Ch>& str) {
202  return String(str.data(), SizeType(str.size()));
203  }
204 #endif
205 
206  bool StartObject() {
208  new (level_stack_.template Push<Level>()) Level(false);
209  return WriteStartObject();
210  }
211 
212  bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
213 
214  bool EndObject(SizeType memberCount = 0) {
215  (void)memberCount;
217  RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
218  level_stack_.template Pop<Level>(1);
219  return EndValue(WriteEndObject());
220  }
221 
222  bool StartArray() {
224  new (level_stack_.template Push<Level>()) Level(true);
225  return WriteStartArray();
226  }
227 
228  bool EndArray(SizeType elementCount = 0) {
229  (void)elementCount;
231  RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
232  level_stack_.template Pop<Level>(1);
233  return EndValue(WriteEndArray());
234  }
235  //@}
236 
237  /*! @name Convenience extensions */
238  //@{
239 
240  //! Simpler but slower overload.
241  bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
242  bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
243 
244  //@}
245 
246  //! Write a raw JSON value.
247  /*!
248  For user to write a stringified JSON as a value.
249 
250  \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
251  \param length Length of the json.
252  \param type Type of the root of json.
253  */
254  bool RawValue(const Ch* json, size_t length, Type type) {
255  RAPIDJSON_ASSERT(json != 0);
256  Prefix(type);
257  return EndValue(WriteRawValue(json, length));
258  }
259 
260 protected:
261  //! Information for each nested level
262  struct Level {
263  Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
264  size_t valueCount; //!< number of values in this level
265  bool inArray; //!< true if in array, otherwise in object
266  };
267 
268  static const size_t kDefaultLevelDepth = 32;
269 
270  bool WriteNull() {
271  PutReserve(*os_, 4);
272  PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
273  }
274 
275  bool WriteBool(bool b) {
276  if (b) {
277  PutReserve(*os_, 4);
278  PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
279  }
280  else {
281  PutReserve(*os_, 5);
282  PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
283  }
284  return true;
285  }
286 
287  bool WriteInt(int i) {
288  char buffer[11];
289  const char* end = internal::i32toa(i, buffer);
290  PutReserve(*os_, static_cast<size_t>(end - buffer));
291  for (const char* p = buffer; p != end; ++p)
292  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
293  return true;
294  }
295 
296  bool WriteUint(unsigned u) {
297  char buffer[10];
298  const char* end = internal::u32toa(u, buffer);
299  PutReserve(*os_, static_cast<size_t>(end - buffer));
300  for (const char* p = buffer; p != end; ++p)
301  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
302  return true;
303  }
304 
305  bool WriteInt64(int64_t i64) {
306  char buffer[21];
307  const char* end = internal::i64toa(i64, 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 TargetEncoding::Ch>(*p));
311  return true;
312  }
313 
314  bool WriteUint64(uint64_t u64) {
315  char buffer[20];
316  char* end = internal::u64toa(u64, buffer);
317  PutReserve(*os_, static_cast<size_t>(end - buffer));
318  for (char* p = buffer; p != end; ++p)
319  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
320  return true;
321  }
322 
323  bool WriteDouble(double d) {
324  if (internal::Double(d).IsNanOrInf()) {
325  if (!(writeFlags & kWriteNanAndInfFlag))
326  return false;
327  if (internal::Double(d).IsNan()) {
328  PutReserve(*os_, 3);
329  PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
330  return true;
331  }
332  if (internal::Double(d).Sign()) {
333  PutReserve(*os_, 9);
334  PutUnsafe(*os_, '-');
335  }
336  else
337  PutReserve(*os_, 8);
338  PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
339  PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
340  return true;
341  }
342 
343  char buffer[25];
344  char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
345  PutReserve(*os_, static_cast<size_t>(end - buffer));
346  for (char* p = buffer; p != end; ++p)
347  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
348  return true;
349  }
350 
351  bool WriteString(const Ch* str, SizeType length) {
352  static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
353  static const char escape[256] = {
354 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
355  //0 1 2 3 4 5 6 7 8 9 A B C D E F
356  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
357  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
358  0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
359  Z16, Z16, // 30~4F
360  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
361  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
362 #undef Z16
363  };
364 
365  if (TargetEncoding::supportUnicode)
366  PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
367  else
368  PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
369 
370  PutUnsafe(*os_, '\"');
372  while (ScanWriteUnescapedString(is, length)) {
373  const Ch c = is.Peek();
374  if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
375  // Unicode escaping
376  unsigned codepoint;
377  if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
378  return false;
379  PutUnsafe(*os_, '\\');
380  PutUnsafe(*os_, 'u');
381  if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
382  PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
383  PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
384  PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
385  PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
386  }
387  else {
388  RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
389  // Surrogate pair
390  unsigned s = codepoint - 0x010000;
391  unsigned lead = (s >> 10) + 0xD800;
392  unsigned trail = (s & 0x3FF) + 0xDC00;
393  PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
394  PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
395  PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
396  PutUnsafe(*os_, hexDigits[(lead ) & 15]);
397  PutUnsafe(*os_, '\\');
398  PutUnsafe(*os_, 'u');
399  PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
400  PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
401  PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
402  PutUnsafe(*os_, hexDigits[(trail ) & 15]);
403  }
404  }
405  else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
406  is.Take();
407  PutUnsafe(*os_, '\\');
408  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
409  if (escape[static_cast<unsigned char>(c)] == 'u') {
410  PutUnsafe(*os_, '0');
411  PutUnsafe(*os_, '0');
412  PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
413  PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
414  }
415  }
416  else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
419  return false;
420  }
421  PutUnsafe(*os_, '\"');
422  return true;
423  }
424 
426  return RAPIDJSON_LIKELY(is.Tell() < length);
427  }
428 
429  bool WriteStartObject() { os_->Put('{'); return true; }
430  bool WriteEndObject() { os_->Put('}'); return true; }
431  bool WriteStartArray() { os_->Put('['); return true; }
432  bool WriteEndArray() { os_->Put(']'); return true; }
433 
434  bool WriteRawValue(const Ch* json, size_t length) {
435  PutReserve(*os_, length);
436  for (size_t i = 0; i < length; i++) {
437  RAPIDJSON_ASSERT(json[i] != '\0');
438  PutUnsafe(*os_, json[i]);
439  }
440  return true;
441  }
442 
443  void Prefix(Type type) {
444  (void)type;
445  if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
446  Level* level = level_stack_.template Top<Level>();
447  if (level->valueCount > 0) {
448  if (level->inArray)
449  os_->Put(','); // add comma if it is not the first element in array
450  else // in object
451  os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
452  }
453  if (!level->inArray && level->valueCount % 2 == 0)
454  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
455  level->valueCount++;
456  }
457  else {
458  RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
459  hasRoot_ = true;
460  }
461  }
462 
463  // Flush the value if it is the top level one.
464  bool EndValue(bool ret) {
465  if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
466  os_->Flush();
467  return ret;
468  }
469 
470  OutputStream* os_;
473  bool hasRoot_;
474 
475 private:
476  // Prohibit copy constructor & assignment operator.
477  Writer(const Writer&);
478  Writer& operator=(const Writer&);
479 };
480 
481 // Full specialization for StringStream to prevent memory copying
482 
483 template<>
484 inline bool Writer<StringBuffer>::WriteInt(int i) {
485  char *buffer = os_->Push(11);
486  const char* end = internal::i32toa(i, buffer);
487  os_->Pop(static_cast<size_t>(11 - (end - buffer)));
488  return true;
489 }
490 
491 template<>
492 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
493  char *buffer = os_->Push(10);
494  const char* end = internal::u32toa(u, buffer);
495  os_->Pop(static_cast<size_t>(10 - (end - buffer)));
496  return true;
497 }
498 
499 template<>
501  char *buffer = os_->Push(21);
502  const char* end = internal::i64toa(i64, buffer);
503  os_->Pop(static_cast<size_t>(21 - (end - buffer)));
504  return true;
505 }
506 
507 template<>
509  char *buffer = os_->Push(20);
510  const char* end = internal::u64toa(u, buffer);
511  os_->Pop(static_cast<size_t>(20 - (end - buffer)));
512  return true;
513 }
514 
515 template<>
516 inline bool Writer<StringBuffer>::WriteDouble(double d) {
517  if (internal::Double(d).IsNanOrInf()) {
518  // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
520  return false;
521  if (internal::Double(d).IsNan()) {
522  PutReserve(*os_, 3);
523  PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
524  return true;
525  }
526  if (internal::Double(d).Sign()) {
527  PutReserve(*os_, 9);
528  PutUnsafe(*os_, '-');
529  }
530  else
531  PutReserve(*os_, 8);
532  PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
533  PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
534  return true;
535  }
536 
537  char *buffer = os_->Push(25);
538  char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
539  os_->Pop(static_cast<size_t>(25 - (end - buffer)));
540  return true;
541 }
542 
543 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
544 template<>
545 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
546  if (length < 16)
547  return RAPIDJSON_LIKELY(is.Tell() < length);
548 
549  if (!RAPIDJSON_LIKELY(is.Tell() < length))
550  return false;
551 
552  const char* p = is.src_;
553  const char* end = is.head_ + length;
554  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
555  const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
556  if (nextAligned > end)
557  return true;
558 
559  while (p != nextAligned)
560  if (*p < 0x20 || *p == '\"' || *p == '\\') {
561  is.src_ = p;
562  return RAPIDJSON_LIKELY(is.Tell() < length);
563  }
564  else
565  os_->PutUnsafe(*p++);
566 
567  // The rest of string using SIMD
568  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
569  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
570  static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
571  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
572  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
573  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
574 
575  for (; p != endAligned; p += 16) {
576  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
577  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
578  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
579  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
580  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
581  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
582  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
583  SizeType len;
584 #ifdef _MSC_VER // Find the index of first escaped
585  unsigned long offset;
586  _BitScanForward(&offset, r);
587  len = offset;
588 #else
589  len = static_cast<SizeType>(__builtin_ffs(r) - 1);
590 #endif
591  char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
592  for (size_t i = 0; i < len; i++)
593  q[i] = p[i];
594 
595  p += len;
596  break;
597  }
598  _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
599  }
600 
601  is.src_ = p;
602  return RAPIDJSON_LIKELY(is.Tell() < length);
603 }
604 #endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
605 
607 
608 #ifdef _MSC_VER
609 RAPIDJSON_DIAG_POP
610 #endif
611 
612 #ifdef __clang__
613 RAPIDJSON_DIAG_POP
614 #endif
615 
616 #endif // RAPIDJSON_RAPIDJSON_H_
internal::i32toa
char * i32toa(int32_t value, char *buffer)
Definition: itoa.h:113
RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:119
internal::dtoa
char * dtoa(double value, char *buffer, int maxDecimalPlaces=324)
Definition: dtoa.h:216
Writer::WriteRawValue
bool WriteRawValue(const Ch *json, size_t length)
Definition: writer.h:434
kNullType
@ kNullType
null
Definition: rapidjson.h:604
RAPIDJSON_NAMESPACE_BEGIN
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:116
Writer::WriteDouble
bool WriteDouble(double d)
Definition: writer.h:323
Writer::Key
bool Key(const Ch *str)
Definition: writer.h:242
kWriteNoFlags
@ kWriteNoFlags
No flags are set.
Definition: writer.h:64
kFalseType
@ kFalseType
false
Definition: rapidjson.h:605
kArrayType
@ kArrayType
array
Definition: rapidjson.h:608
kWriteNanAndInfFlag
@ kWriteNanAndInfFlag
Allow writing of Infinity, -Infinity and NaN.
Definition: writer.h:66
Transcoder
Encoding conversion.
Definition: encodings.h:658
Writer::maxDecimalPlaces_
int maxDecimalPlaces_
Definition: writer.h:472
Writer::Uint
bool Uint(unsigned u)
Definition: writer.h:175
Type
Type
Type of JSON value.
Definition: rapidjson.h:603
internal::Stack::Clear
void Clear()
Definition: stack.h:98
Z16
#define Z16
Writer::Double
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:184
Writer::hasRoot_
bool hasRoot_
Definition: writer.h:473
GenericStringStream::Peek
Ch Peek() const
Definition: stream.h:115
Writer::Int64
bool Int64(int64_t i64)
Definition: writer.h:176
kObjectType
@ kObjectType
object
Definition: rapidjson.h:607
Writer::WriteEndArray
bool WriteEndArray()
Definition: writer.h:432
Writer::Bool
bool Bool(bool b)
Definition: writer.h:173
PutUnsafe
void PutUnsafe(Stream &stream, typename Stream::Ch c)
Write character to a stream, presuming buffer is reserved.
Definition: stream.h:91
Writer::Level::valueCount
size_t valueCount
number of values in this level
Definition: writer.h:264
WriteFlag
WriteFlag
Combination of writeFlags.
Definition: writer.h:63
kWriteValidateEncodingFlag
@ kWriteValidateEncodingFlag
Validate encoding of JSON strings.
Definition: writer.h:65
Writer::Writer
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:99
Writer::ScanWriteUnescapedString
bool ScanWriteUnescapedString(GenericStringStream< SourceEncoding > &is, size_t length)
Definition: writer.h:425
Writer::IsComplete
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:134
Writer::WriteUint64
bool WriteUint64(uint64_t u64)
Definition: writer.h:314
Writer::SetMaxDecimalPlaces
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition: writer.h:163
Writer::WriteString
bool WriteString(const Ch *str, SizeType length)
Definition: writer.h:351
Writer::Level::Level
Level(bool inArray_)
Definition: writer.h:263
SizeType
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:380
Writer::WriteUint
bool WriteUint(unsigned u)
Definition: writer.h:296
Writer::Null
bool Null()
Definition: writer.h:172
Writer::EndObject
bool EndObject(SizeType memberCount=0)
Definition: writer.h:214
internal::i64toa
char * i64toa(int64_t value, char *buffer)
Definition: itoa.h:291
internal::Double
Definition: ieee754.h:23
stringbuffer.h
kStringType
@ kStringType
string
Definition: rapidjson.h:609
Writer::GetMaxDecimalPlaces
int GetMaxDecimalPlaces() const
Definition: writer.h:138
Writer::WriteStartArray
bool WriteStartArray()
Definition: writer.h:431
GenericStringStream
Read-only string stream.
Definition: fwd.h:47
Writer
JSON writer.
Definition: fwd.h:95
RAPIDJSON_ASSERT
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:402
itoa.h
GenericStringStream::Tell
size_t Tell() const
Definition: stream.h:117
RAPIDJSON_WRITE_DEFAULT_FLAGS
#define RAPIDJSON_WRITE_DEFAULT_FLAGS
Definition: writer.h:59
Writer::WriteBool
bool WriteBool(bool b)
Definition: writer.h:275
uint64_t
unsigned __int64 uint64_t
Definition: stdint.h:136
Writer::Key
bool Key(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:212
kNumberType
@ kNumberType
number
Definition: rapidjson.h:610
Writer::WriteInt64
bool WriteInt64(int64_t i64)
Definition: writer.h:305
c
constexpr QSpeed c
Definition: rquantities.hpp:351
Writer::WriteEndObject
bool WriteEndObject()
Definition: writer.h:430
stream.h
Writer::Prefix
void Prefix(Type type)
Definition: writer.h:443
Writer::StartArray
bool StartArray()
Definition: writer.h:222
internal::Stack::GetSize
size_t GetSize() const
Definition: stack.h:176
Writer::Level::inArray
bool inArray
true if in array, otherwise in object
Definition: writer.h:265
dtoa.h
GenericStringStream::src_
const Ch * src_
Current read position.
Definition: stream.h:124
Writer::level_stack_
internal::Stack< StackAllocator > level_stack_
Definition: writer.h:471
Writer::String
bool String(const Ch *str)
Simpler but slower overload.
Definition: writer.h:241
strfunc.h
PutReserve
void PutReserve(Stream &stream, size_t count)
Reserve n characters for writing to a stream.
Definition: stream.h:84
Writer::EndArray
bool EndArray(SizeType elementCount=0)
Definition: writer.h:228
Writer::os_
OutputStream * os_
Definition: writer.h:470
Writer::Int
bool Int(int i)
Definition: writer.h:174
int64_t
signed __int64 int64_t
Definition: stdint.h:135
internal::Stack< StackAllocator >
Writer::Writer
Writer(StackAllocator *allocator=0, size_t levelDepth=kDefaultLevelDepth)
Definition: writer.h:103
GenericStringStream::Take
Ch Take()
Definition: stream.h:116
Writer::StartObject
bool StartObject()
Definition: writer.h:206
Writer::WriteStartObject
bool WriteStartObject()
Definition: writer.h:429
Writer::Ch
SourceEncoding::Ch Ch
Definition: writer.h:89
Writer::kDefaultMaxDecimalPlaces
static const int kDefaultMaxDecimalPlaces
Definition: writer.h:91
internal::Stack::Empty
bool Empty() const
Definition: stack.h:175
kTrueType
@ kTrueType
true
Definition: rapidjson.h:606
Writer::kDefaultLevelDepth
static const size_t kDefaultLevelDepth
Definition: writer.h:268
Writer::String
bool String(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:193
Writer::WriteNull
bool WriteNull()
Definition: writer.h:270
Writer::Reset
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:124
internal::u64toa
char * u64toa(uint64_t value, char *buffer)
Definition: itoa.h:123
Writer::WriteInt
bool WriteInt(int i)
Definition: writer.h:287
GenericStringStream::head_
const Ch * head_
Original head of the string.
Definition: stream.h:125
Writer::Level
Information for each nested level.
Definition: writer.h:262
RAPIDJSON_LIKELY
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:455
internal::u32toa
char * u32toa(uint32_t value, char *buffer)
Definition: itoa.h:39
Writer::Uint64
bool Uint64(uint64_t u64)
Definition: writer.h:177
Writer::RawValue
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:254
RAPIDJSON_UNLIKELY
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:468
kWriteDefaultFlags
@ kWriteDefaultFlags
Default write flags.
Definition: writer.h:67
internal::StrLen
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
Definition: strfunc.h:30
Writer::EndValue
bool EndValue(bool ret)
Definition: writer.h:464
Writer::RawNumber
bool RawNumber(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:186
stack.h