Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MaximInterface
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_
Generated on Tue Jul 12 2022 12:06:50 by
 1.7.2
 1.7.2