git repos / blockattack-game

blame: source/code/Libs/include/cereal/external/rapidjson/writer.h

normal view · raw

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