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 __clang__
40 RAPIDJSON_DIAG_PUSH
41 RAPIDJSON_DIAG_OFF(padded)
42 RAPIDJSON_DIAG_OFF(unreachable-code)
43 RAPIDJSON_DIAG_OFF(c++98-compat)
44 #elif defined(_MSC_VER)
45 RAPIDJSON_DIAG_PUSH
46 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
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
Writer(Writer && rhs)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     */
Reset(OutputStream & os)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     */
IsComplete()143     bool IsComplete() const {
144         return hasRoot_ && level_stack_.Empty();
145     }
146 
GetMaxDecimalPlaces()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     */
SetMaxDecimalPlaces(int maxDecimalPlaces)172     void SetMaxDecimalPlaces(int maxDecimalPlaces) {
173         maxDecimalPlaces_ = maxDecimalPlaces;
174     }
175 
176     /*!@name Implementation of Handler
177         \see Handler
178     */
179     //@{
180 
Null()181     bool Null()                 { Prefix(kNullType);   return EndValue(WriteNull()); }
Bool(bool b)182     bool Bool(bool b)           { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
Int(int i)183     bool Int(int i)             { Prefix(kNumberType); return EndValue(WriteInt(i)); }
Uint(unsigned u)184     bool Uint(unsigned u)       { Prefix(kNumberType); return EndValue(WriteUint(u)); }
Int64(int64_t i64)185     bool Int64(int64_t i64)     { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
Uint64(uint64_t u64)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     */
Double(double d)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
String(const std::basic_string<Ch> & str)210     bool String(const std::basic_string<Ch>& str) {
211         return String(str.data(), SizeType(str.size()));
212     }
213 #endif
214 
StartObject()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 #if RAPIDJSON_HAS_STDSTRING
Key(const std::basic_string<Ch> & str)224     bool Key(const std::basic_string<Ch>& str)
225     {
226       return Key(str.data(), SizeType(str.size()));
227     }
228 #endif
229 
230     bool EndObject(SizeType memberCount = 0) {
231         (void)memberCount;
232         RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
233         RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object
234         RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value
235         level_stack_.template Pop<Level>(1);
236         return EndValue(WriteEndObject());
237     }
238 
StartArray()239     bool StartArray() {
240         Prefix(kArrayType);
241         new (level_stack_.template Push<Level>()) Level(true);
242         return WriteStartArray();
243     }
244 
245     bool EndArray(SizeType elementCount = 0) {
246         (void)elementCount;
247         RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
248         RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
249         level_stack_.template Pop<Level>(1);
250         return EndValue(WriteEndArray());
251     }
252     //@}
253 
254     /*! @name Convenience extensions */
255     //@{
256 
257     //! Simpler but slower overload.
String(const Ch * const & str)258     bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }
Key(const Ch * const & str)259     bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }
260 
261     //@}
262 
263     //! Write a raw JSON value.
264     /*!
265         For user to write a stringified JSON as a value.
266 
267         \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
268         \param length Length of the json.
269         \param type Type of the root of json.
270     */
RawValue(const Ch * json,size_t length,Type type)271     bool RawValue(const Ch* json, size_t length, Type type) {
272         RAPIDJSON_ASSERT(json != 0);
273         Prefix(type);
274         return EndValue(WriteRawValue(json, length));
275     }
276 
277     //! Flush the output stream.
278     /*!
279         Allows the user to flush the output stream immediately.
280      */
Flush()281     void Flush() {
282         os_->Flush();
283     }
284 
285 protected:
286     //! Information for each nested level
287     struct Level {
LevelLevel288         Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
289         size_t valueCount;  //!< number of values in this level
290         bool inArray;       //!< true if in array, otherwise in object
291     };
292 
293     static const size_t kDefaultLevelDepth = 32;
294 
WriteNull()295     bool WriteNull()  {
296         PutReserve(*os_, 4);
297         PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
298     }
299 
WriteBool(bool b)300     bool WriteBool(bool b)  {
301         if (b) {
302             PutReserve(*os_, 4);
303             PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
304         }
305         else {
306             PutReserve(*os_, 5);
307             PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
308         }
309         return true;
310     }
311 
WriteInt(int i)312     bool WriteInt(int i) {
313         char buffer[11];
314         const char* end = internal::i32toa(i, buffer);
315         PutReserve(*os_, static_cast<size_t>(end - buffer));
316         for (const char* p = buffer; p != end; ++p)
317             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
318         return true;
319     }
320 
WriteUint(unsigned u)321     bool WriteUint(unsigned u) {
322         char buffer[10];
323         const char* end = internal::u32toa(u, buffer);
324         PutReserve(*os_, static_cast<size_t>(end - buffer));
325         for (const char* p = buffer; p != end; ++p)
326             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
327         return true;
328     }
329 
WriteInt64(int64_t i64)330     bool WriteInt64(int64_t i64) {
331         char buffer[21];
332         const char* end = internal::i64toa(i64, buffer);
333         PutReserve(*os_, static_cast<size_t>(end - buffer));
334         for (const char* p = buffer; p != end; ++p)
335             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
336         return true;
337     }
338 
WriteUint64(uint64_t u64)339     bool WriteUint64(uint64_t u64) {
340         char buffer[20];
341         char* end = internal::u64toa(u64, buffer);
342         PutReserve(*os_, static_cast<size_t>(end - buffer));
343         for (char* p = buffer; p != end; ++p)
344             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
345         return true;
346     }
347 
WriteDouble(double d)348     bool WriteDouble(double d) {
349         if (internal::Double(d).IsNanOrInf()) {
350             if (!(writeFlags & kWriteNanAndInfFlag))
351                 return false;
352             if (internal::Double(d).IsNan()) {
353                 PutReserve(*os_, 3);
354                 PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
355                 return true;
356             }
357             if (internal::Double(d).Sign()) {
358                 PutReserve(*os_, 9);
359                 PutUnsafe(*os_, '-');
360             }
361             else
362                 PutReserve(*os_, 8);
363             PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
364             PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
365             return true;
366         }
367 
368         char buffer[25];
369         char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
370         PutReserve(*os_, static_cast<size_t>(end - buffer));
371         for (char* p = buffer; p != end; ++p)
372             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
373         return true;
374     }
375 
WriteString(const Ch * str,SizeType length)376     bool WriteString(const Ch* str, SizeType length)  {
377         static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
378         static const char escape[256] = {
379 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
380             //0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
381             'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
382             'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
383               0,   0, '"',   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20
384             Z16, Z16,                                                                       // 30~4F
385               0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,'\\',   0,   0,   0, // 50
386             Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16                                // 60~FF
387 #undef Z16
388         };
389 
390         if (TargetEncoding::supportUnicode)
391             PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
392         else
393             PutReserve(*os_, 2 + length * 12);  // "\uxxxx\uyyyy..."
394 
395         PutUnsafe(*os_, '\"');
396         GenericStringStream<SourceEncoding> is(str);
397         while (ScanWriteUnescapedString(is, length)) {
398             const Ch c = is.Peek();
399             if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
400                 // Unicode escaping
401                 unsigned codepoint;
402                 if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
403                     return false;
404                 PutUnsafe(*os_, '\\');
405                 PutUnsafe(*os_, 'u');
406                 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
407                     PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
408                     PutUnsafe(*os_, hexDigits[(codepoint >>  8) & 15]);
409                     PutUnsafe(*os_, hexDigits[(codepoint >>  4) & 15]);
410                     PutUnsafe(*os_, hexDigits[(codepoint      ) & 15]);
411                 }
412                 else {
413                     RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
414                     // Surrogate pair
415                     unsigned s = codepoint - 0x010000;
416                     unsigned lead = (s >> 10) + 0xD800;
417                     unsigned trail = (s & 0x3FF) + 0xDC00;
418                     PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
419                     PutUnsafe(*os_, hexDigits[(lead >>  8) & 15]);
420                     PutUnsafe(*os_, hexDigits[(lead >>  4) & 15]);
421                     PutUnsafe(*os_, hexDigits[(lead      ) & 15]);
422                     PutUnsafe(*os_, '\\');
423                     PutUnsafe(*os_, 'u');
424                     PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
425                     PutUnsafe(*os_, hexDigits[(trail >>  8) & 15]);
426                     PutUnsafe(*os_, hexDigits[(trail >>  4) & 15]);
427                     PutUnsafe(*os_, hexDigits[(trail      ) & 15]);
428                 }
429             }
430             else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)]))  {
431                 is.Take();
432                 PutUnsafe(*os_, '\\');
433                 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
434                 if (escape[static_cast<unsigned char>(c)] == 'u') {
435                     PutUnsafe(*os_, '0');
436                     PutUnsafe(*os_, '0');
437                     PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
438                     PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
439                 }
440             }
441             else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
442                 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
443                 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
444                 return false;
445         }
446         PutUnsafe(*os_, '\"');
447         return true;
448     }
449 
ScanWriteUnescapedString(GenericStringStream<SourceEncoding> & is,size_t length)450     bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
451         return RAPIDJSON_LIKELY(is.Tell() < length);
452     }
453 
WriteStartObject()454     bool WriteStartObject() { os_->Put('{'); return true; }
WriteEndObject()455     bool WriteEndObject()   { os_->Put('}'); return true; }
WriteStartArray()456     bool WriteStartArray()  { os_->Put('['); return true; }
WriteEndArray()457     bool WriteEndArray()    { os_->Put(']'); return true; }
458 
WriteRawValue(const Ch * json,size_t length)459     bool WriteRawValue(const Ch* json, size_t length) {
460         PutReserve(*os_, length);
461         GenericStringStream<SourceEncoding> is(json);
462         while (RAPIDJSON_LIKELY(is.Tell() < length)) {
463             const Ch c = is.Peek();
464             RAPIDJSON_ASSERT(c != '\0');
465             if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
466                 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
467                 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
468                 return false;
469         }
470         return true;
471     }
472 
Prefix(Type type)473     void Prefix(Type type) {
474         (void)type;
475         if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
476             Level* level = level_stack_.template Top<Level>();
477             if (level->valueCount > 0) {
478                 if (level->inArray)
479                     os_->Put(','); // add comma if it is not the first element in array
480                 else  // in object
481                     os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
482             }
483             if (!level->inArray && level->valueCount % 2 == 0)
484                 RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name
485             level->valueCount++;
486         }
487         else {
488             RAPIDJSON_ASSERT(!hasRoot_);    // Should only has one and only one root.
489             hasRoot_ = true;
490         }
491     }
492 
493     // Flush the value if it is the top level one.
EndValue(bool ret)494     bool EndValue(bool ret) {
495         if (RAPIDJSON_UNLIKELY(level_stack_.Empty()))   // end of json text
496             Flush();
497         return ret;
498     }
499 
500     OutputStream* os_;
501     internal::Stack<StackAllocator> level_stack_;
502     int maxDecimalPlaces_;
503     bool hasRoot_;
504 
505 private:
506     // Prohibit copy constructor & assignment operator.
507     Writer(const Writer&);
508     Writer& operator=(const Writer&);
509 };
510 
511 // Full specialization for StringStream to prevent memory copying
512 
513 template<>
WriteInt(int i)514 inline bool Writer<StringBuffer>::WriteInt(int i) {
515     char *buffer = os_->Push(11);
516     const char* end = internal::i32toa(i, buffer);
517     os_->Pop(static_cast<size_t>(11 - (end - buffer)));
518     return true;
519 }
520 
521 template<>
WriteUint(unsigned u)522 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
523     char *buffer = os_->Push(10);
524     const char* end = internal::u32toa(u, buffer);
525     os_->Pop(static_cast<size_t>(10 - (end - buffer)));
526     return true;
527 }
528 
529 template<>
WriteInt64(int64_t i64)530 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
531     char *buffer = os_->Push(21);
532     const char* end = internal::i64toa(i64, buffer);
533     os_->Pop(static_cast<size_t>(21 - (end - buffer)));
534     return true;
535 }
536 
537 template<>
WriteUint64(uint64_t u)538 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
539     char *buffer = os_->Push(20);
540     const char* end = internal::u64toa(u, buffer);
541     os_->Pop(static_cast<size_t>(20 - (end - buffer)));
542     return true;
543 }
544 
545 template<>
WriteDouble(double d)546 inline bool Writer<StringBuffer>::WriteDouble(double d) {
547     if (internal::Double(d).IsNanOrInf()) {
548         // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
549         if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
550             return false;
551         if (internal::Double(d).IsNan()) {
552             PutReserve(*os_, 3);
553             PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
554             return true;
555         }
556         if (internal::Double(d).Sign()) {
557             PutReserve(*os_, 9);
558             PutUnsafe(*os_, '-');
559         }
560         else
561             PutReserve(*os_, 8);
562         PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
563         PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
564         return true;
565     }
566 
567     char *buffer = os_->Push(25);
568     char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
569     os_->Pop(static_cast<size_t>(25 - (end - buffer)));
570     return true;
571 }
572 
573 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
574 template<>
ScanWriteUnescapedString(StringStream & is,size_t length)575 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
576     if (length < 16)
577         return RAPIDJSON_LIKELY(is.Tell() < length);
578 
579     if (!RAPIDJSON_LIKELY(is.Tell() < length))
580         return false;
581 
582     const char* p = is.src_;
583     const char* end = is.head_ + length;
584     const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
585     const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
586     if (nextAligned > end)
587         return true;
588 
589     while (p != nextAligned)
590         if (*p < 0x20 || *p == '\"' || *p == '\\') {
591             is.src_ = p;
592             return RAPIDJSON_LIKELY(is.Tell() < length);
593         }
594         else
595             os_->PutUnsafe(*p++);
596 
597     // The rest of string using SIMD
598     static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
599     static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
600     static const char space[16]  = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
601     const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
602     const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
603     const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
604 
605     for (; p != endAligned; p += 16) {
606         const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
607         const __m128i t1 = _mm_cmpeq_epi8(s, dq);
608         const __m128i t2 = _mm_cmpeq_epi8(s, bs);
609         const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
610         const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
611         unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
612         if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped
613             SizeType len;
614 #ifdef _MSC_VER         // Find the index of first escaped
615             unsigned long offset;
616             _BitScanForward(&offset, r);
617             len = offset;
618 #else
619             len = static_cast<SizeType>(__builtin_ffs(r) - 1);
620 #endif
621             char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
622             for (size_t i = 0; i < len; i++)
623                 q[i] = p[i];
624 
625             p += len;
626             break;
627         }
628         _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
629     }
630 
631     is.src_ = p;
632     return RAPIDJSON_LIKELY(is.Tell() < length);
633 }
634 #elif defined(RAPIDJSON_NEON)
635 template<>
ScanWriteUnescapedString(StringStream & is,size_t length)636 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
637     if (length < 16)
638         return RAPIDJSON_LIKELY(is.Tell() < length);
639 
640     if (!RAPIDJSON_LIKELY(is.Tell() < length))
641         return false;
642 
643     const char* p = is.src_;
644     const char* end = is.head_ + length;
645     const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
646     const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
647     if (nextAligned > end)
648         return true;
649 
650     while (p != nextAligned)
651         if (*p < 0x20 || *p == '\"' || *p == '\\') {
652             is.src_ = p;
653             return RAPIDJSON_LIKELY(is.Tell() < length);
654         }
655         else
656             os_->PutUnsafe(*p++);
657 
658     // The rest of string using SIMD
659     const uint8x16_t s0 = vmovq_n_u8('"');
660     const uint8x16_t s1 = vmovq_n_u8('\\');
661     const uint8x16_t s2 = vmovq_n_u8('\b');
662     const uint8x16_t s3 = vmovq_n_u8(32);
663 
664     for (; p != endAligned; p += 16) {
665         const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
666         uint8x16_t x = vceqq_u8(s, s0);
667         x = vorrq_u8(x, vceqq_u8(s, s1));
668         x = vorrq_u8(x, vceqq_u8(s, s2));
669         x = vorrq_u8(x, vcltq_u8(s, s3));
670 
671         x = vrev64q_u8(x);                     // Rev in 64
672         uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0);   // extract
673         uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1);  // extract
674 
675         SizeType len = 0;
676         bool escaped = false;
677         if (low == 0) {
678             if (high != 0) {
679                 unsigned lz = (unsigned)__builtin_clzll(high);
680                 len = 8 + (lz >> 3);
681                 escaped = true;
682             }
683         } else {
684             unsigned lz = (unsigned)__builtin_clzll(low);
685             len = lz >> 3;
686             escaped = true;
687         }
688         if (RAPIDJSON_UNLIKELY(escaped)) {   // some of characters is escaped
689             char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
690             for (size_t i = 0; i < len; i++)
691                 q[i] = p[i];
692 
693             p += len;
694             break;
695         }
696         vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
697     }
698 
699     is.src_ = p;
700     return RAPIDJSON_LIKELY(is.Tell() < length);
701 }
702 #endif // RAPIDJSON_NEON
703 
704 RAPIDJSON_NAMESPACE_END
705 
706 #if defined(_MSC_VER) || defined(__clang__)
707 RAPIDJSON_DIAG_POP
708 #endif
709 
710 #endif // RAPIDJSON_RAPIDJSON_H_
711