rlottie/rapidjson: updated to latest rapidjson
[platform/core/uifw/lottie-player.git] / src / lottie / rapidjson / 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/clzll.h"
20 #include "internal/meta.h"
21 #include "internal/stack.h"
22 #include "internal/strfunc.h"
23 #include "internal/dtoa.h"
24 #include "internal/itoa.h"
25 #include "stringbuffer.h"
26 #include <new>      // placement new
27
28 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
29 #include <intrin.h>
30 #pragma intrinsic(_BitScanForward)
31 #endif
32 #ifdef RAPIDJSON_SSE42
33 #include <nmmintrin.h>
34 #elif defined(RAPIDJSON_SSE2)
35 #include <emmintrin.h>
36 #elif defined(RAPIDJSON_NEON)
37 #include <arm_neon.h>
38 #endif
39
40 #ifdef __clang__
41 RAPIDJSON_DIAG_PUSH
42 RAPIDJSON_DIAG_OFF(padded)
43 RAPIDJSON_DIAG_OFF(unreachable-code)
44 RAPIDJSON_DIAG_OFF(c++98-compat)
45 #elif defined(_MSC_VER)
46 RAPIDJSON_DIAG_PUSH
47 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
48 #endif
49
50 RAPIDJSON_NAMESPACE_BEGIN
51
52 ///////////////////////////////////////////////////////////////////////////////
53 // WriteFlag
54
55 /*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS 
56     \ingroup RAPIDJSON_CONFIG
57     \brief User-defined kWriteDefaultFlags definition.
58
59     User can define this as any \c WriteFlag combinations.
60 */
61 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
62 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
63 #endif
64
65 //! Combination of writeFlags
66 enum WriteFlag {
67     kWriteNoFlags = 0,              //!< No flags are set.
68     kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
69     kWriteNanAndInfFlag = 2,        //!< Allow writing of Infinity, -Infinity and NaN.
70     kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS  //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
71 };
72
73 //! JSON writer
74 /*! Writer implements the concept Handler.
75     It generates JSON text by events to an output os.
76
77     User may programmatically calls the functions of a writer to generate JSON text.
78
79     On the other side, a writer can also be passed to objects that generates events, 
80
81     for example Reader::Parse() and Document::Accept().
82
83     \tparam OutputStream Type of output stream.
84     \tparam SourceEncoding Encoding of source string.
85     \tparam TargetEncoding Encoding of output stream.
86     \tparam StackAllocator Type of allocator for allocating memory of stack.
87     \note implements Handler concept
88 */
89 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
90 class Writer {
91 public:
92     typedef typename SourceEncoding::Ch Ch;
93
94     static const int kDefaultMaxDecimalPlaces = 324;
95
96     //! Constructor
97     /*! \param os Output stream.
98         \param stackAllocator User supplied allocator. If it is null, it will create a private one.
99         \param levelDepth Initial capacity of stack.
100     */
101     explicit
102     Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : 
103         os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
104
105     explicit
106     Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
107         os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
108
109 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
110     Writer(Writer&& rhs) :
111         os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
112         rhs.os_ = 0;
113     }
114 #endif
115
116     //! Reset the writer with a new stream.
117     /*!
118         This function reset the writer with a new stream and default settings,
119         in order to make a Writer object reusable for output multiple JSONs.
120
121         \param os New output stream.
122         \code
123         Writer<OutputStream> writer(os1);
124         writer.StartObject();
125         // ...
126         writer.EndObject();
127
128         writer.Reset(os2);
129         writer.StartObject();
130         // ...
131         writer.EndObject();
132         \endcode
133     */
134     void Reset(OutputStream& os) {
135         os_ = &os;
136         hasRoot_ = false;
137         level_stack_.Clear();
138     }
139
140     //! Checks whether the output is a complete JSON.
141     /*!
142         A complete JSON has a complete root object or array.
143     */
144     bool IsComplete() const {
145         return hasRoot_ && level_stack_.Empty();
146     }
147
148     int GetMaxDecimalPlaces() const {
149         return maxDecimalPlaces_;
150     }
151
152     //! Sets the maximum number of decimal places for double output.
153     /*!
154         This setting truncates the output with specified number of decimal places.
155
156         For example, 
157
158         \code
159         writer.SetMaxDecimalPlaces(3);
160         writer.StartArray();
161         writer.Double(0.12345);                 // "0.123"
162         writer.Double(0.0001);                  // "0.0"
163         writer.Double(1.234567890123456e30);    // "1.234567890123456e30" (do not truncate significand for positive exponent)
164         writer.Double(1.23e-4);                 // "0.0"                  (do truncate significand for negative exponent)
165         writer.EndArray();
166         \endcode
167
168         The default setting does not truncate any decimal places. You can restore to this setting by calling
169         \code
170         writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
171         \endcode
172     */
173     void SetMaxDecimalPlaces(int maxDecimalPlaces) {
174         maxDecimalPlaces_ = maxDecimalPlaces;
175     }
176
177     /*!@name Implementation of Handler
178         \see Handler
179     */
180     //@{
181
182     bool Null()                 { Prefix(kNullType);   return EndValue(WriteNull()); }
183     bool Bool(bool b)           { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
184     bool Int(int i)             { Prefix(kNumberType); return EndValue(WriteInt(i)); }
185     bool Uint(unsigned u)       { Prefix(kNumberType); return EndValue(WriteUint(u)); }
186     bool Int64(int64_t i64)     { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
187     bool Uint64(uint64_t u64)   { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
188
189     //! Writes the given \c double value to the stream
190     /*!
191         \param d The value to be written.
192         \return Whether it is succeed.
193     */
194     bool Double(double d)       { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
195
196     bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
197         RAPIDJSON_ASSERT(str != 0);
198         (void)copy;
199         Prefix(kNumberType);
200         return EndValue(WriteString(str, length));
201     }
202
203     bool String(const Ch* str, SizeType length, bool copy = false) {
204         RAPIDJSON_ASSERT(str != 0);
205         (void)copy;
206         Prefix(kStringType);
207         return EndValue(WriteString(str, length));
208     }
209
210 #if RAPIDJSON_HAS_STDSTRING
211     bool String(const std::basic_string<Ch>& str) {
212         return String(str.data(), SizeType(str.size()));
213     }
214 #endif
215
216     bool StartObject() {
217         Prefix(kObjectType);
218         new (level_stack_.template Push<Level>()) Level(false);
219         return WriteStartObject();
220     }
221
222     bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
223
224 #if RAPIDJSON_HAS_STDSTRING
225     bool Key(const std::basic_string<Ch>& str)
226     {
227       return Key(str.data(), SizeType(str.size()));
228     }
229 #endif
230
231     bool EndObject(SizeType memberCount = 0) {
232         (void)memberCount;
233         RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
234         RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object
235         RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value
236         level_stack_.template Pop<Level>(1);
237         return EndValue(WriteEndObject());
238     }
239
240     bool StartArray() {
241         Prefix(kArrayType);
242         new (level_stack_.template Push<Level>()) Level(true);
243         return WriteStartArray();
244     }
245
246     bool EndArray(SizeType elementCount = 0) {
247         (void)elementCount;
248         RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
249         RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
250         level_stack_.template Pop<Level>(1);
251         return EndValue(WriteEndArray());
252     }
253     //@}
254
255     /*! @name Convenience extensions */
256     //@{
257
258     //! Simpler but slower overload.
259     bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }
260     bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }
261     
262     //@}
263
264     //! Write a raw JSON value.
265     /*!
266         For user to write a stringified JSON as a value.
267
268         \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
269         \param length Length of the json.
270         \param type Type of the root of json.
271     */
272     bool RawValue(const Ch* json, size_t length, Type type) {
273         RAPIDJSON_ASSERT(json != 0);
274         Prefix(type);
275         return EndValue(WriteRawValue(json, length));
276     }
277
278     //! Flush the output stream.
279     /*!
280         Allows the user to flush the output stream immediately.
281      */
282     void Flush() {
283         os_->Flush();
284     }
285
286     static const size_t kDefaultLevelDepth = 32;
287
288 protected:
289     //! Information for each nested level
290     struct Level {
291         Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
292         size_t valueCount;  //!< number of values in this level
293         bool inArray;       //!< true if in array, otherwise in object
294     };
295
296     bool WriteNull()  {
297         PutReserve(*os_, 4);
298         PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
299     }
300
301     bool WriteBool(bool b)  {
302         if (b) {
303             PutReserve(*os_, 4);
304             PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
305         }
306         else {
307             PutReserve(*os_, 5);
308             PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
309         }
310         return true;
311     }
312
313     bool WriteInt(int i) {
314         char buffer[11];
315         const char* end = internal::i32toa(i, buffer);
316         PutReserve(*os_, static_cast<size_t>(end - buffer));
317         for (const char* p = buffer; p != end; ++p)
318             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
319         return true;
320     }
321
322     bool WriteUint(unsigned u) {
323         char buffer[10];
324         const char* end = internal::u32toa(u, buffer);
325         PutReserve(*os_, static_cast<size_t>(end - buffer));
326         for (const char* p = buffer; p != end; ++p)
327             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
328         return true;
329     }
330
331     bool WriteInt64(int64_t i64) {
332         char buffer[21];
333         const char* end = internal::i64toa(i64, buffer);
334         PutReserve(*os_, static_cast<size_t>(end - buffer));
335         for (const char* p = buffer; p != end; ++p)
336             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
337         return true;
338     }
339
340     bool WriteUint64(uint64_t u64) {
341         char buffer[20];
342         char* end = internal::u64toa(u64, buffer);
343         PutReserve(*os_, static_cast<size_t>(end - buffer));
344         for (char* p = buffer; p != end; ++p)
345             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
346         return true;
347     }
348
349     bool WriteDouble(double d) {
350         if (internal::Double(d).IsNanOrInf()) {
351             if (!(writeFlags & kWriteNanAndInfFlag))
352                 return false;
353             if (internal::Double(d).IsNan()) {
354                 PutReserve(*os_, 3);
355                 PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
356                 return true;
357             }
358             if (internal::Double(d).Sign()) {
359                 PutReserve(*os_, 9);
360                 PutUnsafe(*os_, '-');
361             }
362             else
363                 PutReserve(*os_, 8);
364             PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
365             PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
366             return true;
367         }
368
369         char buffer[25];
370         char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
371         PutReserve(*os_, static_cast<size_t>(end - buffer));
372         for (char* p = buffer; p != end; ++p)
373             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
374         return true;
375     }
376
377     bool WriteString(const Ch* str, SizeType length)  {
378         static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
379         static const char escape[256] = {
380 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
381             //0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
382             'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
383             'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
384               0,   0, '"',   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20
385             Z16, Z16,                                                                       // 30~4F
386               0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,'\\',   0,   0,   0, // 50
387             Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16                                // 60~FF
388 #undef Z16
389         };
390
391         if (TargetEncoding::supportUnicode)
392             PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
393         else
394             PutReserve(*os_, 2 + length * 12);  // "\uxxxx\uyyyy..."
395
396         PutUnsafe(*os_, '\"');
397         GenericStringStream<SourceEncoding> is(str);
398         while (ScanWriteUnescapedString(is, length)) {
399             const Ch c = is.Peek();
400             if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
401                 // Unicode escaping
402                 unsigned codepoint;
403                 if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
404                     return false;
405                 PutUnsafe(*os_, '\\');
406                 PutUnsafe(*os_, 'u');
407                 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
408                     PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
409                     PutUnsafe(*os_, hexDigits[(codepoint >>  8) & 15]);
410                     PutUnsafe(*os_, hexDigits[(codepoint >>  4) & 15]);
411                     PutUnsafe(*os_, hexDigits[(codepoint      ) & 15]);
412                 }
413                 else {
414                     RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
415                     // Surrogate pair
416                     unsigned s = codepoint - 0x010000;
417                     unsigned lead = (s >> 10) + 0xD800;
418                     unsigned trail = (s & 0x3FF) + 0xDC00;
419                     PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
420                     PutUnsafe(*os_, hexDigits[(lead >>  8) & 15]);
421                     PutUnsafe(*os_, hexDigits[(lead >>  4) & 15]);
422                     PutUnsafe(*os_, hexDigits[(lead      ) & 15]);
423                     PutUnsafe(*os_, '\\');
424                     PutUnsafe(*os_, 'u');
425                     PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
426                     PutUnsafe(*os_, hexDigits[(trail >>  8) & 15]);
427                     PutUnsafe(*os_, hexDigits[(trail >>  4) & 15]);
428                     PutUnsafe(*os_, hexDigits[(trail      ) & 15]);                    
429                 }
430             }
431             else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)]))  {
432                 is.Take();
433                 PutUnsafe(*os_, '\\');
434                 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
435                 if (escape[static_cast<unsigned char>(c)] == 'u') {
436                     PutUnsafe(*os_, '0');
437                     PutUnsafe(*os_, '0');
438                     PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
439                     PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
440                 }
441             }
442             else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? 
443                 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
444                 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
445                 return false;
446         }
447         PutUnsafe(*os_, '\"');
448         return true;
449     }
450
451     bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
452         return RAPIDJSON_LIKELY(is.Tell() < length);
453     }
454
455     bool WriteStartObject() { os_->Put('{'); return true; }
456     bool WriteEndObject()   { os_->Put('}'); return true; }
457     bool WriteStartArray()  { os_->Put('['); return true; }
458     bool WriteEndArray()    { os_->Put(']'); return true; }
459
460     bool WriteRawValue(const Ch* json, size_t length) {
461         PutReserve(*os_, length);
462         GenericStringStream<SourceEncoding> is(json);
463         while (RAPIDJSON_LIKELY(is.Tell() < length)) {
464             RAPIDJSON_ASSERT(is.Peek() != '\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
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.
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<>
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<>
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<>
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<>
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<>
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<>
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<>
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(vreinterpretq_u64_u8(x), 0);   // extract
673         uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);  // extract
674
675         SizeType len = 0;
676         bool escaped = false;
677         if (low == 0) {
678             if (high != 0) {
679                 uint32_t lz = internal::clzll(high);
680                 len = 8 + (lz >> 3);
681                 escaped = true;
682             }
683         } else {
684             uint32_t lz = internal::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_