Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:06

0001 // Tencent is pleased to support the open source community by making RapidJSON available.
0002 // 
0003 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
0004 //
0005 // Licensed under the MIT License (the "License"); you may not use this file except
0006 // in compliance with the License. You may obtain a copy of the License at
0007 //
0008 // http://opensource.org/licenses/MIT
0009 //
0010 // Unless required by applicable law or agreed to in writing, software distributed 
0011 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
0012 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 
0013 // specific language governing permissions and limitations under the License.
0014 
0015 #ifndef RAPIDJSON_WRITER_H_
0016 #define RAPIDJSON_WRITER_H_
0017 
0018 #include "stream.h"
0019 #include "internal/clzll.h"
0020 #include "internal/meta.h"
0021 #include "internal/stack.h"
0022 #include "internal/strfunc.h"
0023 #include "internal/dtoa.h"
0024 #include "internal/itoa.h"
0025 #include "stringbuffer.h"
0026 #include <new>      // placement new
0027 
0028 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
0029 #include <intrin.h>
0030 #pragma intrinsic(_BitScanForward)
0031 #endif
0032 #ifdef RAPIDJSON_SSE42
0033 #include <nmmintrin.h>
0034 #elif defined(RAPIDJSON_SSE2)
0035 #include <emmintrin.h>
0036 #elif defined(RAPIDJSON_NEON)
0037 #include <arm_neon.h>
0038 #endif
0039 
0040 #ifdef __clang__
0041 RAPIDJSON_DIAG_PUSH
0042 RAPIDJSON_DIAG_OFF(padded)
0043 RAPIDJSON_DIAG_OFF(unreachable-code)
0044 RAPIDJSON_DIAG_OFF(c++98-compat)
0045 #elif defined(_MSC_VER)
0046 RAPIDJSON_DIAG_PUSH
0047 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
0048 #endif
0049 
0050 RAPIDJSON_NAMESPACE_BEGIN
0051 
0052 ///////////////////////////////////////////////////////////////////////////////
0053 // WriteFlag
0054 
0055 /*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS 
0056     \ingroup RAPIDJSON_CONFIG
0057     \brief User-defined kWriteDefaultFlags definition.
0058 
0059     User can define this as any \c WriteFlag combinations.
0060 */
0061 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
0062 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
0063 #endif
0064 
0065 //! Combination of writeFlags
0066 enum WriteFlag {
0067     kWriteNoFlags = 0,              //!< No flags are set.
0068     kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
0069     kWriteNanAndInfFlag = 2,        //!< Allow writing of Infinity, -Infinity and NaN.
0070     kWriteNanAndInfNullFlag = 4,    //!< Allow writing of Infinity, -Infinity and NaN as null.
0071     kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS  //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
0072 };
0073 
0074 //! JSON writer
0075 /*! Writer implements the concept Handler.
0076     It generates JSON text by events to an output os.
0077 
0078     User may programmatically calls the functions of a writer to generate JSON text.
0079 
0080     On the other side, a writer can also be passed to objects that generates events, 
0081 
0082     for example Reader::Parse() and Document::Accept().
0083 
0084     \tparam OutputStream Type of output stream.
0085     \tparam SourceEncoding Encoding of source string.
0086     \tparam TargetEncoding Encoding of output stream.
0087     \tparam StackAllocator Type of allocator for allocating memory of stack.
0088     \note implements Handler concept
0089 */
0090 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
0091 class Writer {
0092 public:
0093     typedef typename SourceEncoding::Ch Ch;
0094 
0095     static const int kDefaultMaxDecimalPlaces = 324;
0096 
0097     //! Constructor
0098     /*! \param os Output stream.
0099         \param stackAllocator User supplied allocator. If it is null, it will create a private one.
0100         \param levelDepth Initial capacity of stack.
0101     */
0102     explicit
0103     Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : 
0104         os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
0105 
0106     explicit
0107     Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
0108         os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
0109 
0110 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
0111     Writer(Writer&& rhs) :
0112         os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
0113         rhs.os_ = 0;
0114     }
0115 #endif
0116 
0117     //! Reset the writer with a new stream.
0118     /*!
0119         This function reset the writer with a new stream and default settings,
0120         in order to make a Writer object reusable for output multiple JSONs.
0121 
0122         \param os New output stream.
0123         \code
0124         Writer<OutputStream> writer(os1);
0125         writer.StartObject();
0126         // ...
0127         writer.EndObject();
0128 
0129         writer.Reset(os2);
0130         writer.StartObject();
0131         // ...
0132         writer.EndObject();
0133         \endcode
0134     */
0135     void Reset(OutputStream& os) {
0136         os_ = &os;
0137         hasRoot_ = false;
0138         level_stack_.Clear();
0139     }
0140 
0141     //! Checks whether the output is a complete JSON.
0142     /*!
0143         A complete JSON has a complete root object or array.
0144     */
0145     bool IsComplete() const {
0146         return hasRoot_ && level_stack_.Empty();
0147     }
0148 
0149     int GetMaxDecimalPlaces() const {
0150         return maxDecimalPlaces_;
0151     }
0152 
0153     //! Sets the maximum number of decimal places for double output.
0154     /*!
0155         This setting truncates the output with specified number of decimal places.
0156 
0157         For example, 
0158 
0159         \code
0160         writer.SetMaxDecimalPlaces(3);
0161         writer.StartArray();
0162         writer.Double(0.12345);                 // "0.123"
0163         writer.Double(0.0001);                  // "0.0"
0164         writer.Double(1.234567890123456e30);    // "1.234567890123456e30" (do not truncate significand for positive exponent)
0165         writer.Double(1.23e-4);                 // "0.0"                  (do truncate significand for negative exponent)
0166         writer.EndArray();
0167         \endcode
0168 
0169         The default setting does not truncate any decimal places. You can restore to this setting by calling
0170         \code
0171         writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
0172         \endcode
0173     */
0174     void SetMaxDecimalPlaces(int maxDecimalPlaces) {
0175         maxDecimalPlaces_ = maxDecimalPlaces;
0176     }
0177 
0178     /*!@name Implementation of Handler
0179         \see Handler
0180     */
0181     //@{
0182 
0183     bool Null()                 { Prefix(kNullType);   return EndValue(WriteNull()); }
0184     bool Bool(bool b)           { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
0185     bool Int(int i)             { Prefix(kNumberType); return EndValue(WriteInt(i)); }
0186     bool Uint(unsigned u)       { Prefix(kNumberType); return EndValue(WriteUint(u)); }
0187     bool Int64(int64_t i64)     { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
0188     bool Uint64(uint64_t u64)   { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
0189 
0190     //! Writes the given \c double value to the stream
0191     /*!
0192         \param d The value to be written.
0193         \return Whether it is succeed.
0194     */
0195     bool Double(double d)       { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
0196 
0197     bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
0198         RAPIDJSON_ASSERT(str != 0);
0199         (void)copy;
0200         Prefix(kNumberType);
0201         return EndValue(WriteString(str, length));
0202     }
0203 
0204     bool String(const Ch* str, SizeType length, bool copy = false) {
0205         RAPIDJSON_ASSERT(str != 0);
0206         (void)copy;
0207         Prefix(kStringType);
0208         return EndValue(WriteString(str, length));
0209     }
0210 
0211 #if RAPIDJSON_HAS_STDSTRING
0212     bool String(const std::basic_string<Ch>& str) {
0213         return String(str.data(), SizeType(str.size()));
0214     }
0215 #endif
0216 
0217     bool StartObject() {
0218         Prefix(kObjectType);
0219         new (level_stack_.template Push<Level>()) Level(false);
0220         return WriteStartObject();
0221     }
0222 
0223     bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
0224 
0225 #if RAPIDJSON_HAS_STDSTRING
0226     bool Key(const std::basic_string<Ch>& str)
0227     {
0228       return Key(str.data(), SizeType(str.size()));
0229     }
0230 #endif
0231 
0232     bool EndObject(SizeType memberCount = 0) {
0233         (void)memberCount;
0234         RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
0235         RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object
0236         RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value
0237         level_stack_.template Pop<Level>(1);
0238         return EndValue(WriteEndObject());
0239     }
0240 
0241     bool StartArray() {
0242         Prefix(kArrayType);
0243         new (level_stack_.template Push<Level>()) Level(true);
0244         return WriteStartArray();
0245     }
0246 
0247     bool EndArray(SizeType elementCount = 0) {
0248         (void)elementCount;
0249         RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
0250         RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
0251         level_stack_.template Pop<Level>(1);
0252         return EndValue(WriteEndArray());
0253     }
0254     //@}
0255 
0256     /*! @name Convenience extensions */
0257     //@{
0258 
0259     //! Simpler but slower overload.
0260     bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }
0261     bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }
0262     
0263     //@}
0264 
0265     //! Write a raw JSON value.
0266     /*!
0267         For user to write a stringified JSON as a value.
0268 
0269         \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
0270         \param length Length of the json.
0271         \param type Type of the root of json.
0272     */
0273     bool RawValue(const Ch* json, size_t length, Type type) {
0274         RAPIDJSON_ASSERT(json != 0);
0275         Prefix(type);
0276         return EndValue(WriteRawValue(json, length));
0277     }
0278 
0279     //! Flush the output stream.
0280     /*!
0281         Allows the user to flush the output stream immediately.
0282      */
0283     void Flush() {
0284         os_->Flush();
0285     }
0286 
0287     static const size_t kDefaultLevelDepth = 32;
0288 
0289 protected:
0290     //! Information for each nested level
0291     struct Level {
0292         Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
0293         size_t valueCount;  //!< number of values in this level
0294         bool inArray;       //!< true if in array, otherwise in object
0295     };
0296 
0297     bool WriteNull()  {
0298         PutReserve(*os_, 4);
0299         PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
0300     }
0301 
0302     bool WriteBool(bool b)  {
0303         if (b) {
0304             PutReserve(*os_, 4);
0305             PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
0306         }
0307         else {
0308             PutReserve(*os_, 5);
0309             PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
0310         }
0311         return true;
0312     }
0313 
0314     bool WriteInt(int i) {
0315         char buffer[11];
0316         const char* end = internal::i32toa(i, buffer);
0317         PutReserve(*os_, static_cast<size_t>(end - buffer));
0318         for (const char* p = buffer; p != end; ++p)
0319             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
0320         return true;
0321     }
0322 
0323     bool WriteUint(unsigned u) {
0324         char buffer[10];
0325         const char* end = internal::u32toa(u, buffer);
0326         PutReserve(*os_, static_cast<size_t>(end - buffer));
0327         for (const char* p = buffer; p != end; ++p)
0328             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
0329         return true;
0330     }
0331 
0332     bool WriteInt64(int64_t i64) {
0333         char buffer[21];
0334         const char* end = internal::i64toa(i64, buffer);
0335         PutReserve(*os_, static_cast<size_t>(end - buffer));
0336         for (const char* p = buffer; p != end; ++p)
0337             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
0338         return true;
0339     }
0340 
0341     bool WriteUint64(uint64_t u64) {
0342         char buffer[20];
0343         char* end = internal::u64toa(u64, buffer);
0344         PutReserve(*os_, static_cast<size_t>(end - buffer));
0345         for (char* p = buffer; p != end; ++p)
0346             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
0347         return true;
0348     }
0349 
0350     bool WriteDouble(double d) {
0351         if (internal::Double(d).IsNanOrInf()) {
0352             if (!(writeFlags & kWriteNanAndInfFlag) && !(writeFlags & kWriteNanAndInfNullFlag))
0353                 return false;
0354             if (writeFlags & kWriteNanAndInfNullFlag) {
0355                 PutReserve(*os_, 4);
0356                 PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l');
0357                 return true;
0358             }
0359             if (internal::Double(d).IsNan()) {
0360                 PutReserve(*os_, 3);
0361                 PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
0362                 return true;
0363             }
0364             if (internal::Double(d).Sign()) {
0365                 PutReserve(*os_, 9);
0366                 PutUnsafe(*os_, '-');
0367             }
0368             else
0369                 PutReserve(*os_, 8);
0370             PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
0371             PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
0372             return true;
0373         }
0374 
0375         char buffer[25];
0376         char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
0377         PutReserve(*os_, static_cast<size_t>(end - buffer));
0378         for (char* p = buffer; p != end; ++p)
0379             PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
0380         return true;
0381     }
0382 
0383     bool WriteString(const Ch* str, SizeType length)  {
0384         static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
0385         static const char escape[256] = {
0386 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0387             //0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
0388             'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
0389             'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
0390               0,   0, '"',   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20
0391             Z16, Z16,                                                                       // 30~4F
0392               0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,'\\',   0,   0,   0, // 50
0393             Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16                                // 60~FF
0394 #undef Z16
0395         };
0396 
0397         if (TargetEncoding::supportUnicode)
0398             PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
0399         else
0400             PutReserve(*os_, 2 + length * 12);  // "\uxxxx\uyyyy..."
0401 
0402         PutUnsafe(*os_, '\"');
0403         GenericStringStream<SourceEncoding> is(str);
0404         while (ScanWriteUnescapedString(is, length)) {
0405             const Ch c = is.Peek();
0406             if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
0407                 // Unicode escaping
0408                 unsigned codepoint;
0409                 if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
0410                     return false;
0411                 PutUnsafe(*os_, '\\');
0412                 PutUnsafe(*os_, 'u');
0413                 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
0414                     PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
0415                     PutUnsafe(*os_, hexDigits[(codepoint >>  8) & 15]);
0416                     PutUnsafe(*os_, hexDigits[(codepoint >>  4) & 15]);
0417                     PutUnsafe(*os_, hexDigits[(codepoint      ) & 15]);
0418                 }
0419                 else {
0420                     RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
0421                     // Surrogate pair
0422                     unsigned s = codepoint - 0x010000;
0423                     unsigned lead = (s >> 10) + 0xD800;
0424                     unsigned trail = (s & 0x3FF) + 0xDC00;
0425                     PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
0426                     PutUnsafe(*os_, hexDigits[(lead >>  8) & 15]);
0427                     PutUnsafe(*os_, hexDigits[(lead >>  4) & 15]);
0428                     PutUnsafe(*os_, hexDigits[(lead      ) & 15]);
0429                     PutUnsafe(*os_, '\\');
0430                     PutUnsafe(*os_, 'u');
0431                     PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
0432                     PutUnsafe(*os_, hexDigits[(trail >>  8) & 15]);
0433                     PutUnsafe(*os_, hexDigits[(trail >>  4) & 15]);
0434                     PutUnsafe(*os_, hexDigits[(trail      ) & 15]);                    
0435                 }
0436             }
0437             else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)]))  {
0438                 is.Take();
0439                 PutUnsafe(*os_, '\\');
0440                 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
0441                 if (escape[static_cast<unsigned char>(c)] == 'u') {
0442                     PutUnsafe(*os_, '0');
0443                     PutUnsafe(*os_, '0');
0444                     PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
0445                     PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
0446                 }
0447             }
0448             else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? 
0449                 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
0450                 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
0451                 return false;
0452         }
0453         PutUnsafe(*os_, '\"');
0454         return true;
0455     }
0456 
0457     bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
0458         return RAPIDJSON_LIKELY(is.Tell() < length);
0459     }
0460 
0461     bool WriteStartObject() { os_->Put('{'); return true; }
0462     bool WriteEndObject()   { os_->Put('}'); return true; }
0463     bool WriteStartArray()  { os_->Put('['); return true; }
0464     bool WriteEndArray()    { os_->Put(']'); return true; }
0465 
0466     bool WriteRawValue(const Ch* json, size_t length) {
0467         PutReserve(*os_, length);
0468         GenericStringStream<SourceEncoding> is(json);
0469         while (RAPIDJSON_LIKELY(is.Tell() < length)) {
0470             RAPIDJSON_ASSERT(is.Peek() != '\0');
0471             if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? 
0472                 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
0473                 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
0474                 return false;
0475         }
0476         return true;
0477     }
0478 
0479     void Prefix(Type type) {
0480         (void)type;
0481         if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
0482             Level* level = level_stack_.template Top<Level>();
0483             if (level->valueCount > 0) {
0484                 if (level->inArray) 
0485                     os_->Put(','); // add comma if it is not the first element in array
0486                 else  // in object
0487                     os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
0488             }
0489             if (!level->inArray && level->valueCount % 2 == 0)
0490                 RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name
0491             level->valueCount++;
0492         }
0493         else {
0494             RAPIDJSON_ASSERT(!hasRoot_);    // Should only has one and only one root.
0495             hasRoot_ = true;
0496         }
0497     }
0498 
0499     // Flush the value if it is the top level one.
0500     bool EndValue(bool ret) {
0501         if (RAPIDJSON_UNLIKELY(level_stack_.Empty()))   // end of json text
0502             Flush();
0503         return ret;
0504     }
0505 
0506     OutputStream* os_;
0507     internal::Stack<StackAllocator> level_stack_;
0508     int maxDecimalPlaces_;
0509     bool hasRoot_;
0510 
0511 private:
0512     // Prohibit copy constructor & assignment operator.
0513     Writer(const Writer&);
0514     Writer& operator=(const Writer&);
0515 };
0516 
0517 // Full specialization for StringStream to prevent memory copying
0518 
0519 template<>
0520 inline bool Writer<StringBuffer>::WriteInt(int i) {
0521     char *buffer = os_->Push(11);
0522     const char* end = internal::i32toa(i, buffer);
0523     os_->Pop(static_cast<size_t>(11 - (end - buffer)));
0524     return true;
0525 }
0526 
0527 template<>
0528 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
0529     char *buffer = os_->Push(10);
0530     const char* end = internal::u32toa(u, buffer);
0531     os_->Pop(static_cast<size_t>(10 - (end - buffer)));
0532     return true;
0533 }
0534 
0535 template<>
0536 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
0537     char *buffer = os_->Push(21);
0538     const char* end = internal::i64toa(i64, buffer);
0539     os_->Pop(static_cast<size_t>(21 - (end - buffer)));
0540     return true;
0541 }
0542 
0543 template<>
0544 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
0545     char *buffer = os_->Push(20);
0546     const char* end = internal::u64toa(u, buffer);
0547     os_->Pop(static_cast<size_t>(20 - (end - buffer)));
0548     return true;
0549 }
0550 
0551 template<>
0552 inline bool Writer<StringBuffer>::WriteDouble(double d) {
0553     if (internal::Double(d).IsNanOrInf()) {
0554         // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
0555         if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
0556             return false;
0557         if (kWriteDefaultFlags & kWriteNanAndInfNullFlag) {
0558             PutReserve(*os_, 4);
0559             PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l');
0560             return true;
0561         }
0562         if (internal::Double(d).IsNan()) {
0563             PutReserve(*os_, 3);
0564             PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
0565             return true;
0566         }
0567         if (internal::Double(d).Sign()) {
0568             PutReserve(*os_, 9);
0569             PutUnsafe(*os_, '-');
0570         }
0571         else
0572             PutReserve(*os_, 8);
0573         PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
0574         PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
0575         return true;
0576     }
0577     
0578     char *buffer = os_->Push(25);
0579     char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
0580     os_->Pop(static_cast<size_t>(25 - (end - buffer)));
0581     return true;
0582 }
0583 
0584 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
0585 template<>
0586 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
0587     if (length < 16)
0588         return RAPIDJSON_LIKELY(is.Tell() < length);
0589 
0590     if (!RAPIDJSON_LIKELY(is.Tell() < length))
0591         return false;
0592 
0593     const char* p = is.src_;
0594     const char* end = is.head_ + length;
0595     const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
0596     const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
0597     if (nextAligned > end)
0598         return true;
0599 
0600     while (p != nextAligned)
0601         if (*p < 0x20 || *p == '\"' || *p == '\\') {
0602             is.src_ = p;
0603             return RAPIDJSON_LIKELY(is.Tell() < length);
0604         }
0605         else
0606             os_->PutUnsafe(*p++);
0607 
0608     // The rest of string using SIMD
0609     static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
0610     static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
0611     static const char space[16]  = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
0612     const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
0613     const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
0614     const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
0615 
0616     for (; p != endAligned; p += 16) {
0617         const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
0618         const __m128i t1 = _mm_cmpeq_epi8(s, dq);
0619         const __m128i t2 = _mm_cmpeq_epi8(s, bs);
0620         const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
0621         const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
0622         unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
0623         if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped
0624             SizeType len;
0625 #ifdef _MSC_VER         // Find the index of first escaped
0626             unsigned long offset;
0627             _BitScanForward(&offset, r);
0628             len = offset;
0629 #else
0630             len = static_cast<SizeType>(__builtin_ffs(r) - 1);
0631 #endif
0632             char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
0633             for (size_t i = 0; i < len; i++)
0634                 q[i] = p[i];
0635 
0636             p += len;
0637             break;
0638         }
0639         _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
0640     }
0641 
0642     is.src_ = p;
0643     return RAPIDJSON_LIKELY(is.Tell() < length);
0644 }
0645 #elif defined(RAPIDJSON_NEON)
0646 template<>
0647 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
0648     if (length < 16)
0649         return RAPIDJSON_LIKELY(is.Tell() < length);
0650 
0651     if (!RAPIDJSON_LIKELY(is.Tell() < length))
0652         return false;
0653 
0654     const char* p = is.src_;
0655     const char* end = is.head_ + length;
0656     const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
0657     const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
0658     if (nextAligned > end)
0659         return true;
0660 
0661     while (p != nextAligned)
0662         if (*p < 0x20 || *p == '\"' || *p == '\\') {
0663             is.src_ = p;
0664             return RAPIDJSON_LIKELY(is.Tell() < length);
0665         }
0666         else
0667             os_->PutUnsafe(*p++);
0668 
0669     // The rest of string using SIMD
0670     const uint8x16_t s0 = vmovq_n_u8('"');
0671     const uint8x16_t s1 = vmovq_n_u8('\\');
0672     const uint8x16_t s2 = vmovq_n_u8('\b');
0673     const uint8x16_t s3 = vmovq_n_u8(32);
0674 
0675     for (; p != endAligned; p += 16) {
0676         const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
0677         uint8x16_t x = vceqq_u8(s, s0);
0678         x = vorrq_u8(x, vceqq_u8(s, s1));
0679         x = vorrq_u8(x, vceqq_u8(s, s2));
0680         x = vorrq_u8(x, vcltq_u8(s, s3));
0681 
0682         x = vrev64q_u8(x);                     // Rev in 64
0683         uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);   // extract
0684         uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);  // extract
0685 
0686         SizeType len = 0;
0687         bool escaped = false;
0688         if (low == 0) {
0689             if (high != 0) {
0690                 uint32_t lz = internal::clzll(high);
0691                 len = 8 + (lz >> 3);
0692                 escaped = true;
0693             }
0694         } else {
0695             uint32_t lz = internal::clzll(low);
0696             len = lz >> 3;
0697             escaped = true;
0698         }
0699         if (RAPIDJSON_UNLIKELY(escaped)) {   // some of characters is escaped
0700             char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
0701             for (size_t i = 0; i < len; i++)
0702                 q[i] = p[i];
0703 
0704             p += len;
0705             break;
0706         }
0707         vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
0708     }
0709 
0710     is.src_ = p;
0711     return RAPIDJSON_LIKELY(is.Tell() < length);
0712 }
0713 #endif // RAPIDJSON_NEON
0714 
0715 RAPIDJSON_NAMESPACE_END
0716 
0717 #if defined(_MSC_VER) || defined(__clang__)
0718 RAPIDJSON_DIAG_POP
0719 #endif
0720 
0721 #endif // RAPIDJSON_RAPIDJSON_H_