Maxim Integrated / Mbed OS MAXREFDES155#

Dependencies:   MaximInterface

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers writer.h Source File

writer.h

00001 // Tencent is pleased to support the open source community by making RapidJSON available.
00002 // 
00003 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
00004 //
00005 // Licensed under the MIT License (the "License"); you may not use this file except
00006 // in compliance with the License. You may obtain a copy of the License at
00007 //
00008 // http://opensource.org/licenses/MIT
00009 //
00010 // Unless required by applicable law or agreed to in writing, software distributed 
00011 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
00012 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 
00013 // specific language governing permissions and limitations under the License.
00014 
00015 #ifndef RAPIDJSON_WRITER_H_
00016 #define RAPIDJSON_WRITER_H_
00017 
00018 #include "stream.h"
00019 #include "internal/stack.h"
00020 #include "internal/strfunc.h"
00021 #include "internal/dtoa.h"
00022 #include "internal/itoa.h"
00023 #include "stringbuffer.h"
00024 #include <new>      // placement new
00025 
00026 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
00027 #include <intrin.h>
00028 #pragma intrinsic(_BitScanForward)
00029 #endif
00030 #ifdef RAPIDJSON_SSE42
00031 #include <nmmintrin.h>
00032 #elif defined(RAPIDJSON_SSE2)
00033 #include <emmintrin.h>
00034 #endif
00035 
00036 #ifdef _MSC_VER
00037 RAPIDJSON_DIAG_PUSH
00038 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
00039 #endif
00040 
00041 #ifdef __clang__
00042 RAPIDJSON_DIAG_PUSH
00043 RAPIDJSON_DIAG_OFF(padded)
00044 RAPIDJSON_DIAG_OFF(unreachable-code)
00045 RAPIDJSON_DIAG_OFF(c++98-compat)
00046 #endif
00047 
00048 RAPIDJSON_NAMESPACE_BEGIN
00049 
00050 ///////////////////////////////////////////////////////////////////////////////
00051 // WriteFlag
00052 
00053 /*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS 
00054     \ingroup RAPIDJSON_CONFIG
00055     \brief User-defined kWriteDefaultFlags definition.
00056 
00057     User can define this as any \c WriteFlag combinations.
00058 */
00059 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
00060 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
00061 #endif
00062 
00063 //! Combination of writeFlags
00064 enum WriteFlag {
00065     kWriteNoFlags = 0,              //!< No flags are set.
00066     kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
00067     kWriteNanAndInfFlag = 2,        //!< Allow writing of Infinity, -Infinity and NaN.
00068     kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS  //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
00069 };
00070 
00071 //! JSON writer
00072 /*! Writer implements the concept Handler.
00073     It generates JSON text by events to an output os.
00074 
00075     User may programmatically calls the functions of a writer to generate JSON text.
00076 
00077     On the other side, a writer can also be passed to objects that generates events, 
00078 
00079     for example Reader::Parse() and Document::Accept().
00080 
00081     \tparam OutputStream Type of output stream.
00082     \tparam SourceEncoding Encoding of source string.
00083     \tparam TargetEncoding Encoding of output stream.
00084     \tparam StackAllocator Type of allocator for allocating memory of stack.
00085     \note implements Handler concept
00086 */
00087 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
00088 class Writer {
00089 public:
00090     typedef typename SourceEncoding::Ch Ch;
00091 
00092     static const int kDefaultMaxDecimalPlaces = 324;
00093 
00094     //! Constructor
00095     /*! \param os Output stream.
00096         \param stackAllocator User supplied allocator. If it is null, it will create a private one.
00097         \param levelDepth Initial capacity of stack.
00098     */
00099     explicit
00100     Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : 
00101         os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
00102 
00103     explicit
00104     Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
00105         os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
00106 
00107 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
00108     Writer(Writer&& rhs) :
00109         os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
00110         rhs.os_ = 0;
00111     }
00112 #endif
00113 
00114     //! Reset the writer with a new stream.
00115     /*!
00116         This function reset the writer with a new stream and default settings,
00117         in order to make a Writer object reusable for output multiple JSONs.
00118 
00119         \param os New output stream.
00120         \code
00121         Writer<OutputStream> writer(os1);
00122         writer.StartObject();
00123         // ...
00124         writer.EndObject();
00125 
00126         writer.Reset(os2);
00127         writer.StartObject();
00128         // ...
00129         writer.EndObject();
00130         \endcode
00131     */
00132     void Reset(OutputStream& os) {
00133         os_ = &os;
00134         hasRoot_ = false;
00135         level_stack_.Clear();
00136     }
00137 
00138     //! Checks whether the output is a complete JSON.
00139     /*!
00140         A complete JSON has a complete root object or array.
00141     */
00142     bool IsComplete() const {
00143         return hasRoot_ && level_stack_.Empty();
00144     }
00145 
00146     int GetMaxDecimalPlaces() const {
00147         return maxDecimalPlaces_;
00148     }
00149 
00150     //! Sets the maximum number of decimal places for double output.
00151     /*!
00152         This setting truncates the output with specified number of decimal places.
00153 
00154         For example, 
00155 
00156         \code
00157         writer.SetMaxDecimalPlaces(3);
00158         writer.StartArray();
00159         writer.Double(0.12345);                 // "0.123"
00160         writer.Double(0.0001);                  // "0.0"
00161         writer.Double(1.234567890123456e30);    // "1.234567890123456e30" (do not truncate significand for positive exponent)
00162         writer.Double(1.23e-4);                 // "0.0"                  (do truncate significand for negative exponent)
00163         writer.EndArray();
00164         \endcode
00165 
00166         The default setting does not truncate any decimal places. You can restore to this setting by calling
00167         \code
00168         writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
00169         \endcode
00170     */
00171     void SetMaxDecimalPlaces(int maxDecimalPlaces) {
00172         maxDecimalPlaces_ = maxDecimalPlaces;
00173     }
00174 
00175     /*!@name Implementation of Handler
00176         \see Handler
00177     */
00178     //@{
00179 
00180     bool Null()                 { Prefix(kNullType);   return EndValue(WriteNull()); }
00181     bool Bool(bool b)           { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
00182     bool Int(int i)             { Prefix(kNumberType); return EndValue(WriteInt(i)); }
00183     bool Uint(unsigned u)       { Prefix(kNumberType); return EndValue(WriteUint(u)); }
00184     bool Int64(int64_t i64)     { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
00185     bool Uint64(uint64_t u64)   { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
00186 
00187     //! Writes the given \c double value to the stream
00188     /*!
00189         \param d The value to be written.
00190         \return Whether it is succeed.
00191     */
00192     bool Double(double d)       { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
00193 
00194     bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
00195         RAPIDJSON_ASSERT(str != 0);
00196         (void)copy;
00197         Prefix(kNumberType);
00198         return EndValue(WriteString(str, length));
00199     }
00200 
00201     bool String(const Ch* str, SizeType length, bool copy = false) {
00202         RAPIDJSON_ASSERT(str != 0);
00203         (void)copy;
00204         Prefix(kStringType);
00205         return EndValue(WriteString(str, length));
00206     }
00207 
00208 #if RAPIDJSON_HAS_STDSTRING
00209     bool String(const std::basic_string<Ch>& str) {
00210         return String(str.data(), SizeType(str.size()));
00211     }
00212 #endif
00213 
00214     bool StartObject() {
00215         Prefix(kObjectType);
00216         new (level_stack_.template Push<Level>()) Level(false);
00217         return WriteStartObject();
00218     }
00219 
00220     bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
00221 
00222     bool EndObject(SizeType memberCount = 0) {
00223         (void)memberCount;
00224         RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
00225         RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
00226         level_stack_.template Pop<Level>(1);
00227         return EndValue(WriteEndObject());
00228     }
00229 
00230     bool StartArray() {
00231         Prefix(kArrayType);
00232         new (level_stack_.template Push<Level>()) Level(true);
00233         return WriteStartArray();
00234     }
00235 
00236     bool EndArray(SizeType elementCount = 0) {
00237         (void)elementCount;
00238         RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
00239         RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
00240         level_stack_.template Pop<Level>(1);
00241         return EndValue(WriteEndArray());
00242     }
00243     //@}
00244 
00245     /*! @name Convenience extensions */
00246     //@{
00247 
00248     //! Simpler but slower overload.
00249     bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
00250     bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
00251 
00252     //@}
00253 
00254     //! Write a raw JSON value.
00255     /*!
00256         For user to write a stringified JSON as a value.
00257 
00258         \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
00259         \param length Length of the json.
00260         \param type Type of the root of json.
00261     */
00262     bool RawValue(const Ch* json, size_t length, Type type) {
00263         RAPIDJSON_ASSERT(json != 0);
00264         Prefix(type);
00265         return EndValue(WriteRawValue(json, length));
00266     }
00267 
00268 protected:
00269     //! Information for each nested level
00270     struct Level {
00271         Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
00272         size_t valueCount;  //!< number of values in this level
00273         bool inArray;       //!< true if in array, otherwise in object
00274     };
00275 
00276     static const size_t kDefaultLevelDepth = 32;
00277 
00278     bool WriteNull()  {
00279         PutReserve(*os_, 4);
00280         PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
00281     }
00282 
00283     bool WriteBool(bool b)  {
00284         if (b) {
00285             PutReserve(*os_, 4);
00286             PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
00287         }
00288         else {
00289             PutReserve(*os_, 5);
00290             PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
00291         }
00292         return true;
00293     }
00294 
00295     bool WriteInt(int i) {
00296         char buffer[11];
00297         const char* end = internal::i32toa(i, buffer);
00298         PutReserve(*os_, static_cast<size_t>(end - buffer));
00299         for (const char* p = buffer; p != end; ++p)
00300             PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
00301         return true;
00302     }
00303 
00304     bool WriteUint(unsigned u) {
00305         char buffer[10];
00306         const char* end = internal::u32toa(u, buffer);
00307         PutReserve(*os_, static_cast<size_t>(end - buffer));
00308         for (const char* p = buffer; p != end; ++p)
00309             PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
00310         return true;
00311     }
00312 
00313     bool WriteInt64(int64_t i64) {
00314         char buffer[21];
00315         const char* end = internal::i64toa(i64, buffer);
00316         PutReserve(*os_, static_cast<size_t>(end - buffer));
00317         for (const char* p = buffer; p != end; ++p)
00318             PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
00319         return true;
00320     }
00321 
00322     bool WriteUint64(uint64_t u64) {
00323         char buffer[20];
00324         char* end = internal::u64toa(u64, buffer);
00325         PutReserve(*os_, static_cast<size_t>(end - buffer));
00326         for (char* p = buffer; p != end; ++p)
00327             PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
00328         return true;
00329     }
00330 
00331     bool WriteDouble(double d) {
00332         if (internal::Double(d).IsNanOrInf()) {
00333             if (!(writeFlags & kWriteNanAndInfFlag))
00334                 return false;
00335             if (internal::Double(d).IsNan()) {
00336                 PutReserve(*os_, 3);
00337                 PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
00338                 return true;
00339             }
00340             if (internal::Double(d).Sign()) {
00341                 PutReserve(*os_, 9);
00342                 PutUnsafe(*os_, '-');
00343             }
00344             else
00345                 PutReserve(*os_, 8);
00346             PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
00347             PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
00348             return true;
00349         }
00350 
00351         char buffer[25];
00352         char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
00353         PutReserve(*os_, static_cast<size_t>(end - buffer));
00354         for (char* p = buffer; p != end; ++p)
00355             PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
00356         return true;
00357     }
00358 
00359     bool WriteString(const Ch* str, SizeType length)  {
00360         static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
00361         static const char escape[256] = {
00362 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00363             //0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
00364             'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
00365             'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
00366               0,   0, '"',   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20
00367             Z16, Z16,                                                                       // 30~4F
00368               0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,'\\',   0,   0,   0, // 50
00369             Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16                                // 60~FF
00370 #undef Z16
00371         };
00372 
00373         if (TargetEncoding::supportUnicode)
00374             PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
00375         else
00376             PutReserve(*os_, 2 + length * 12);  // "\uxxxx\uyyyy..."
00377 
00378         PutUnsafe(*os_, '\"');
00379         GenericStringStream<SourceEncoding> is(str);
00380         while (ScanWriteUnescapedString(is, length)) {
00381             const Ch c = is.Peek();
00382             if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
00383                 // Unicode escaping
00384                 unsigned codepoint;
00385                 if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
00386                     return false;
00387                 PutUnsafe(*os_, '\\');
00388                 PutUnsafe(*os_, 'u');
00389                 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
00390                     PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
00391                     PutUnsafe(*os_, hexDigits[(codepoint >>  8) & 15]);
00392                     PutUnsafe(*os_, hexDigits[(codepoint >>  4) & 15]);
00393                     PutUnsafe(*os_, hexDigits[(codepoint      ) & 15]);
00394                 }
00395                 else {
00396                     RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
00397                     // Surrogate pair
00398                     unsigned s = codepoint - 0x010000;
00399                     unsigned lead = (s >> 10) + 0xD800;
00400                     unsigned trail = (s & 0x3FF) + 0xDC00;
00401                     PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
00402                     PutUnsafe(*os_, hexDigits[(lead >>  8) & 15]);
00403                     PutUnsafe(*os_, hexDigits[(lead >>  4) & 15]);
00404                     PutUnsafe(*os_, hexDigits[(lead      ) & 15]);
00405                     PutUnsafe(*os_, '\\');
00406                     PutUnsafe(*os_, 'u');
00407                     PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
00408                     PutUnsafe(*os_, hexDigits[(trail >>  8) & 15]);
00409                     PutUnsafe(*os_, hexDigits[(trail >>  4) & 15]);
00410                     PutUnsafe(*os_, hexDigits[(trail      ) & 15]);                    
00411                 }
00412             }
00413             else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)]))  {
00414                 is.Take();
00415                 PutUnsafe(*os_, '\\');
00416                 PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
00417                 if (escape[static_cast<unsigned char>(c)] == 'u') {
00418                     PutUnsafe(*os_, '0');
00419                     PutUnsafe(*os_, '0');
00420                     PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
00421                     PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
00422                 }
00423             }
00424             else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? 
00425                 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
00426                 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
00427                 return false;
00428         }
00429         PutUnsafe(*os_, '\"');
00430         return true;
00431     }
00432 
00433     bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
00434         return RAPIDJSON_LIKELY(is.Tell() < length);
00435     }
00436 
00437     bool WriteStartObject() { os_->Put('{'); return true; }
00438     bool WriteEndObject()   { os_->Put('}'); return true; }
00439     bool WriteStartArray()  { os_->Put('['); return true; }
00440     bool WriteEndArray()    { os_->Put(']'); return true; }
00441 
00442     bool WriteRawValue(const Ch* json, size_t length) {
00443         PutReserve(*os_, length);
00444         for (size_t i = 0; i < length; i++) {
00445             RAPIDJSON_ASSERT(json[i] != '\0');
00446             PutUnsafe(*os_, json[i]);
00447         }
00448         return true;
00449     }
00450 
00451     void Prefix(Type type) {
00452         (void)type;
00453         if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
00454             Level* level = level_stack_.template Top<Level>();
00455             if (level->valueCount > 0) {
00456                 if (level->inArray) 
00457                     os_->Put(','); // add comma if it is not the first element in array
00458                 else  // in object
00459                     os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
00460             }
00461             if (!level->inArray && level->valueCount % 2 == 0)
00462                 RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name
00463             level->valueCount++;
00464         }
00465         else {
00466             RAPIDJSON_ASSERT(!hasRoot_);    // Should only has one and only one root.
00467             hasRoot_ = true;
00468         }
00469     }
00470 
00471     // Flush the value if it is the top level one.
00472     bool EndValue(bool ret) {
00473         if (RAPIDJSON_UNLIKELY(level_stack_.Empty()))   // end of json text
00474             os_->Flush();
00475         return ret;
00476     }
00477 
00478     OutputStream* os_;
00479     internal::Stack<StackAllocator> level_stack_;
00480     int maxDecimalPlaces_;
00481     bool hasRoot_;
00482 
00483 private:
00484     // Prohibit copy constructor & assignment operator.
00485     Writer(const Writer&);
00486     Writer& operator=(const Writer&);
00487 };
00488 
00489 // Full specialization for StringStream to prevent memory copying
00490 
00491 template<>
00492 inline bool Writer<StringBuffer>::WriteInt(int i) {
00493     char *buffer = os_->Push(11);
00494     const char* end = internal::i32toa(i, buffer);
00495     os_->Pop(static_cast<size_t>(11 - (end - buffer)));
00496     return true;
00497 }
00498 
00499 template<>
00500 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
00501     char *buffer = os_->Push(10);
00502     const char* end = internal::u32toa(u, buffer);
00503     os_->Pop(static_cast<size_t>(10 - (end - buffer)));
00504     return true;
00505 }
00506 
00507 template<>
00508 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
00509     char *buffer = os_->Push(21);
00510     const char* end = internal::i64toa(i64, buffer);
00511     os_->Pop(static_cast<size_t>(21 - (end - buffer)));
00512     return true;
00513 }
00514 
00515 template<>
00516 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
00517     char *buffer = os_->Push(20);
00518     const char* end = internal::u64toa(u, buffer);
00519     os_->Pop(static_cast<size_t>(20 - (end - buffer)));
00520     return true;
00521 }
00522 
00523 template<>
00524 inline bool Writer<StringBuffer>::WriteDouble(double d) {
00525     if (internal::Double(d).IsNanOrInf()) {
00526         // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
00527         if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
00528             return false;
00529         if (internal::Double(d).IsNan()) {
00530             PutReserve(*os_, 3);
00531             PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
00532             return true;
00533         }
00534         if (internal::Double(d).Sign()) {
00535             PutReserve(*os_, 9);
00536             PutUnsafe(*os_, '-');
00537         }
00538         else
00539             PutReserve(*os_, 8);
00540         PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
00541         PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
00542         return true;
00543     }
00544     
00545     char *buffer = os_->Push(25);
00546     char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
00547     os_->Pop(static_cast<size_t>(25 - (end - buffer)));
00548     return true;
00549 }
00550 
00551 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
00552 template<>
00553 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
00554     if (length < 16)
00555         return RAPIDJSON_LIKELY(is.Tell() < length);
00556 
00557     if (!RAPIDJSON_LIKELY(is.Tell() < length))
00558         return false;
00559 
00560     const char* p = is.src_;
00561     const char* end = is.head_ + length;
00562     const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
00563     const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
00564     if (nextAligned > end)
00565         return true;
00566 
00567     while (p != nextAligned)
00568         if (*p < 0x20 || *p == '\"' || *p == '\\') {
00569             is.src_ = p;
00570             return RAPIDJSON_LIKELY(is.Tell() < length);
00571         }
00572         else
00573             os_->PutUnsafe(*p++);
00574 
00575     // The rest of string using SIMD
00576     static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
00577     static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
00578     static const char space[16]  = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
00579     const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
00580     const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
00581     const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
00582 
00583     for (; p != endAligned; p += 16) {
00584         const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
00585         const __m128i t1 = _mm_cmpeq_epi8(s, dq);
00586         const __m128i t2 = _mm_cmpeq_epi8(s, bs);
00587         const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
00588         const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
00589         unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
00590         if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped
00591             SizeType len;
00592 #ifdef _MSC_VER         // Find the index of first escaped
00593             unsigned long offset;
00594             _BitScanForward(&offset, r);
00595             len = offset;
00596 #else
00597             len = static_cast<SizeType>(__builtin_ffs(r) - 1);
00598 #endif
00599             char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
00600             for (size_t i = 0; i < len; i++)
00601                 q[i] = p[i];
00602 
00603             p += len;
00604             break;
00605         }
00606         _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
00607     }
00608 
00609     is.src_ = p;
00610     return RAPIDJSON_LIKELY(is.Tell() < length);
00611 }
00612 #endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
00613 
00614 RAPIDJSON_NAMESPACE_END
00615 
00616 #ifdef _MSC_VER
00617 RAPIDJSON_DIAG_POP
00618 #endif
00619 
00620 #ifdef __clang__
00621 RAPIDJSON_DIAG_POP
00622 #endif
00623 
00624 #endif // RAPIDJSON_RAPIDJSON_H_