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