all repos — mgba @ f6755a6e1b7b0cf2b944cd8ca842746f11d6bf82

mGBA Game Boy Advance Emulator

src/third-party/discord-rpc/include/rapidjson/writer.h (view raw)

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