Maxim Integrated / Mbed OS MAXREFDES155#

Dependencies:   MaximInterface

Committer:
IanBenzMaxim
Date:
Tue Dec 03 12:56:25 2019 -0600
Revision:
18:c2631e985780
Parent:
16:a004191a79ab
Updated MaximInterface to version 2.1.

Who changed what in which revision?

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