git repos / blockattack-game

blame: source/code/Libs/include/cereal/external/rapidjson/pointer.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_POINTER_H_
6c5f2c01 sago007 2017-03-15 17:56 16
#define CEREAL_RAPIDJSON_POINTER_H_
6c5f2c01 sago007 2017-03-15 17:56 17
6c5f2c01 sago007 2017-03-15 17:56 18
#include "document.h"
6c5f2c01 sago007 2017-03-15 17:56 19
#include "internal/itoa.h"
6c5f2c01 sago007 2017-03-15 17:56 20
6c5f2c01 sago007 2017-03-15 17:56 21
#ifdef __clang__
6c5f2c01 sago007 2017-03-15 17:56 22
CEREAL_RAPIDJSON_DIAG_PUSH
6c5f2c01 sago007 2017-03-15 17:56 23
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
8f94a7f5 sago007 2020-05-10 10:26 24
#elif defined(_MSC_VER)
6c5f2c01 sago007 2017-03-15 17:56 25
CEREAL_RAPIDJSON_DIAG_PUSH
6c5f2c01 sago007 2017-03-15 17:56 26
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
6c5f2c01 sago007 2017-03-15 17:56 27
#endif
6c5f2c01 sago007 2017-03-15 17:56 28
6c5f2c01 sago007 2017-03-15 17:56 29
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
6c5f2c01 sago007 2017-03-15 17:56 30
6c5f2c01 sago007 2017-03-15 17:56 31
static const SizeType kPointerInvalidIndex = ~SizeType(0);  //!< Represents an invalid index in GenericPointer::Token
6c5f2c01 sago007 2017-03-15 17:56 32
6c5f2c01 sago007 2017-03-15 17:56 33
//! Error code of parsing.
6c5f2c01 sago007 2017-03-15 17:56 34
/*! \ingroup CEREAL_RAPIDJSON_ERRORS
6c5f2c01 sago007 2017-03-15 17:56 35
    \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
6c5f2c01 sago007 2017-03-15 17:56 36
*/
6c5f2c01 sago007 2017-03-15 17:56 37
enum PointerParseErrorCode {
6c5f2c01 sago007 2017-03-15 17:56 38
    kPointerParseErrorNone = 0,                     //!< The parse is successful
6c5f2c01 sago007 2017-03-15 17:56 39
6c5f2c01 sago007 2017-03-15 17:56 40
    kPointerParseErrorTokenMustBeginWithSolidus,    //!< A token must begin with a '/'
6c5f2c01 sago007 2017-03-15 17:56 41
    kPointerParseErrorInvalidEscape,                //!< Invalid escape
6c5f2c01 sago007 2017-03-15 17:56 42
    kPointerParseErrorInvalidPercentEncoding,       //!< Invalid percent encoding in URI fragment
6c5f2c01 sago007 2017-03-15 17:56 43
    kPointerParseErrorCharacterMustPercentEncode    //!< A character must percent encoded in URI fragment
6c5f2c01 sago007 2017-03-15 17:56 44
};
6c5f2c01 sago007 2017-03-15 17:56 45
6c5f2c01 sago007 2017-03-15 17:56 46
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 47
// GenericPointer
6c5f2c01 sago007 2017-03-15 17:56 48
6c5f2c01 sago007 2017-03-15 17:56 49
//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
6c5f2c01 sago007 2017-03-15 17:56 50
/*!
6c5f2c01 sago007 2017-03-15 17:56 51
    This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" 
6c5f2c01 sago007 2017-03-15 17:56 52
    (https://tools.ietf.org/html/rfc6901).
6c5f2c01 sago007 2017-03-15 17:56 53
6c5f2c01 sago007 2017-03-15 17:56 54
    A JSON pointer is for identifying a specific value in a JSON document
6c5f2c01 sago007 2017-03-15 17:56 55
    (GenericDocument). It can simplify coding of DOM tree manipulation, because it
6c5f2c01 sago007 2017-03-15 17:56 56
    can access multiple-level depth of DOM tree with single API call.
6c5f2c01 sago007 2017-03-15 17:56 57
6c5f2c01 sago007 2017-03-15 17:56 58
    After it parses a string representation (e.g. "/foo/0" or URI fragment 
6c5f2c01 sago007 2017-03-15 17:56 59
    representation (e.g. "#/foo/0") into its internal representation (tokens),
6c5f2c01 sago007 2017-03-15 17:56 60
    it can be used to resolve a specific value in multiple documents, or sub-tree 
6c5f2c01 sago007 2017-03-15 17:56 61
    of documents.
6c5f2c01 sago007 2017-03-15 17:56 62
6c5f2c01 sago007 2017-03-15 17:56 63
    Contrary to GenericValue, Pointer can be copy constructed and copy assigned.
6c5f2c01 sago007 2017-03-15 17:56 64
    Apart from assignment, a Pointer cannot be modified after construction.
6c5f2c01 sago007 2017-03-15 17:56 65
6c5f2c01 sago007 2017-03-15 17:56 66
    Although Pointer is very convenient, please aware that constructing Pointer
6c5f2c01 sago007 2017-03-15 17:56 67
    involves parsing and dynamic memory allocation. A special constructor with user-
6c5f2c01 sago007 2017-03-15 17:56 68
    supplied tokens eliminates these.
6c5f2c01 sago007 2017-03-15 17:56 69
6c5f2c01 sago007 2017-03-15 17:56 70
    GenericPointer depends on GenericDocument and GenericValue.
6c5f2c01 sago007 2017-03-15 17:56 71
    
6c5f2c01 sago007 2017-03-15 17:56 72
    \tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> >
6c5f2c01 sago007 2017-03-15 17:56 73
    \tparam Allocator The allocator type for allocating memory for internal representation.
6c5f2c01 sago007 2017-03-15 17:56 74
    
6c5f2c01 sago007 2017-03-15 17:56 75
    \note GenericPointer uses same encoding of ValueType.
6c5f2c01 sago007 2017-03-15 17:56 76
    However, Allocator of GenericPointer is independent of Allocator of Value.
6c5f2c01 sago007 2017-03-15 17:56 77
*/
6c5f2c01 sago007 2017-03-15 17:56 78
template <typename ValueType, typename Allocator = CrtAllocator>
6c5f2c01 sago007 2017-03-15 17:56 79
class GenericPointer {
6c5f2c01 sago007 2017-03-15 17:56 80
public:
6c5f2c01 sago007 2017-03-15 17:56 81
    typedef typename ValueType::EncodingType EncodingType;  //!< Encoding type from Value
6c5f2c01 sago007 2017-03-15 17:56 82
    typedef typename ValueType::Ch Ch;                      //!< Character type from Value
6c5f2c01 sago007 2017-03-15 17:56 83
6c5f2c01 sago007 2017-03-15 17:56 84
    //! A token is the basic units of internal representation.
6c5f2c01 sago007 2017-03-15 17:56 85
    /*!
6c5f2c01 sago007 2017-03-15 17:56 86
        A JSON pointer string representation "/foo/123" is parsed to two tokens: 
6c5f2c01 sago007 2017-03-15 17:56 87
        "foo" and 123. 123 will be represented in both numeric form and string form.
6c5f2c01 sago007 2017-03-15 17:56 88
        They are resolved according to the actual value type (object or array).
6c5f2c01 sago007 2017-03-15 17:56 89
6c5f2c01 sago007 2017-03-15 17:56 90
        For token that are not numbers, or the numeric value is out of bound
6c5f2c01 sago007 2017-03-15 17:56 91
        (greater than limits of SizeType), they are only treated as string form
6c5f2c01 sago007 2017-03-15 17:56 92
        (i.e. the token's index will be equal to kPointerInvalidIndex).
6c5f2c01 sago007 2017-03-15 17:56 93
6c5f2c01 sago007 2017-03-15 17:56 94
        This struct is public so that user can create a Pointer without parsing and 
6c5f2c01 sago007 2017-03-15 17:56 95
        allocation, using a special constructor.
6c5f2c01 sago007 2017-03-15 17:56 96
    */
6c5f2c01 sago007 2017-03-15 17:56 97
    struct Token {
6c5f2c01 sago007 2017-03-15 17:56 98
        const Ch* name;             //!< Name of the token. It has null character at the end but it can contain null character.
6c5f2c01 sago007 2017-03-15 17:56 99
        SizeType length;            //!< Length of the name.
6c5f2c01 sago007 2017-03-15 17:56 100
        SizeType index;             //!< A valid array index, if it is not equal to kPointerInvalidIndex.
6c5f2c01 sago007 2017-03-15 17:56 101
    };
6c5f2c01 sago007 2017-03-15 17:56 102
6c5f2c01 sago007 2017-03-15 17:56 103
    //!@name Constructors and destructor.
6c5f2c01 sago007 2017-03-15 17:56 104
    //@{
6c5f2c01 sago007 2017-03-15 17:56 105
6c5f2c01 sago007 2017-03-15 17:56 106
    //! Default constructor.
6c5f2c01 sago007 2017-03-15 17:56 107
    GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
6c5f2c01 sago007 2017-03-15 17:56 108
6c5f2c01 sago007 2017-03-15 17:56 109
    //! Constructor that parses a string or URI fragment representation.
6c5f2c01 sago007 2017-03-15 17:56 110
    /*!
6c5f2c01 sago007 2017-03-15 17:56 111
        \param source A null-terminated, string or URI fragment representation of JSON pointer.
6c5f2c01 sago007 2017-03-15 17:56 112
        \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
6c5f2c01 sago007 2017-03-15 17:56 113
    */
6c5f2c01 sago007 2017-03-15 17:56 114
    explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
6c5f2c01 sago007 2017-03-15 17:56 115
        Parse(source, internal::StrLen(source));
6c5f2c01 sago007 2017-03-15 17:56 116
    }
6c5f2c01 sago007 2017-03-15 17:56 117
6c5f2c01 sago007 2017-03-15 17:56 118
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 119
    //! Constructor that parses a string or URI fragment representation.
6c5f2c01 sago007 2017-03-15 17:56 120
    /*!
6c5f2c01 sago007 2017-03-15 17:56 121
        \param source A string or URI fragment representation of JSON pointer.
6c5f2c01 sago007 2017-03-15 17:56 122
        \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
6c5f2c01 sago007 2017-03-15 17:56 123
        \note Requires the definition of the preprocessor symbol \ref CEREAL_RAPIDJSON_HAS_STDSTRING.
6c5f2c01 sago007 2017-03-15 17:56 124
    */
6c5f2c01 sago007 2017-03-15 17:56 125
    explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
6c5f2c01 sago007 2017-03-15 17:56 126
        Parse(source.c_str(), source.size());
6c5f2c01 sago007 2017-03-15 17:56 127
    }
6c5f2c01 sago007 2017-03-15 17:56 128
#endif
6c5f2c01 sago007 2017-03-15 17:56 129
6c5f2c01 sago007 2017-03-15 17:56 130
    //! Constructor that parses a string or URI fragment representation, with length of the source string.
6c5f2c01 sago007 2017-03-15 17:56 131
    /*!
6c5f2c01 sago007 2017-03-15 17:56 132
        \param source A string or URI fragment representation of JSON pointer.
6c5f2c01 sago007 2017-03-15 17:56 133
        \param length Length of source.
6c5f2c01 sago007 2017-03-15 17:56 134
        \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
6c5f2c01 sago007 2017-03-15 17:56 135
        \note Slightly faster than the overload without length.
6c5f2c01 sago007 2017-03-15 17:56 136
    */
6c5f2c01 sago007 2017-03-15 17:56 137
    GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
6c5f2c01 sago007 2017-03-15 17:56 138
        Parse(source, length);
6c5f2c01 sago007 2017-03-15 17:56 139
    }
6c5f2c01 sago007 2017-03-15 17:56 140
6c5f2c01 sago007 2017-03-15 17:56 141
    //! Constructor with user-supplied tokens.
6c5f2c01 sago007 2017-03-15 17:56 142
    /*!
6c5f2c01 sago007 2017-03-15 17:56 143
        This constructor let user supplies const array of tokens.
6c5f2c01 sago007 2017-03-15 17:56 144
        This prevents the parsing process and eliminates allocation.
6c5f2c01 sago007 2017-03-15 17:56 145
        This is preferred for memory constrained environments.
6c5f2c01 sago007 2017-03-15 17:56 146
6c5f2c01 sago007 2017-03-15 17:56 147
        \param tokens An constant array of tokens representing the JSON pointer.
6c5f2c01 sago007 2017-03-15 17:56 148
        \param tokenCount Number of tokens.
6c5f2c01 sago007 2017-03-15 17:56 149
6c5f2c01 sago007 2017-03-15 17:56 150
        \b Example
6c5f2c01 sago007 2017-03-15 17:56 151
        \code
6c5f2c01 sago007 2017-03-15 17:56 152
        #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }
6c5f2c01 sago007 2017-03-15 17:56 153
        #define INDEX(i) { #i, sizeof(#i) - 1, i }
6c5f2c01 sago007 2017-03-15 17:56 154
6c5f2c01 sago007 2017-03-15 17:56 155
        static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) };
6c5f2c01 sago007 2017-03-15 17:56 156
        static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
6c5f2c01 sago007 2017-03-15 17:56 157
        // Equivalent to static const Pointer p("/foo/123");
6c5f2c01 sago007 2017-03-15 17:56 158
6c5f2c01 sago007 2017-03-15 17:56 159
        #undef NAME
6c5f2c01 sago007 2017-03-15 17:56 160
        #undef INDEX
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
    GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
6c5f2c01 sago007 2017-03-15 17:56 164
6c5f2c01 sago007 2017-03-15 17:56 165
    //! Copy constructor.
8f94a7f5 sago007 2020-05-10 10:26 166
    GenericPointer(const GenericPointer& rhs) : allocator_(rhs.allocator_), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
8f94a7f5 sago007 2020-05-10 10:26 167
        *this = rhs;
8f94a7f5 sago007 2020-05-10 10:26 168
    }
8f94a7f5 sago007 2020-05-10 10:26 169
8f94a7f5 sago007 2020-05-10 10:26 170
    //! Copy constructor.
8f94a7f5 sago007 2020-05-10 10:26 171
    GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
6c5f2c01 sago007 2017-03-15 17:56 172
        *this = rhs;
6c5f2c01 sago007 2017-03-15 17:56 173
    }
6c5f2c01 sago007 2017-03-15 17:56 174
6c5f2c01 sago007 2017-03-15 17:56 175
    //! Destructor.
6c5f2c01 sago007 2017-03-15 17:56 176
    ~GenericPointer() {
6c5f2c01 sago007 2017-03-15 17:56 177
        if (nameBuffer_)    // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
6c5f2c01 sago007 2017-03-15 17:56 178
            Allocator::Free(tokens_);
6c5f2c01 sago007 2017-03-15 17:56 179
        CEREAL_RAPIDJSON_DELETE(ownAllocator_);
6c5f2c01 sago007 2017-03-15 17:56 180
    }
6c5f2c01 sago007 2017-03-15 17:56 181
6c5f2c01 sago007 2017-03-15 17:56 182
    //! Assignment operator.
6c5f2c01 sago007 2017-03-15 17:56 183
    GenericPointer& operator=(const GenericPointer& rhs) {
6c5f2c01 sago007 2017-03-15 17:56 184
        if (this != &rhs) {
6c5f2c01 sago007 2017-03-15 17:56 185
            // Do not delete ownAllcator
6c5f2c01 sago007 2017-03-15 17:56 186
            if (nameBuffer_)
6c5f2c01 sago007 2017-03-15 17:56 187
                Allocator::Free(tokens_);
6c5f2c01 sago007 2017-03-15 17:56 188
6c5f2c01 sago007 2017-03-15 17:56 189
            tokenCount_ = rhs.tokenCount_;
6c5f2c01 sago007 2017-03-15 17:56 190
            parseErrorOffset_ = rhs.parseErrorOffset_;
6c5f2c01 sago007 2017-03-15 17:56 191
            parseErrorCode_ = rhs.parseErrorCode_;
6c5f2c01 sago007 2017-03-15 17:56 192
6c5f2c01 sago007 2017-03-15 17:56 193
            if (rhs.nameBuffer_)
6c5f2c01 sago007 2017-03-15 17:56 194
                CopyFromRaw(rhs); // Normally parsed tokens.
6c5f2c01 sago007 2017-03-15 17:56 195
            else {
6c5f2c01 sago007 2017-03-15 17:56 196
                tokens_ = rhs.tokens_; // User supplied const tokens.
6c5f2c01 sago007 2017-03-15 17:56 197
                nameBuffer_ = 0;
6c5f2c01 sago007 2017-03-15 17:56 198
            }
6c5f2c01 sago007 2017-03-15 17:56 199
        }
6c5f2c01 sago007 2017-03-15 17:56 200
        return *this;
6c5f2c01 sago007 2017-03-15 17:56 201
    }
6c5f2c01 sago007 2017-03-15 17:56 202
8f94a7f5 sago007 2020-05-10 10:26 203
    //! Swap the content of this pointer with an other.
8f94a7f5 sago007 2020-05-10 10:26 204
    /*!
8f94a7f5 sago007 2020-05-10 10:26 205
        \param other The pointer to swap with.
8f94a7f5 sago007 2020-05-10 10:26 206
        \note Constant complexity.
8f94a7f5 sago007 2020-05-10 10:26 207
    */
8f94a7f5 sago007 2020-05-10 10:26 208
    GenericPointer& Swap(GenericPointer& other) CEREAL_RAPIDJSON_NOEXCEPT {
8f94a7f5 sago007 2020-05-10 10:26 209
        internal::Swap(allocator_, other.allocator_);
8f94a7f5 sago007 2020-05-10 10:26 210
        internal::Swap(ownAllocator_, other.ownAllocator_);
8f94a7f5 sago007 2020-05-10 10:26 211
        internal::Swap(nameBuffer_, other.nameBuffer_);
8f94a7f5 sago007 2020-05-10 10:26 212
        internal::Swap(tokens_, other.tokens_);
8f94a7f5 sago007 2020-05-10 10:26 213
        internal::Swap(tokenCount_, other.tokenCount_);
8f94a7f5 sago007 2020-05-10 10:26 214
        internal::Swap(parseErrorOffset_, other.parseErrorOffset_);
8f94a7f5 sago007 2020-05-10 10:26 215
        internal::Swap(parseErrorCode_, other.parseErrorCode_);
8f94a7f5 sago007 2020-05-10 10:26 216
        return *this;
8f94a7f5 sago007 2020-05-10 10:26 217
    }
8f94a7f5 sago007 2020-05-10 10:26 218
8f94a7f5 sago007 2020-05-10 10:26 219
    //! free-standing swap function helper
8f94a7f5 sago007 2020-05-10 10:26 220
    /*!
8f94a7f5 sago007 2020-05-10 10:26 221
        Helper function to enable support for common swap implementation pattern based on \c std::swap:
8f94a7f5 sago007 2020-05-10 10:26 222
        \code
8f94a7f5 sago007 2020-05-10 10:26 223
        void swap(MyClass& a, MyClass& b) {
8f94a7f5 sago007 2020-05-10 10:26 224
            using std::swap;
8f94a7f5 sago007 2020-05-10 10:26 225
            swap(a.pointer, b.pointer);
8f94a7f5 sago007 2020-05-10 10:26 226
            // ...
8f94a7f5 sago007 2020-05-10 10:26 227
        }
8f94a7f5 sago007 2020-05-10 10:26 228
        \endcode
8f94a7f5 sago007 2020-05-10 10:26 229
        \see Swap()
8f94a7f5 sago007 2020-05-10 10:26 230
     */
8f94a7f5 sago007 2020-05-10 10:26 231
    friend inline void swap(GenericPointer& a, GenericPointer& b) CEREAL_RAPIDJSON_NOEXCEPT { a.Swap(b); }
8f94a7f5 sago007 2020-05-10 10:26 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 Append token
6c5f2c01 sago007 2017-03-15 17:56 236
    //@{
6c5f2c01 sago007 2017-03-15 17:56 237
6c5f2c01 sago007 2017-03-15 17:56 238
    //! Append a token and return a new Pointer
6c5f2c01 sago007 2017-03-15 17:56 239
    /*!
6c5f2c01 sago007 2017-03-15 17:56 240
        \param token Token to be appended.
6c5f2c01 sago007 2017-03-15 17:56 241
        \param allocator Allocator for the newly return Pointer.
6c5f2c01 sago007 2017-03-15 17:56 242
        \return A new Pointer with appended token.
6c5f2c01 sago007 2017-03-15 17:56 243
    */
6c5f2c01 sago007 2017-03-15 17:56 244
    GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
6c5f2c01 sago007 2017-03-15 17:56 245
        GenericPointer r;
6c5f2c01 sago007 2017-03-15 17:56 246
        r.allocator_ = allocator;
6c5f2c01 sago007 2017-03-15 17:56 247
        Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
6c5f2c01 sago007 2017-03-15 17:56 248
        std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
6c5f2c01 sago007 2017-03-15 17:56 249
        r.tokens_[tokenCount_].name = p;
6c5f2c01 sago007 2017-03-15 17:56 250
        r.tokens_[tokenCount_].length = token.length;
6c5f2c01 sago007 2017-03-15 17:56 251
        r.tokens_[tokenCount_].index = token.index;
6c5f2c01 sago007 2017-03-15 17:56 252
        return r;
6c5f2c01 sago007 2017-03-15 17:56 253
    }
6c5f2c01 sago007 2017-03-15 17:56 254
6c5f2c01 sago007 2017-03-15 17:56 255
    //! Append a name token with length, and return a new Pointer
6c5f2c01 sago007 2017-03-15 17:56 256
    /*!
6c5f2c01 sago007 2017-03-15 17:56 257
        \param name Name to be appended.
6c5f2c01 sago007 2017-03-15 17:56 258
        \param length Length of name.
6c5f2c01 sago007 2017-03-15 17:56 259
        \param allocator Allocator for the newly return Pointer.
6c5f2c01 sago007 2017-03-15 17:56 260
        \return A new Pointer with appended token.
6c5f2c01 sago007 2017-03-15 17:56 261
    */
6c5f2c01 sago007 2017-03-15 17:56 262
    GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
6c5f2c01 sago007 2017-03-15 17:56 263
        Token token = { name, length, kPointerInvalidIndex };
6c5f2c01 sago007 2017-03-15 17:56 264
        return Append(token, allocator);
6c5f2c01 sago007 2017-03-15 17:56 265
    }
6c5f2c01 sago007 2017-03-15 17:56 266
6c5f2c01 sago007 2017-03-15 17:56 267
    //! Append a name token without length, and return a new Pointer
6c5f2c01 sago007 2017-03-15 17:56 268
    /*!
6c5f2c01 sago007 2017-03-15 17:56 269
        \param name Name (const Ch*) to be appended.
6c5f2c01 sago007 2017-03-15 17:56 270
        \param allocator Allocator for the newly return Pointer.
6c5f2c01 sago007 2017-03-15 17:56 271
        \return A new Pointer with appended token.
6c5f2c01 sago007 2017-03-15 17:56 272
    */
6c5f2c01 sago007 2017-03-15 17:56 273
    template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 274
    CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
6c5f2c01 sago007 2017-03-15 17:56 275
    Append(T* name, Allocator* allocator = 0) const {
8f94a7f5 sago007 2020-05-10 10:26 276
        return Append(name, internal::StrLen(name), allocator);
6c5f2c01 sago007 2017-03-15 17:56 277
    }
6c5f2c01 sago007 2017-03-15 17:56 278
6c5f2c01 sago007 2017-03-15 17:56 279
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 280
    //! Append a name token, and return a new Pointer
6c5f2c01 sago007 2017-03-15 17:56 281
    /*!
6c5f2c01 sago007 2017-03-15 17:56 282
        \param name Name to be appended.
6c5f2c01 sago007 2017-03-15 17:56 283
        \param allocator Allocator for the newly return Pointer.
6c5f2c01 sago007 2017-03-15 17:56 284
        \return A new Pointer with appended token.
6c5f2c01 sago007 2017-03-15 17:56 285
    */
6c5f2c01 sago007 2017-03-15 17:56 286
    GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
6c5f2c01 sago007 2017-03-15 17:56 287
        return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
6c5f2c01 sago007 2017-03-15 17:56 288
    }
6c5f2c01 sago007 2017-03-15 17:56 289
#endif
6c5f2c01 sago007 2017-03-15 17:56 290
6c5f2c01 sago007 2017-03-15 17:56 291
    //! Append a index token, and return a new Pointer
6c5f2c01 sago007 2017-03-15 17:56 292
    /*!
6c5f2c01 sago007 2017-03-15 17:56 293
        \param index Index to be appended.
6c5f2c01 sago007 2017-03-15 17:56 294
        \param allocator Allocator for the newly return Pointer.
6c5f2c01 sago007 2017-03-15 17:56 295
        \return A new Pointer with appended token.
6c5f2c01 sago007 2017-03-15 17:56 296
    */
6c5f2c01 sago007 2017-03-15 17:56 297
    GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
6c5f2c01 sago007 2017-03-15 17:56 298
        char buffer[21];
6c5f2c01 sago007 2017-03-15 17:56 299
        char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
6c5f2c01 sago007 2017-03-15 17:56 300
        SizeType length = static_cast<SizeType>(end - buffer);
6c5f2c01 sago007 2017-03-15 17:56 301
        buffer[length] = '\0';
6c5f2c01 sago007 2017-03-15 17:56 302
6c5f2c01 sago007 2017-03-15 17:56 303
        if (sizeof(Ch) == 1) {
6c5f2c01 sago007 2017-03-15 17:56 304
            Token token = { reinterpret_cast<Ch*>(buffer), length, index };
6c5f2c01 sago007 2017-03-15 17:56 305
            return Append(token, allocator);
6c5f2c01 sago007 2017-03-15 17:56 306
        }
6c5f2c01 sago007 2017-03-15 17:56 307
        else {
6c5f2c01 sago007 2017-03-15 17:56 308
            Ch name[21];
6c5f2c01 sago007 2017-03-15 17:56 309
            for (size_t i = 0; i <= length; i++)
8f94a7f5 sago007 2020-05-10 10:26 310
                name[i] = static_cast<Ch>(buffer[i]);
6c5f2c01 sago007 2017-03-15 17:56 311
            Token token = { name, length, index };
6c5f2c01 sago007 2017-03-15 17:56 312
            return Append(token, allocator);
6c5f2c01 sago007 2017-03-15 17:56 313
        }
6c5f2c01 sago007 2017-03-15 17:56 314
    }
6c5f2c01 sago007 2017-03-15 17:56 315
6c5f2c01 sago007 2017-03-15 17:56 316
    //! Append a token by value, and return a new Pointer
6c5f2c01 sago007 2017-03-15 17:56 317
    /*!
6c5f2c01 sago007 2017-03-15 17:56 318
        \param token token to be appended.
6c5f2c01 sago007 2017-03-15 17:56 319
        \param allocator Allocator for the newly return Pointer.
6c5f2c01 sago007 2017-03-15 17:56 320
        \return A new Pointer with appended token.
6c5f2c01 sago007 2017-03-15 17:56 321
    */
6c5f2c01 sago007 2017-03-15 17:56 322
    GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
6c5f2c01 sago007 2017-03-15 17:56 323
        if (token.IsString())
6c5f2c01 sago007 2017-03-15 17:56 324
            return Append(token.GetString(), token.GetStringLength(), allocator);
6c5f2c01 sago007 2017-03-15 17:56 325
        else {
6c5f2c01 sago007 2017-03-15 17:56 326
            CEREAL_RAPIDJSON_ASSERT(token.IsUint64());
6c5f2c01 sago007 2017-03-15 17:56 327
            CEREAL_RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
6c5f2c01 sago007 2017-03-15 17:56 328
            return Append(static_cast<SizeType>(token.GetUint64()), allocator);
6c5f2c01 sago007 2017-03-15 17:56 329
        }
6c5f2c01 sago007 2017-03-15 17:56 330
    }
6c5f2c01 sago007 2017-03-15 17:56 331
6c5f2c01 sago007 2017-03-15 17:56 332
    //!@name Handling Parse Error
6c5f2c01 sago007 2017-03-15 17:56 333
    //@{
6c5f2c01 sago007 2017-03-15 17:56 334
6c5f2c01 sago007 2017-03-15 17:56 335
    //! Check whether this is a valid pointer.
6c5f2c01 sago007 2017-03-15 17:56 336
    bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
6c5f2c01 sago007 2017-03-15 17:56 337
6c5f2c01 sago007 2017-03-15 17:56 338
    //! Get the parsing error offset in code unit.
6c5f2c01 sago007 2017-03-15 17:56 339
    size_t GetParseErrorOffset() const { return parseErrorOffset_; }
6c5f2c01 sago007 2017-03-15 17:56 340
6c5f2c01 sago007 2017-03-15 17:56 341
    //! Get the parsing error code.
6c5f2c01 sago007 2017-03-15 17:56 342
    PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
6c5f2c01 sago007 2017-03-15 17:56 343
6c5f2c01 sago007 2017-03-15 17:56 344
    //@}
6c5f2c01 sago007 2017-03-15 17:56 345
6c5f2c01 sago007 2017-03-15 17:56 346
    //! Get the allocator of this pointer.
6c5f2c01 sago007 2017-03-15 17:56 347
    Allocator& GetAllocator() { return *allocator_; }
6c5f2c01 sago007 2017-03-15 17:56 348
6c5f2c01 sago007 2017-03-15 17:56 349
    //!@name Tokens
6c5f2c01 sago007 2017-03-15 17:56 350
    //@{
6c5f2c01 sago007 2017-03-15 17:56 351
6c5f2c01 sago007 2017-03-15 17:56 352
    //! Get the token array (const version only).
6c5f2c01 sago007 2017-03-15 17:56 353
    const Token* GetTokens() const { return tokens_; }
6c5f2c01 sago007 2017-03-15 17:56 354
6c5f2c01 sago007 2017-03-15 17:56 355
    //! Get the number of tokens.
6c5f2c01 sago007 2017-03-15 17:56 356
    size_t GetTokenCount() const { return tokenCount_; }
6c5f2c01 sago007 2017-03-15 17:56 357
6c5f2c01 sago007 2017-03-15 17:56 358
    //@}
6c5f2c01 sago007 2017-03-15 17:56 359
6c5f2c01 sago007 2017-03-15 17:56 360
    //!@name Equality/inequality operators
6c5f2c01 sago007 2017-03-15 17:56 361
    //@{
6c5f2c01 sago007 2017-03-15 17:56 362
6c5f2c01 sago007 2017-03-15 17:56 363
    //! Equality operator.
6c5f2c01 sago007 2017-03-15 17:56 364
    /*!
6c5f2c01 sago007 2017-03-15 17:56 365
        \note When any pointers are invalid, always returns false.
6c5f2c01 sago007 2017-03-15 17:56 366
    */
6c5f2c01 sago007 2017-03-15 17:56 367
    bool operator==(const GenericPointer& rhs) const {
6c5f2c01 sago007 2017-03-15 17:56 368
        if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
6c5f2c01 sago007 2017-03-15 17:56 369
            return false;
6c5f2c01 sago007 2017-03-15 17:56 370
6c5f2c01 sago007 2017-03-15 17:56 371
        for (size_t i = 0; i < tokenCount_; i++) {
6c5f2c01 sago007 2017-03-15 17:56 372
            if (tokens_[i].index != rhs.tokens_[i].index ||
6c5f2c01 sago007 2017-03-15 17:56 373
                tokens_[i].length != rhs.tokens_[i].length || 
6c5f2c01 sago007 2017-03-15 17:56 374
                (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
6c5f2c01 sago007 2017-03-15 17:56 375
            {
6c5f2c01 sago007 2017-03-15 17:56 376
                return false;
6c5f2c01 sago007 2017-03-15 17:56 377
            }
6c5f2c01 sago007 2017-03-15 17:56 378
        }
6c5f2c01 sago007 2017-03-15 17:56 379
6c5f2c01 sago007 2017-03-15 17:56 380
        return true;
6c5f2c01 sago007 2017-03-15 17:56 381
    }
6c5f2c01 sago007 2017-03-15 17:56 382
6c5f2c01 sago007 2017-03-15 17:56 383
    //! Inequality operator.
6c5f2c01 sago007 2017-03-15 17:56 384
    /*!
6c5f2c01 sago007 2017-03-15 17:56 385
        \note When any pointers are invalid, always returns true.
6c5f2c01 sago007 2017-03-15 17:56 386
    */
6c5f2c01 sago007 2017-03-15 17:56 387
    bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
6c5f2c01 sago007 2017-03-15 17:56 388
8f94a7f5 sago007 2020-05-10 10:26 389
    //! Less than operator.
8f94a7f5 sago007 2020-05-10 10:26 390
    /*!
8f94a7f5 sago007 2020-05-10 10:26 391
        \note Invalid pointers are always greater than valid ones.
8f94a7f5 sago007 2020-05-10 10:26 392
    */
8f94a7f5 sago007 2020-05-10 10:26 393
    bool operator<(const GenericPointer& rhs) const {
8f94a7f5 sago007 2020-05-10 10:26 394
        if (!IsValid())
8f94a7f5 sago007 2020-05-10 10:26 395
            return false;
8f94a7f5 sago007 2020-05-10 10:26 396
        if (!rhs.IsValid())
8f94a7f5 sago007 2020-05-10 10:26 397
            return true;
8f94a7f5 sago007 2020-05-10 10:26 398
8f94a7f5 sago007 2020-05-10 10:26 399
        if (tokenCount_ != rhs.tokenCount_)
8f94a7f5 sago007 2020-05-10 10:26 400
            return tokenCount_ < rhs.tokenCount_;
8f94a7f5 sago007 2020-05-10 10:26 401
8f94a7f5 sago007 2020-05-10 10:26 402
        for (size_t i = 0; i < tokenCount_; i++) {
8f94a7f5 sago007 2020-05-10 10:26 403
            if (tokens_[i].index != rhs.tokens_[i].index)
8f94a7f5 sago007 2020-05-10 10:26 404
                return tokens_[i].index < rhs.tokens_[i].index;
8f94a7f5 sago007 2020-05-10 10:26 405
8f94a7f5 sago007 2020-05-10 10:26 406
            if (tokens_[i].length != rhs.tokens_[i].length)
8f94a7f5 sago007 2020-05-10 10:26 407
                return tokens_[i].length < rhs.tokens_[i].length;
8f94a7f5 sago007 2020-05-10 10:26 408
8f94a7f5 sago007 2020-05-10 10:26 409
            if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length))
8f94a7f5 sago007 2020-05-10 10:26 410
                return cmp < 0;
8f94a7f5 sago007 2020-05-10 10:26 411
        }
8f94a7f5 sago007 2020-05-10 10:26 412
8f94a7f5 sago007 2020-05-10 10:26 413
        return false;
8f94a7f5 sago007 2020-05-10 10:26 414
    }
8f94a7f5 sago007 2020-05-10 10:26 415
6c5f2c01 sago007 2017-03-15 17:56 416
    //@}
6c5f2c01 sago007 2017-03-15 17:56 417
6c5f2c01 sago007 2017-03-15 17:56 418
    //!@name Stringify
6c5f2c01 sago007 2017-03-15 17:56 419
    //@{
6c5f2c01 sago007 2017-03-15 17:56 420
6c5f2c01 sago007 2017-03-15 17:56 421
    //! Stringify the pointer into string representation.
6c5f2c01 sago007 2017-03-15 17:56 422
    /*!
6c5f2c01 sago007 2017-03-15 17:56 423
        \tparam OutputStream Type of output stream.
6c5f2c01 sago007 2017-03-15 17:56 424
        \param os The output stream.
6c5f2c01 sago007 2017-03-15 17:56 425
    */
6c5f2c01 sago007 2017-03-15 17:56 426
    template<typename OutputStream>
6c5f2c01 sago007 2017-03-15 17:56 427
    bool Stringify(OutputStream& os) const {
6c5f2c01 sago007 2017-03-15 17:56 428
        return Stringify<false, OutputStream>(os);
6c5f2c01 sago007 2017-03-15 17:56 429
    }
6c5f2c01 sago007 2017-03-15 17:56 430
6c5f2c01 sago007 2017-03-15 17:56 431
    //! Stringify the pointer into URI fragment representation.
6c5f2c01 sago007 2017-03-15 17:56 432
    /*!
6c5f2c01 sago007 2017-03-15 17:56 433
        \tparam OutputStream Type of output stream.
6c5f2c01 sago007 2017-03-15 17:56 434
        \param os The output stream.
6c5f2c01 sago007 2017-03-15 17:56 435
    */
6c5f2c01 sago007 2017-03-15 17:56 436
    template<typename OutputStream>
6c5f2c01 sago007 2017-03-15 17:56 437
    bool StringifyUriFragment(OutputStream& os) const {
6c5f2c01 sago007 2017-03-15 17:56 438
        return Stringify<true, OutputStream>(os);
6c5f2c01 sago007 2017-03-15 17:56 439
    }
6c5f2c01 sago007 2017-03-15 17:56 440
6c5f2c01 sago007 2017-03-15 17:56 441
    //@}
6c5f2c01 sago007 2017-03-15 17:56 442
6c5f2c01 sago007 2017-03-15 17:56 443
    //!@name Create value
6c5f2c01 sago007 2017-03-15 17:56 444
    //@{
6c5f2c01 sago007 2017-03-15 17:56 445
6c5f2c01 sago007 2017-03-15 17:56 446
    //! Create a value in a subtree.
6c5f2c01 sago007 2017-03-15 17:56 447
    /*!
6c5f2c01 sago007 2017-03-15 17:56 448
        If the value is not exist, it creates all parent values and a JSON Null value.
6c5f2c01 sago007 2017-03-15 17:56 449
        So it always succeed and return the newly created or existing value.
6c5f2c01 sago007 2017-03-15 17:56 450
6c5f2c01 sago007 2017-03-15 17:56 451
        Remind that it may change types of parents according to tokens, so it 
6c5f2c01 sago007 2017-03-15 17:56 452
        potentially removes previously stored values. For example, if a document 
6c5f2c01 sago007 2017-03-15 17:56 453
        was an array, and "/foo" is used to create a value, then the document 
6c5f2c01 sago007 2017-03-15 17:56 454
        will be changed to an object, and all existing array elements are lost.
6c5f2c01 sago007 2017-03-15 17:56 455
6c5f2c01 sago007 2017-03-15 17:56 456
        \param root Root value of a DOM subtree to be resolved. It can be any value other than document root.
6c5f2c01 sago007 2017-03-15 17:56 457
        \param allocator Allocator for creating the values if the specified value or its parents are not exist.
6c5f2c01 sago007 2017-03-15 17:56 458
        \param alreadyExist If non-null, it stores whether the resolved value is already exist.
6c5f2c01 sago007 2017-03-15 17:56 459
        \return The resolved newly created (a JSON Null value), or already exists value.
6c5f2c01 sago007 2017-03-15 17:56 460
    */
6c5f2c01 sago007 2017-03-15 17:56 461
    ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
6c5f2c01 sago007 2017-03-15 17:56 462
        CEREAL_RAPIDJSON_ASSERT(IsValid());
6c5f2c01 sago007 2017-03-15 17:56 463
        ValueType* v = &root;
6c5f2c01 sago007 2017-03-15 17:56 464
        bool exist = true;
6c5f2c01 sago007 2017-03-15 17:56 465
        for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
6c5f2c01 sago007 2017-03-15 17:56 466
            if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
6c5f2c01 sago007 2017-03-15 17:56 467
                v->PushBack(ValueType().Move(), allocator);
6c5f2c01 sago007 2017-03-15 17:56 468
                v = &((*v)[v->Size() - 1]);
6c5f2c01 sago007 2017-03-15 17:56 469
                exist = false;
6c5f2c01 sago007 2017-03-15 17:56 470
            }
6c5f2c01 sago007 2017-03-15 17:56 471
            else {
6c5f2c01 sago007 2017-03-15 17:56 472
                if (t->index == kPointerInvalidIndex) { // must be object name
6c5f2c01 sago007 2017-03-15 17:56 473
                    if (!v->IsObject())
6c5f2c01 sago007 2017-03-15 17:56 474
                        v->SetObject(); // Change to Object
6c5f2c01 sago007 2017-03-15 17:56 475
                }
6c5f2c01 sago007 2017-03-15 17:56 476
                else { // object name or array index
6c5f2c01 sago007 2017-03-15 17:56 477
                    if (!v->IsArray() && !v->IsObject())
6c5f2c01 sago007 2017-03-15 17:56 478
                        v->SetArray(); // Change to Array
6c5f2c01 sago007 2017-03-15 17:56 479
                }
6c5f2c01 sago007 2017-03-15 17:56 480
6c5f2c01 sago007 2017-03-15 17:56 481
                if (v->IsArray()) {
6c5f2c01 sago007 2017-03-15 17:56 482
                    if (t->index >= v->Size()) {
6c5f2c01 sago007 2017-03-15 17:56 483
                        v->Reserve(t->index + 1, allocator);
6c5f2c01 sago007 2017-03-15 17:56 484
                        while (t->index >= v->Size())
6c5f2c01 sago007 2017-03-15 17:56 485
                            v->PushBack(ValueType().Move(), allocator);
6c5f2c01 sago007 2017-03-15 17:56 486
                        exist = false;
6c5f2c01 sago007 2017-03-15 17:56 487
                    }
6c5f2c01 sago007 2017-03-15 17:56 488
                    v = &((*v)[t->index]);
6c5f2c01 sago007 2017-03-15 17:56 489
                }
6c5f2c01 sago007 2017-03-15 17:56 490
                else {
6c5f2c01 sago007 2017-03-15 17:56 491
                    typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
6c5f2c01 sago007 2017-03-15 17:56 492
                    if (m == v->MemberEnd()) {
6c5f2c01 sago007 2017-03-15 17:56 493
                        v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
6c5f2c01 sago007 2017-03-15 17:56 494
                        v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
6c5f2c01 sago007 2017-03-15 17:56 495
                        exist = false;
6c5f2c01 sago007 2017-03-15 17:56 496
                    }
6c5f2c01 sago007 2017-03-15 17:56 497
                    else
6c5f2c01 sago007 2017-03-15 17:56 498
                        v = &m->value;
6c5f2c01 sago007 2017-03-15 17:56 499
                }
6c5f2c01 sago007 2017-03-15 17:56 500
            }
6c5f2c01 sago007 2017-03-15 17:56 501
        }
6c5f2c01 sago007 2017-03-15 17:56 502
6c5f2c01 sago007 2017-03-15 17:56 503
        if (alreadyExist)
6c5f2c01 sago007 2017-03-15 17:56 504
            *alreadyExist = exist;
6c5f2c01 sago007 2017-03-15 17:56 505
6c5f2c01 sago007 2017-03-15 17:56 506
        return *v;
6c5f2c01 sago007 2017-03-15 17:56 507
    }
6c5f2c01 sago007 2017-03-15 17:56 508
6c5f2c01 sago007 2017-03-15 17:56 509
    //! Creates a value in a document.
6c5f2c01 sago007 2017-03-15 17:56 510
    /*!
6c5f2c01 sago007 2017-03-15 17:56 511
        \param document A document to be resolved.
6c5f2c01 sago007 2017-03-15 17:56 512
        \param alreadyExist If non-null, it stores whether the resolved value is already exist.
6c5f2c01 sago007 2017-03-15 17:56 513
        \return The resolved newly created, or already exists value.
6c5f2c01 sago007 2017-03-15 17:56 514
    */
6c5f2c01 sago007 2017-03-15 17:56 515
    template <typename stackAllocator>
6c5f2c01 sago007 2017-03-15 17:56 516
    ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
6c5f2c01 sago007 2017-03-15 17:56 517
        return Create(document, document.GetAllocator(), alreadyExist);
6c5f2c01 sago007 2017-03-15 17:56 518
    }
6c5f2c01 sago007 2017-03-15 17:56 519
6c5f2c01 sago007 2017-03-15 17:56 520
    //@}
6c5f2c01 sago007 2017-03-15 17:56 521
6c5f2c01 sago007 2017-03-15 17:56 522
    //!@name Query value
6c5f2c01 sago007 2017-03-15 17:56 523
    //@{
6c5f2c01 sago007 2017-03-15 17:56 524
6c5f2c01 sago007 2017-03-15 17:56 525
    //! Query a value in a subtree.
6c5f2c01 sago007 2017-03-15 17:56 526
    /*!
6c5f2c01 sago007 2017-03-15 17:56 527
        \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
6c5f2c01 sago007 2017-03-15 17:56 528
        \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
6c5f2c01 sago007 2017-03-15 17:56 529
        \return Pointer to the value if it can be resolved. Otherwise null.
6c5f2c01 sago007 2017-03-15 17:56 530
6c5f2c01 sago007 2017-03-15 17:56 531
        \note
6c5f2c01 sago007 2017-03-15 17:56 532
        There are only 3 situations when a value cannot be resolved:
6c5f2c01 sago007 2017-03-15 17:56 533
        1. A value in the path is not an array nor object.
6c5f2c01 sago007 2017-03-15 17:56 534
        2. An object value does not contain the token.
6c5f2c01 sago007 2017-03-15 17:56 535
        3. A token is out of range of an array value.
6c5f2c01 sago007 2017-03-15 17:56 536
6c5f2c01 sago007 2017-03-15 17:56 537
        Use unresolvedTokenIndex to retrieve the token index.
6c5f2c01 sago007 2017-03-15 17:56 538
    */
6c5f2c01 sago007 2017-03-15 17:56 539
    ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
6c5f2c01 sago007 2017-03-15 17:56 540
        CEREAL_RAPIDJSON_ASSERT(IsValid());
6c5f2c01 sago007 2017-03-15 17:56 541
        ValueType* v = &root;
6c5f2c01 sago007 2017-03-15 17:56 542
        for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
6c5f2c01 sago007 2017-03-15 17:56 543
            switch (v->GetType()) {
6c5f2c01 sago007 2017-03-15 17:56 544
            case kObjectType:
6c5f2c01 sago007 2017-03-15 17:56 545
                {
6c5f2c01 sago007 2017-03-15 17:56 546
                    typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
6c5f2c01 sago007 2017-03-15 17:56 547
                    if (m == v->MemberEnd())
6c5f2c01 sago007 2017-03-15 17:56 548
                        break;
6c5f2c01 sago007 2017-03-15 17:56 549
                    v = &m->value;
6c5f2c01 sago007 2017-03-15 17:56 550
                }
6c5f2c01 sago007 2017-03-15 17:56 551
                continue;
6c5f2c01 sago007 2017-03-15 17:56 552
            case kArrayType:
6c5f2c01 sago007 2017-03-15 17:56 553
                if (t->index == kPointerInvalidIndex || t->index >= v->Size())
6c5f2c01 sago007 2017-03-15 17:56 554
                    break;
6c5f2c01 sago007 2017-03-15 17:56 555
                v = &((*v)[t->index]);
6c5f2c01 sago007 2017-03-15 17:56 556
                continue;
6c5f2c01 sago007 2017-03-15 17:56 557
            default:
6c5f2c01 sago007 2017-03-15 17:56 558
                break;
6c5f2c01 sago007 2017-03-15 17:56 559
            }
6c5f2c01 sago007 2017-03-15 17:56 560
6c5f2c01 sago007 2017-03-15 17:56 561
            // Error: unresolved token
6c5f2c01 sago007 2017-03-15 17:56 562
            if (unresolvedTokenIndex)
6c5f2c01 sago007 2017-03-15 17:56 563
                *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
6c5f2c01 sago007 2017-03-15 17:56 564
            return 0;
6c5f2c01 sago007 2017-03-15 17:56 565
        }
6c5f2c01 sago007 2017-03-15 17:56 566
        return v;
6c5f2c01 sago007 2017-03-15 17:56 567
    }
6c5f2c01 sago007 2017-03-15 17:56 568
6c5f2c01 sago007 2017-03-15 17:56 569
    //! Query a const value in a const subtree.
6c5f2c01 sago007 2017-03-15 17:56 570
    /*!
6c5f2c01 sago007 2017-03-15 17:56 571
        \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
6c5f2c01 sago007 2017-03-15 17:56 572
        \return Pointer to the value if it can be resolved. Otherwise null.
6c5f2c01 sago007 2017-03-15 17:56 573
    */
6c5f2c01 sago007 2017-03-15 17:56 574
    const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { 
6c5f2c01 sago007 2017-03-15 17:56 575
        return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
6c5f2c01 sago007 2017-03-15 17:56 576
    }
6c5f2c01 sago007 2017-03-15 17:56 577
6c5f2c01 sago007 2017-03-15 17:56 578
    //@}
6c5f2c01 sago007 2017-03-15 17:56 579
6c5f2c01 sago007 2017-03-15 17:56 580
    //!@name Query a value with default
6c5f2c01 sago007 2017-03-15 17:56 581
    //@{
6c5f2c01 sago007 2017-03-15 17:56 582
6c5f2c01 sago007 2017-03-15 17:56 583
    //! Query a value in a subtree with default value.
6c5f2c01 sago007 2017-03-15 17:56 584
    /*!
6c5f2c01 sago007 2017-03-15 17:56 585
        Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value.
6c5f2c01 sago007 2017-03-15 17:56 586
        So that this function always succeed.
6c5f2c01 sago007 2017-03-15 17:56 587
6c5f2c01 sago007 2017-03-15 17:56 588
        \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
6c5f2c01 sago007 2017-03-15 17:56 589
        \param defaultValue Default value to be cloned if the value was not exists.
6c5f2c01 sago007 2017-03-15 17:56 590
        \param allocator Allocator for creating the values if the specified value or its parents are not exist.
6c5f2c01 sago007 2017-03-15 17:56 591
        \see Create()
6c5f2c01 sago007 2017-03-15 17:56 592
    */
6c5f2c01 sago007 2017-03-15 17:56 593
    ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
6c5f2c01 sago007 2017-03-15 17:56 594
        bool alreadyExist;
8f94a7f5 sago007 2020-05-10 10:26 595
        ValueType& v = Create(root, allocator, &alreadyExist);
6c5f2c01 sago007 2017-03-15 17:56 596
        return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
6c5f2c01 sago007 2017-03-15 17:56 597
    }
6c5f2c01 sago007 2017-03-15 17:56 598
6c5f2c01 sago007 2017-03-15 17:56 599
    //! Query a value in a subtree with default null-terminated string.
6c5f2c01 sago007 2017-03-15 17:56 600
    ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
6c5f2c01 sago007 2017-03-15 17:56 601
        bool alreadyExist;
8f94a7f5 sago007 2020-05-10 10:26 602
        ValueType& v = Create(root, allocator, &alreadyExist);
6c5f2c01 sago007 2017-03-15 17:56 603
        return alreadyExist ? v : v.SetString(defaultValue, allocator);
6c5f2c01 sago007 2017-03-15 17:56 604
    }
6c5f2c01 sago007 2017-03-15 17:56 605
6c5f2c01 sago007 2017-03-15 17:56 606
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 607
    //! Query a value in a subtree with default std::basic_string.
6c5f2c01 sago007 2017-03-15 17:56 608
    ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
6c5f2c01 sago007 2017-03-15 17:56 609
        bool alreadyExist;
8f94a7f5 sago007 2020-05-10 10:26 610
        ValueType& v = Create(root, allocator, &alreadyExist);
6c5f2c01 sago007 2017-03-15 17:56 611
        return alreadyExist ? v : v.SetString(defaultValue, allocator);
6c5f2c01 sago007 2017-03-15 17:56 612
    }
6c5f2c01 sago007 2017-03-15 17:56 613
#endif
6c5f2c01 sago007 2017-03-15 17:56 614
6c5f2c01 sago007 2017-03-15 17:56 615
    //! Query a value in a subtree with default primitive value.
6c5f2c01 sago007 2017-03-15 17:56 616
    /*!
6c5f2c01 sago007 2017-03-15 17:56 617
        \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
6c5f2c01 sago007 2017-03-15 17:56 618
    */
6c5f2c01 sago007 2017-03-15 17:56 619
    template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 620
    CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
6c5f2c01 sago007 2017-03-15 17:56 621
    GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
6c5f2c01 sago007 2017-03-15 17:56 622
        return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
6c5f2c01 sago007 2017-03-15 17:56 623
    }
6c5f2c01 sago007 2017-03-15 17:56 624
6c5f2c01 sago007 2017-03-15 17:56 625
    //! Query a value in a document with default value.
6c5f2c01 sago007 2017-03-15 17:56 626
    template <typename stackAllocator>
6c5f2c01 sago007 2017-03-15 17:56 627
    ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const {
6c5f2c01 sago007 2017-03-15 17:56 628
        return GetWithDefault(document, defaultValue, document.GetAllocator());
6c5f2c01 sago007 2017-03-15 17:56 629
    }
6c5f2c01 sago007 2017-03-15 17:56 630
6c5f2c01 sago007 2017-03-15 17:56 631
    //! Query a value in a document with default null-terminated string.
6c5f2c01 sago007 2017-03-15 17:56 632
    template <typename stackAllocator>
6c5f2c01 sago007 2017-03-15 17:56 633
    ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
6c5f2c01 sago007 2017-03-15 17:56 634
        return GetWithDefault(document, defaultValue, document.GetAllocator());
6c5f2c01 sago007 2017-03-15 17:56 635
    }
6c5f2c01 sago007 2017-03-15 17:56 636
    
6c5f2c01 sago007 2017-03-15 17:56 637
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 638
    //! Query a value in a document with default std::basic_string.
6c5f2c01 sago007 2017-03-15 17:56 639
    template <typename stackAllocator>
6c5f2c01 sago007 2017-03-15 17:56 640
    ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
6c5f2c01 sago007 2017-03-15 17:56 641
        return GetWithDefault(document, defaultValue, document.GetAllocator());
6c5f2c01 sago007 2017-03-15 17:56 642
    }
6c5f2c01 sago007 2017-03-15 17:56 643
#endif
6c5f2c01 sago007 2017-03-15 17:56 644
6c5f2c01 sago007 2017-03-15 17:56 645
    //! Query a value in a document with default primitive value.
6c5f2c01 sago007 2017-03-15 17:56 646
    /*!
6c5f2c01 sago007 2017-03-15 17:56 647
        \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
6c5f2c01 sago007 2017-03-15 17:56 648
    */
6c5f2c01 sago007 2017-03-15 17:56 649
    template <typename T, typename stackAllocator>
6c5f2c01 sago007 2017-03-15 17:56 650
    CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
6c5f2c01 sago007 2017-03-15 17:56 651
    GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
6c5f2c01 sago007 2017-03-15 17:56 652
        return GetWithDefault(document, defaultValue, document.GetAllocator());
6c5f2c01 sago007 2017-03-15 17:56 653
    }
6c5f2c01 sago007 2017-03-15 17:56 654
6c5f2c01 sago007 2017-03-15 17:56 655
    //@}
6c5f2c01 sago007 2017-03-15 17:56 656
6c5f2c01 sago007 2017-03-15 17:56 657
    //!@name Set a value
6c5f2c01 sago007 2017-03-15 17:56 658
    //@{
6c5f2c01 sago007 2017-03-15 17:56 659
6c5f2c01 sago007 2017-03-15 17:56 660
    //! Set a value in a subtree, with move semantics.
6c5f2c01 sago007 2017-03-15 17:56 661
    /*!
6c5f2c01 sago007 2017-03-15 17:56 662
        It creates all parents if they are not exist or types are different to the tokens.
6c5f2c01 sago007 2017-03-15 17:56 663
        So this function always succeeds but potentially remove existing values.
6c5f2c01 sago007 2017-03-15 17:56 664
6c5f2c01 sago007 2017-03-15 17:56 665
        \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
6c5f2c01 sago007 2017-03-15 17:56 666
        \param value Value to be set.
6c5f2c01 sago007 2017-03-15 17:56 667
        \param allocator Allocator for creating the values if the specified value or its parents are not exist.
6c5f2c01 sago007 2017-03-15 17:56 668
        \see Create()
6c5f2c01 sago007 2017-03-15 17:56 669
    */
6c5f2c01 sago007 2017-03-15 17:56 670
    ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
6c5f2c01 sago007 2017-03-15 17:56 671
        return Create(root, allocator) = value;
6c5f2c01 sago007 2017-03-15 17:56 672
    }
6c5f2c01 sago007 2017-03-15 17:56 673
6c5f2c01 sago007 2017-03-15 17:56 674
    //! Set a value in a subtree, with copy semantics.
6c5f2c01 sago007 2017-03-15 17:56 675
    ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
6c5f2c01 sago007 2017-03-15 17:56 676
        return Create(root, allocator).CopyFrom(value, allocator);
6c5f2c01 sago007 2017-03-15 17:56 677
    }
6c5f2c01 sago007 2017-03-15 17:56 678
6c5f2c01 sago007 2017-03-15 17:56 679
    //! Set a null-terminated string in a subtree.
6c5f2c01 sago007 2017-03-15 17:56 680
    ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
6c5f2c01 sago007 2017-03-15 17:56 681
        return Create(root, allocator) = ValueType(value, allocator).Move();
6c5f2c01 sago007 2017-03-15 17:56 682
    }
6c5f2c01 sago007 2017-03-15 17:56 683
6c5f2c01 sago007 2017-03-15 17:56 684
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 685
    //! Set a std::basic_string in a subtree.
6c5f2c01 sago007 2017-03-15 17:56 686
    ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
6c5f2c01 sago007 2017-03-15 17:56 687
        return Create(root, allocator) = ValueType(value, allocator).Move();
6c5f2c01 sago007 2017-03-15 17:56 688
    }
6c5f2c01 sago007 2017-03-15 17:56 689
#endif
6c5f2c01 sago007 2017-03-15 17:56 690
6c5f2c01 sago007 2017-03-15 17:56 691
    //! Set a primitive value in a subtree.
6c5f2c01 sago007 2017-03-15 17:56 692
    /*!
6c5f2c01 sago007 2017-03-15 17:56 693
        \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
6c5f2c01 sago007 2017-03-15 17:56 694
    */
6c5f2c01 sago007 2017-03-15 17:56 695
    template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 696
    CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
6c5f2c01 sago007 2017-03-15 17:56 697
    Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
6c5f2c01 sago007 2017-03-15 17:56 698
        return Create(root, allocator) = ValueType(value).Move();
6c5f2c01 sago007 2017-03-15 17:56 699
    }
6c5f2c01 sago007 2017-03-15 17:56 700
6c5f2c01 sago007 2017-03-15 17:56 701
    //! Set a value in a document, with move semantics.
6c5f2c01 sago007 2017-03-15 17:56 702
    template <typename stackAllocator>
6c5f2c01 sago007 2017-03-15 17:56 703
    ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
6c5f2c01 sago007 2017-03-15 17:56 704
        return Create(document) = value;
6c5f2c01 sago007 2017-03-15 17:56 705
    }
6c5f2c01 sago007 2017-03-15 17:56 706
6c5f2c01 sago007 2017-03-15 17:56 707
    //! Set a value in a document, with copy semantics.
6c5f2c01 sago007 2017-03-15 17:56 708
    template <typename stackAllocator>
6c5f2c01 sago007 2017-03-15 17:56 709
    ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {
6c5f2c01 sago007 2017-03-15 17:56 710
        return Create(document).CopyFrom(value, document.GetAllocator());
6c5f2c01 sago007 2017-03-15 17:56 711
    }
6c5f2c01 sago007 2017-03-15 17:56 712
6c5f2c01 sago007 2017-03-15 17:56 713
    //! Set a null-terminated string in a document.
6c5f2c01 sago007 2017-03-15 17:56 714
    template <typename stackAllocator>
6c5f2c01 sago007 2017-03-15 17:56 715
    ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const {
6c5f2c01 sago007 2017-03-15 17:56 716
        return Create(document) = ValueType(value, document.GetAllocator()).Move();
6c5f2c01 sago007 2017-03-15 17:56 717
    }
6c5f2c01 sago007 2017-03-15 17:56 718
6c5f2c01 sago007 2017-03-15 17:56 719
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 720
    //! Sets a std::basic_string in a document.
6c5f2c01 sago007 2017-03-15 17:56 721
    template <typename stackAllocator>
6c5f2c01 sago007 2017-03-15 17:56 722
    ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
6c5f2c01 sago007 2017-03-15 17:56 723
        return Create(document) = ValueType(value, document.GetAllocator()).Move();
6c5f2c01 sago007 2017-03-15 17:56 724
    }
6c5f2c01 sago007 2017-03-15 17:56 725
#endif
6c5f2c01 sago007 2017-03-15 17:56 726
6c5f2c01 sago007 2017-03-15 17:56 727
    //! Set a primitive value in a document.
6c5f2c01 sago007 2017-03-15 17:56 728
    /*!
6c5f2c01 sago007 2017-03-15 17:56 729
    \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
6c5f2c01 sago007 2017-03-15 17:56 730
    */
6c5f2c01 sago007 2017-03-15 17:56 731
    template <typename T, typename stackAllocator>
6c5f2c01 sago007 2017-03-15 17:56 732
    CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
6c5f2c01 sago007 2017-03-15 17:56 733
        Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
6c5f2c01 sago007 2017-03-15 17:56 734
            return Create(document) = value;
6c5f2c01 sago007 2017-03-15 17:56 735
    }
6c5f2c01 sago007 2017-03-15 17:56 736
6c5f2c01 sago007 2017-03-15 17:56 737
    //@}
6c5f2c01 sago007 2017-03-15 17:56 738
6c5f2c01 sago007 2017-03-15 17:56 739
    //!@name Swap a value
6c5f2c01 sago007 2017-03-15 17:56 740
    //@{
6c5f2c01 sago007 2017-03-15 17:56 741
6c5f2c01 sago007 2017-03-15 17:56 742
    //! Swap a value with a value in a subtree.
6c5f2c01 sago007 2017-03-15 17:56 743
    /*!
6c5f2c01 sago007 2017-03-15 17:56 744
        It creates all parents if they are not exist or types are different to the tokens.
6c5f2c01 sago007 2017-03-15 17:56 745
        So this function always succeeds but potentially remove existing values.
6c5f2c01 sago007 2017-03-15 17:56 746
6c5f2c01 sago007 2017-03-15 17:56 747
        \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
6c5f2c01 sago007 2017-03-15 17:56 748
        \param value Value to be swapped.
6c5f2c01 sago007 2017-03-15 17:56 749
        \param allocator Allocator for creating the values if the specified value or its parents are not exist.
6c5f2c01 sago007 2017-03-15 17:56 750
        \see Create()
6c5f2c01 sago007 2017-03-15 17:56 751
    */
6c5f2c01 sago007 2017-03-15 17:56 752
    ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
6c5f2c01 sago007 2017-03-15 17:56 753
        return Create(root, allocator).Swap(value);
6c5f2c01 sago007 2017-03-15 17:56 754
    }
6c5f2c01 sago007 2017-03-15 17:56 755
6c5f2c01 sago007 2017-03-15 17:56 756
    //! Swap a value with a value in a document.
6c5f2c01 sago007 2017-03-15 17:56 757
    template <typename stackAllocator>
6c5f2c01 sago007 2017-03-15 17:56 758
    ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
6c5f2c01 sago007 2017-03-15 17:56 759
        return Create(document).Swap(value);
6c5f2c01 sago007 2017-03-15 17:56 760
    }
6c5f2c01 sago007 2017-03-15 17:56 761
6c5f2c01 sago007 2017-03-15 17:56 762
    //@}
6c5f2c01 sago007 2017-03-15 17:56 763
6c5f2c01 sago007 2017-03-15 17:56 764
    //! Erase a value in a subtree.
6c5f2c01 sago007 2017-03-15 17:56 765
    /*!
6c5f2c01 sago007 2017-03-15 17:56 766
        \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
6c5f2c01 sago007 2017-03-15 17:56 767
        \return Whether the resolved value is found and erased.
6c5f2c01 sago007 2017-03-15 17:56 768
6c5f2c01 sago007 2017-03-15 17:56 769
        \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false.
6c5f2c01 sago007 2017-03-15 17:56 770
    */
6c5f2c01 sago007 2017-03-15 17:56 771
    bool Erase(ValueType& root) const {
6c5f2c01 sago007 2017-03-15 17:56 772
        CEREAL_RAPIDJSON_ASSERT(IsValid());
6c5f2c01 sago007 2017-03-15 17:56 773
        if (tokenCount_ == 0) // Cannot erase the root
6c5f2c01 sago007 2017-03-15 17:56 774
            return false;
6c5f2c01 sago007 2017-03-15 17:56 775
6c5f2c01 sago007 2017-03-15 17:56 776
        ValueType* v = &root;
6c5f2c01 sago007 2017-03-15 17:56 777
        const Token* last = tokens_ + (tokenCount_ - 1);
6c5f2c01 sago007 2017-03-15 17:56 778
        for (const Token *t = tokens_; t != last; ++t) {
6c5f2c01 sago007 2017-03-15 17:56 779
            switch (v->GetType()) {
6c5f2c01 sago007 2017-03-15 17:56 780
            case kObjectType:
6c5f2c01 sago007 2017-03-15 17:56 781
                {
6c5f2c01 sago007 2017-03-15 17:56 782
                    typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
6c5f2c01 sago007 2017-03-15 17:56 783
                    if (m == v->MemberEnd())
6c5f2c01 sago007 2017-03-15 17:56 784
                        return false;
6c5f2c01 sago007 2017-03-15 17:56 785
                    v = &m->value;
6c5f2c01 sago007 2017-03-15 17:56 786
                }
6c5f2c01 sago007 2017-03-15 17:56 787
                break;
6c5f2c01 sago007 2017-03-15 17:56 788
            case kArrayType:
6c5f2c01 sago007 2017-03-15 17:56 789
                if (t->index == kPointerInvalidIndex || t->index >= v->Size())
6c5f2c01 sago007 2017-03-15 17:56 790
                    return false;
6c5f2c01 sago007 2017-03-15 17:56 791
                v = &((*v)[t->index]);
6c5f2c01 sago007 2017-03-15 17:56 792
                break;
6c5f2c01 sago007 2017-03-15 17:56 793
            default:
6c5f2c01 sago007 2017-03-15 17:56 794
                return false;
6c5f2c01 sago007 2017-03-15 17:56 795
            }
6c5f2c01 sago007 2017-03-15 17:56 796
        }
6c5f2c01 sago007 2017-03-15 17:56 797
6c5f2c01 sago007 2017-03-15 17:56 798
        switch (v->GetType()) {
6c5f2c01 sago007 2017-03-15 17:56 799
        case kObjectType:
6c5f2c01 sago007 2017-03-15 17:56 800
            return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
6c5f2c01 sago007 2017-03-15 17:56 801
        case kArrayType:
6c5f2c01 sago007 2017-03-15 17:56 802
            if (last->index == kPointerInvalidIndex || last->index >= v->Size())
6c5f2c01 sago007 2017-03-15 17:56 803
                return false;
6c5f2c01 sago007 2017-03-15 17:56 804
            v->Erase(v->Begin() + last->index);
6c5f2c01 sago007 2017-03-15 17:56 805
            return true;
6c5f2c01 sago007 2017-03-15 17:56 806
        default:
6c5f2c01 sago007 2017-03-15 17:56 807
            return false;
6c5f2c01 sago007 2017-03-15 17:56 808
        }
6c5f2c01 sago007 2017-03-15 17:56 809
    }
6c5f2c01 sago007 2017-03-15 17:56 810
6c5f2c01 sago007 2017-03-15 17:56 811
private:
6c5f2c01 sago007 2017-03-15 17:56 812
    //! Clone the content from rhs to this.
6c5f2c01 sago007 2017-03-15 17:56 813
    /*!
6c5f2c01 sago007 2017-03-15 17:56 814
        \param rhs Source pointer.
6c5f2c01 sago007 2017-03-15 17:56 815
        \param extraToken Extra tokens to be allocated.
6c5f2c01 sago007 2017-03-15 17:56 816
        \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated.
6c5f2c01 sago007 2017-03-15 17:56 817
        \return Start of non-occupied name buffer, for storing extra names.
6c5f2c01 sago007 2017-03-15 17:56 818
    */
6c5f2c01 sago007 2017-03-15 17:56 819
    Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
6c5f2c01 sago007 2017-03-15 17:56 820
        if (!allocator_) // allocator is independently owned.
8f94a7f5 sago007 2020-05-10 10:26 821
            ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator)();
6c5f2c01 sago007 2017-03-15 17:56 822
6c5f2c01 sago007 2017-03-15 17:56 823
        size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
6c5f2c01 sago007 2017-03-15 17:56 824
        for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
6c5f2c01 sago007 2017-03-15 17:56 825
            nameBufferSize += t->length;
6c5f2c01 sago007 2017-03-15 17:56 826
6c5f2c01 sago007 2017-03-15 17:56 827
        tokenCount_ = rhs.tokenCount_ + extraToken;
6c5f2c01 sago007 2017-03-15 17:56 828
        tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
6c5f2c01 sago007 2017-03-15 17:56 829
        nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
6c5f2c01 sago007 2017-03-15 17:56 830
        if (rhs.tokenCount_ > 0) {
6c5f2c01 sago007 2017-03-15 17:56 831
            std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
6c5f2c01 sago007 2017-03-15 17:56 832
        }
6c5f2c01 sago007 2017-03-15 17:56 833
        if (nameBufferSize > 0) {
6c5f2c01 sago007 2017-03-15 17:56 834
            std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
6c5f2c01 sago007 2017-03-15 17:56 835
        }
6c5f2c01 sago007 2017-03-15 17:56 836
6c5f2c01 sago007 2017-03-15 17:56 837
        // Adjust pointers to name buffer
6c5f2c01 sago007 2017-03-15 17:56 838
        std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
6c5f2c01 sago007 2017-03-15 17:56 839
        for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
6c5f2c01 sago007 2017-03-15 17:56 840
            t->name += diff;
6c5f2c01 sago007 2017-03-15 17:56 841
6c5f2c01 sago007 2017-03-15 17:56 842
        return nameBuffer_ + nameBufferSize;
6c5f2c01 sago007 2017-03-15 17:56 843
    }
6c5f2c01 sago007 2017-03-15 17:56 844
6c5f2c01 sago007 2017-03-15 17:56 845
    //! Check whether a character should be percent-encoded.
6c5f2c01 sago007 2017-03-15 17:56 846
    /*!
6c5f2c01 sago007 2017-03-15 17:56 847
        According to RFC 3986 2.3 Unreserved Characters.
6c5f2c01 sago007 2017-03-15 17:56 848
        \param c The character (code unit) to be tested.
6c5f2c01 sago007 2017-03-15 17:56 849
    */
6c5f2c01 sago007 2017-03-15 17:56 850
    bool NeedPercentEncode(Ch c) const {
6c5f2c01 sago007 2017-03-15 17:56 851
        return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
6c5f2c01 sago007 2017-03-15 17:56 852
    }
6c5f2c01 sago007 2017-03-15 17:56 853
6c5f2c01 sago007 2017-03-15 17:56 854
    //! Parse a JSON String or its URI fragment representation into tokens.
6c5f2c01 sago007 2017-03-15 17:56 855
#ifndef __clang__ // -Wdocumentation
6c5f2c01 sago007 2017-03-15 17:56 856
    /*!
6c5f2c01 sago007 2017-03-15 17:56 857
        \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated.
6c5f2c01 sago007 2017-03-15 17:56 858
        \param length Length of the source string.
6c5f2c01 sago007 2017-03-15 17:56 859
        \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped.
6c5f2c01 sago007 2017-03-15 17:56 860
    */
6c5f2c01 sago007 2017-03-15 17:56 861
#endif
6c5f2c01 sago007 2017-03-15 17:56 862
    void Parse(const Ch* source, size_t length) {
6c5f2c01 sago007 2017-03-15 17:56 863
        CEREAL_RAPIDJSON_ASSERT(source != NULL);
6c5f2c01 sago007 2017-03-15 17:56 864
        CEREAL_RAPIDJSON_ASSERT(nameBuffer_ == 0);
6c5f2c01 sago007 2017-03-15 17:56 865
        CEREAL_RAPIDJSON_ASSERT(tokens_ == 0);
6c5f2c01 sago007 2017-03-15 17:56 866
6c5f2c01 sago007 2017-03-15 17:56 867
        // Create own allocator if user did not supply.
6c5f2c01 sago007 2017-03-15 17:56 868
        if (!allocator_)
8f94a7f5 sago007 2020-05-10 10:26 869
            ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator)();
6c5f2c01 sago007 2017-03-15 17:56 870
6c5f2c01 sago007 2017-03-15 17:56 871
        // Count number of '/' as tokenCount
6c5f2c01 sago007 2017-03-15 17:56 872
        tokenCount_ = 0;
6c5f2c01 sago007 2017-03-15 17:56 873
        for (const Ch* s = source; s != source + length; s++) 
6c5f2c01 sago007 2017-03-15 17:56 874
            if (*s == '/')
6c5f2c01 sago007 2017-03-15 17:56 875
                tokenCount_++;
6c5f2c01 sago007 2017-03-15 17:56 876
6c5f2c01 sago007 2017-03-15 17:56 877
        Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
6c5f2c01 sago007 2017-03-15 17:56 878
        Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
6c5f2c01 sago007 2017-03-15 17:56 879
        size_t i = 0;
6c5f2c01 sago007 2017-03-15 17:56 880
6c5f2c01 sago007 2017-03-15 17:56 881
        // Detect if it is a URI fragment
6c5f2c01 sago007 2017-03-15 17:56 882
        bool uriFragment = false;
6c5f2c01 sago007 2017-03-15 17:56 883
        if (source[i] == '#') {
6c5f2c01 sago007 2017-03-15 17:56 884
            uriFragment = true;
6c5f2c01 sago007 2017-03-15 17:56 885
            i++;
6c5f2c01 sago007 2017-03-15 17:56 886
        }
6c5f2c01 sago007 2017-03-15 17:56 887
6c5f2c01 sago007 2017-03-15 17:56 888
        if (i != length && source[i] != '/') {
6c5f2c01 sago007 2017-03-15 17:56 889
            parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus;
6c5f2c01 sago007 2017-03-15 17:56 890
            goto error;
6c5f2c01 sago007 2017-03-15 17:56 891
        }
6c5f2c01 sago007 2017-03-15 17:56 892
6c5f2c01 sago007 2017-03-15 17:56 893
        while (i < length) {
6c5f2c01 sago007 2017-03-15 17:56 894
            CEREAL_RAPIDJSON_ASSERT(source[i] == '/');
6c5f2c01 sago007 2017-03-15 17:56 895
            i++; // consumes '/'
6c5f2c01 sago007 2017-03-15 17:56 896
6c5f2c01 sago007 2017-03-15 17:56 897
            token->name = name;
6c5f2c01 sago007 2017-03-15 17:56 898
            bool isNumber = true;
6c5f2c01 sago007 2017-03-15 17:56 899
6c5f2c01 sago007 2017-03-15 17:56 900
            while (i < length && source[i] != '/') {
6c5f2c01 sago007 2017-03-15 17:56 901
                Ch c = source[i];
6c5f2c01 sago007 2017-03-15 17:56 902
                if (uriFragment) {
6c5f2c01 sago007 2017-03-15 17:56 903
                    // Decoding percent-encoding for URI fragment
6c5f2c01 sago007 2017-03-15 17:56 904
                    if (c == '%') {
6c5f2c01 sago007 2017-03-15 17:56 905
                        PercentDecodeStream is(&source[i], source + length);
6c5f2c01 sago007 2017-03-15 17:56 906
                        GenericInsituStringStream<EncodingType> os(name);
6c5f2c01 sago007 2017-03-15 17:56 907
                        Ch* begin = os.PutBegin();
6c5f2c01 sago007 2017-03-15 17:56 908
                        if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
6c5f2c01 sago007 2017-03-15 17:56 909
                            parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding;
6c5f2c01 sago007 2017-03-15 17:56 910
                            goto error;
6c5f2c01 sago007 2017-03-15 17:56 911
                        }
6c5f2c01 sago007 2017-03-15 17:56 912
                        size_t len = os.PutEnd(begin);
6c5f2c01 sago007 2017-03-15 17:56 913
                        i += is.Tell() - 1;
6c5f2c01 sago007 2017-03-15 17:56 914
                        if (len == 1)
6c5f2c01 sago007 2017-03-15 17:56 915
                            c = *name;
6c5f2c01 sago007 2017-03-15 17:56 916
                        else {
6c5f2c01 sago007 2017-03-15 17:56 917
                            name += len;
6c5f2c01 sago007 2017-03-15 17:56 918
                            isNumber = false;
6c5f2c01 sago007 2017-03-15 17:56 919
                            i++;
6c5f2c01 sago007 2017-03-15 17:56 920
                            continue;
6c5f2c01 sago007 2017-03-15 17:56 921
                        }
6c5f2c01 sago007 2017-03-15 17:56 922
                    }
6c5f2c01 sago007 2017-03-15 17:56 923
                    else if (NeedPercentEncode(c)) {
6c5f2c01 sago007 2017-03-15 17:56 924
                        parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode;
6c5f2c01 sago007 2017-03-15 17:56 925
                        goto error;
6c5f2c01 sago007 2017-03-15 17:56 926
                    }
6c5f2c01 sago007 2017-03-15 17:56 927
                }
6c5f2c01 sago007 2017-03-15 17:56 928
6c5f2c01 sago007 2017-03-15 17:56 929
                i++;
6c5f2c01 sago007 2017-03-15 17:56 930
                
6c5f2c01 sago007 2017-03-15 17:56 931
                // Escaping "~0" -> '~', "~1" -> '/'
6c5f2c01 sago007 2017-03-15 17:56 932
                if (c == '~') {
6c5f2c01 sago007 2017-03-15 17:56 933
                    if (i < length) {
6c5f2c01 sago007 2017-03-15 17:56 934
                        c = source[i];
6c5f2c01 sago007 2017-03-15 17:56 935
                        if (c == '0')       c = '~';
6c5f2c01 sago007 2017-03-15 17:56 936
                        else if (c == '1')  c = '/';
6c5f2c01 sago007 2017-03-15 17:56 937
                        else {
6c5f2c01 sago007 2017-03-15 17:56 938
                            parseErrorCode_ = kPointerParseErrorInvalidEscape;
6c5f2c01 sago007 2017-03-15 17:56 939
                            goto error;
6c5f2c01 sago007 2017-03-15 17:56 940
                        }
6c5f2c01 sago007 2017-03-15 17:56 941
                        i++;
6c5f2c01 sago007 2017-03-15 17:56 942
                    }
6c5f2c01 sago007 2017-03-15 17:56 943
                    else {
6c5f2c01 sago007 2017-03-15 17:56 944
                        parseErrorCode_ = kPointerParseErrorInvalidEscape;
6c5f2c01 sago007 2017-03-15 17:56 945
                        goto error;
6c5f2c01 sago007 2017-03-15 17:56 946
                    }
6c5f2c01 sago007 2017-03-15 17:56 947
                }
6c5f2c01 sago007 2017-03-15 17:56 948
6c5f2c01 sago007 2017-03-15 17:56 949
                // First check for index: all of characters are digit
6c5f2c01 sago007 2017-03-15 17:56 950
                if (c < '0' || c > '9')
6c5f2c01 sago007 2017-03-15 17:56 951
                    isNumber = false;
6c5f2c01 sago007 2017-03-15 17:56 952
6c5f2c01 sago007 2017-03-15 17:56 953
                *name++ = c;
6c5f2c01 sago007 2017-03-15 17:56 954
            }
6c5f2c01 sago007 2017-03-15 17:56 955
            token->length = static_cast<SizeType>(name - token->name);
6c5f2c01 sago007 2017-03-15 17:56 956
            if (token->length == 0)
6c5f2c01 sago007 2017-03-15 17:56 957
                isNumber = false;
6c5f2c01 sago007 2017-03-15 17:56 958
            *name++ = '\0'; // Null terminator
6c5f2c01 sago007 2017-03-15 17:56 959
6c5f2c01 sago007 2017-03-15 17:56 960
            // Second check for index: more than one digit cannot have leading zero
6c5f2c01 sago007 2017-03-15 17:56 961
            if (isNumber && token->length > 1 && token->name[0] == '0')
6c5f2c01 sago007 2017-03-15 17:56 962
                isNumber = false;
6c5f2c01 sago007 2017-03-15 17:56 963
6c5f2c01 sago007 2017-03-15 17:56 964
            // String to SizeType conversion
6c5f2c01 sago007 2017-03-15 17:56 965
            SizeType n = 0;
6c5f2c01 sago007 2017-03-15 17:56 966
            if (isNumber) {
6c5f2c01 sago007 2017-03-15 17:56 967
                for (size_t j = 0; j < token->length; j++) {
6c5f2c01 sago007 2017-03-15 17:56 968
                    SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
6c5f2c01 sago007 2017-03-15 17:56 969
                    if (m < n) {   // overflow detection
6c5f2c01 sago007 2017-03-15 17:56 970
                        isNumber = false;
6c5f2c01 sago007 2017-03-15 17:56 971
                        break;
6c5f2c01 sago007 2017-03-15 17:56 972
                    }
6c5f2c01 sago007 2017-03-15 17:56 973
                    n = m;
6c5f2c01 sago007 2017-03-15 17:56 974
                }
6c5f2c01 sago007 2017-03-15 17:56 975
            }
6c5f2c01 sago007 2017-03-15 17:56 976
6c5f2c01 sago007 2017-03-15 17:56 977
            token->index = isNumber ? n : kPointerInvalidIndex;
6c5f2c01 sago007 2017-03-15 17:56 978
            token++;
6c5f2c01 sago007 2017-03-15 17:56 979
        }
6c5f2c01 sago007 2017-03-15 17:56 980
6c5f2c01 sago007 2017-03-15 17:56 981
        CEREAL_RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
6c5f2c01 sago007 2017-03-15 17:56 982
        parseErrorCode_ = kPointerParseErrorNone;
6c5f2c01 sago007 2017-03-15 17:56 983
        return;
6c5f2c01 sago007 2017-03-15 17:56 984
6c5f2c01 sago007 2017-03-15 17:56 985
    error:
6c5f2c01 sago007 2017-03-15 17:56 986
        Allocator::Free(tokens_);
6c5f2c01 sago007 2017-03-15 17:56 987
        nameBuffer_ = 0;
6c5f2c01 sago007 2017-03-15 17:56 988
        tokens_ = 0;
6c5f2c01 sago007 2017-03-15 17:56 989
        tokenCount_ = 0;
6c5f2c01 sago007 2017-03-15 17:56 990
        parseErrorOffset_ = i;
6c5f2c01 sago007 2017-03-15 17:56 991
        return;
6c5f2c01 sago007 2017-03-15 17:56 992
    }
6c5f2c01 sago007 2017-03-15 17:56 993
6c5f2c01 sago007 2017-03-15 17:56 994
    //! Stringify to string or URI fragment representation.
6c5f2c01 sago007 2017-03-15 17:56 995
    /*!
6c5f2c01 sago007 2017-03-15 17:56 996
        \tparam uriFragment True for stringifying to URI fragment representation. False for string representation.
6c5f2c01 sago007 2017-03-15 17:56 997
        \tparam OutputStream type of output stream.
6c5f2c01 sago007 2017-03-15 17:56 998
        \param os The output stream.
6c5f2c01 sago007 2017-03-15 17:56 999
    */
6c5f2c01 sago007 2017-03-15 17:56 1000
    template<bool uriFragment, typename OutputStream>
6c5f2c01 sago007 2017-03-15 17:56 1001
    bool Stringify(OutputStream& os) const {
6c5f2c01 sago007 2017-03-15 17:56 1002
        CEREAL_RAPIDJSON_ASSERT(IsValid());
6c5f2c01 sago007 2017-03-15 17:56 1003
6c5f2c01 sago007 2017-03-15 17:56 1004
        if (uriFragment)
6c5f2c01 sago007 2017-03-15 17:56 1005
            os.Put('#');
6c5f2c01 sago007 2017-03-15 17:56 1006
6c5f2c01 sago007 2017-03-15 17:56 1007
        for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
6c5f2c01 sago007 2017-03-15 17:56 1008
            os.Put('/');
6c5f2c01 sago007 2017-03-15 17:56 1009
            for (size_t j = 0; j < t->length; j++) {
6c5f2c01 sago007 2017-03-15 17:56 1010
                Ch c = t->name[j];
6c5f2c01 sago007 2017-03-15 17:56 1011
                if (c == '~') {
6c5f2c01 sago007 2017-03-15 17:56 1012
                    os.Put('~');
6c5f2c01 sago007 2017-03-15 17:56 1013
                    os.Put('0');
6c5f2c01 sago007 2017-03-15 17:56 1014
                }
6c5f2c01 sago007 2017-03-15 17:56 1015
                else if (c == '/') {
6c5f2c01 sago007 2017-03-15 17:56 1016
                    os.Put('~');
6c5f2c01 sago007 2017-03-15 17:56 1017
                    os.Put('1');
6c5f2c01 sago007 2017-03-15 17:56 1018
                }
6c5f2c01 sago007 2017-03-15 17:56 1019
                else if (uriFragment && NeedPercentEncode(c)) { 
6c5f2c01 sago007 2017-03-15 17:56 1020
                    // Transcode to UTF8 sequence
6c5f2c01 sago007 2017-03-15 17:56 1021
                    GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
6c5f2c01 sago007 2017-03-15 17:56 1022
                    PercentEncodeStream<OutputStream> target(os);
6c5f2c01 sago007 2017-03-15 17:56 1023
                    if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
6c5f2c01 sago007 2017-03-15 17:56 1024
                        return false;
6c5f2c01 sago007 2017-03-15 17:56 1025
                    j += source.Tell() - 1;
6c5f2c01 sago007 2017-03-15 17:56 1026
                }
6c5f2c01 sago007 2017-03-15 17:56 1027
                else
6c5f2c01 sago007 2017-03-15 17:56 1028
                    os.Put(c);
6c5f2c01 sago007 2017-03-15 17:56 1029
            }
6c5f2c01 sago007 2017-03-15 17:56 1030
        }
6c5f2c01 sago007 2017-03-15 17:56 1031
        return true;
6c5f2c01 sago007 2017-03-15 17:56 1032
    }
6c5f2c01 sago007 2017-03-15 17:56 1033
6c5f2c01 sago007 2017-03-15 17:56 1034
    //! A helper stream for decoding a percent-encoded sequence into code unit.
6c5f2c01 sago007 2017-03-15 17:56 1035
    /*!
6c5f2c01 sago007 2017-03-15 17:56 1036
        This stream decodes %XY triplet into code unit (0-255).
6c5f2c01 sago007 2017-03-15 17:56 1037
        If it encounters invalid characters, it sets output code unit as 0 and 
6c5f2c01 sago007 2017-03-15 17:56 1038
        mark invalid, and to be checked by IsValid().
6c5f2c01 sago007 2017-03-15 17:56 1039
    */
6c5f2c01 sago007 2017-03-15 17:56 1040
    class PercentDecodeStream {
6c5f2c01 sago007 2017-03-15 17:56 1041
    public:
6c5f2c01 sago007 2017-03-15 17:56 1042
        typedef typename ValueType::Ch Ch;
6c5f2c01 sago007 2017-03-15 17:56 1043
6c5f2c01 sago007 2017-03-15 17:56 1044
        //! Constructor
6c5f2c01 sago007 2017-03-15 17:56 1045
        /*!
6c5f2c01 sago007 2017-03-15 17:56 1046
            \param source Start of the stream
6c5f2c01 sago007 2017-03-15 17:56 1047
            \param end Past-the-end of the stream.
6c5f2c01 sago007 2017-03-15 17:56 1048
        */
6c5f2c01 sago007 2017-03-15 17:56 1049
        PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
6c5f2c01 sago007 2017-03-15 17:56 1050
6c5f2c01 sago007 2017-03-15 17:56 1051
        Ch Take() {
6c5f2c01 sago007 2017-03-15 17:56 1052
            if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
6c5f2c01 sago007 2017-03-15 17:56 1053
                valid_ = false;
6c5f2c01 sago007 2017-03-15 17:56 1054
                return 0;
6c5f2c01 sago007 2017-03-15 17:56 1055
            }
6c5f2c01 sago007 2017-03-15 17:56 1056
            src_++;
6c5f2c01 sago007 2017-03-15 17:56 1057
            Ch c = 0;
6c5f2c01 sago007 2017-03-15 17:56 1058
            for (int j = 0; j < 2; j++) {
6c5f2c01 sago007 2017-03-15 17:56 1059
                c = static_cast<Ch>(c << 4);
6c5f2c01 sago007 2017-03-15 17:56 1060
                Ch h = *src_;
6c5f2c01 sago007 2017-03-15 17:56 1061
                if      (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
6c5f2c01 sago007 2017-03-15 17:56 1062
                else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
6c5f2c01 sago007 2017-03-15 17:56 1063
                else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
6c5f2c01 sago007 2017-03-15 17:56 1064
                else {
6c5f2c01 sago007 2017-03-15 17:56 1065
                    valid_ = false;
6c5f2c01 sago007 2017-03-15 17:56 1066
                    return 0;
6c5f2c01 sago007 2017-03-15 17:56 1067
                }
6c5f2c01 sago007 2017-03-15 17:56 1068
                src_++;
6c5f2c01 sago007 2017-03-15 17:56 1069
            }
6c5f2c01 sago007 2017-03-15 17:56 1070
            return c;
6c5f2c01 sago007 2017-03-15 17:56 1071
        }
6c5f2c01 sago007 2017-03-15 17:56 1072
6c5f2c01 sago007 2017-03-15 17:56 1073
        size_t Tell() const { return static_cast<size_t>(src_ - head_); }
6c5f2c01 sago007 2017-03-15 17:56 1074
        bool IsValid() const { return valid_; }
6c5f2c01 sago007 2017-03-15 17:56 1075
6c5f2c01 sago007 2017-03-15 17:56 1076
    private:
6c5f2c01 sago007 2017-03-15 17:56 1077
        const Ch* src_;     //!< Current read position.
6c5f2c01 sago007 2017-03-15 17:56 1078
        const Ch* head_;    //!< Original head of the string.
6c5f2c01 sago007 2017-03-15 17:56 1079
        const Ch* end_;     //!< Past-the-end position.
6c5f2c01 sago007 2017-03-15 17:56 1080
        bool valid_;        //!< Whether the parsing is valid.
6c5f2c01 sago007 2017-03-15 17:56 1081
    };
6c5f2c01 sago007 2017-03-15 17:56 1082
6c5f2c01 sago007 2017-03-15 17:56 1083
    //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
6c5f2c01 sago007 2017-03-15 17:56 1084
    template <typename OutputStream>
6c5f2c01 sago007 2017-03-15 17:56 1085
    class PercentEncodeStream {
6c5f2c01 sago007 2017-03-15 17:56 1086
    public:
6c5f2c01 sago007 2017-03-15 17:56 1087
        PercentEncodeStream(OutputStream& os) : os_(os) {}
6c5f2c01 sago007 2017-03-15 17:56 1088
        void Put(char c) { // UTF-8 must be byte
6c5f2c01 sago007 2017-03-15 17:56 1089
            unsigned char u = static_cast<unsigned char>(c);
6c5f2c01 sago007 2017-03-15 17:56 1090
            static const char 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 1091
            os_.Put('%');
8f94a7f5 sago007 2020-05-10 10:26 1092
            os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
8f94a7f5 sago007 2020-05-10 10:26 1093
            os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
6c5f2c01 sago007 2017-03-15 17:56 1094
        }
6c5f2c01 sago007 2017-03-15 17:56 1095
    private:
6c5f2c01 sago007 2017-03-15 17:56 1096
        OutputStream& os_;
6c5f2c01 sago007 2017-03-15 17:56 1097
    };
6c5f2c01 sago007 2017-03-15 17:56 1098
6c5f2c01 sago007 2017-03-15 17:56 1099
    Allocator* allocator_;                  //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
6c5f2c01 sago007 2017-03-15 17:56 1100
    Allocator* ownAllocator_;               //!< Allocator owned by this Pointer.
6c5f2c01 sago007 2017-03-15 17:56 1101
    Ch* nameBuffer_;                        //!< A buffer containing all names in tokens.
6c5f2c01 sago007 2017-03-15 17:56 1102
    Token* tokens_;                         //!< A list of tokens.
6c5f2c01 sago007 2017-03-15 17:56 1103
    size_t tokenCount_;                     //!< Number of tokens in tokens_.
6c5f2c01 sago007 2017-03-15 17:56 1104
    size_t parseErrorOffset_;               //!< Offset in code unit when parsing fail.
6c5f2c01 sago007 2017-03-15 17:56 1105
    PointerParseErrorCode parseErrorCode_;  //!< Parsing error code.
6c5f2c01 sago007 2017-03-15 17:56 1106
};
6c5f2c01 sago007 2017-03-15 17:56 1107
6c5f2c01 sago007 2017-03-15 17:56 1108
//! GenericPointer for Value (UTF-8, default allocator).
6c5f2c01 sago007 2017-03-15 17:56 1109
typedef GenericPointer<Value> Pointer;
6c5f2c01 sago007 2017-03-15 17:56 1110
6c5f2c01 sago007 2017-03-15 17:56 1111
//!@name Helper functions for GenericPointer
6c5f2c01 sago007 2017-03-15 17:56 1112
//@{
6c5f2c01 sago007 2017-03-15 17:56 1113
6c5f2c01 sago007 2017-03-15 17:56 1114
//////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 1115
6c5f2c01 sago007 2017-03-15 17:56 1116
template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 1117
typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1118
    return pointer.Create(root, a);
6c5f2c01 sago007 2017-03-15 17:56 1119
}
6c5f2c01 sago007 2017-03-15 17:56 1120
6c5f2c01 sago007 2017-03-15 17:56 1121
template <typename T, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1122
typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1123
    return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
6c5f2c01 sago007 2017-03-15 17:56 1124
}
6c5f2c01 sago007 2017-03-15 17:56 1125
6c5f2c01 sago007 2017-03-15 17:56 1126
// No allocator parameter
6c5f2c01 sago007 2017-03-15 17:56 1127
6c5f2c01 sago007 2017-03-15 17:56 1128
template <typename DocumentType>
6c5f2c01 sago007 2017-03-15 17:56 1129
typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
6c5f2c01 sago007 2017-03-15 17:56 1130
    return pointer.Create(document);
6c5f2c01 sago007 2017-03-15 17:56 1131
}
6c5f2c01 sago007 2017-03-15 17:56 1132
6c5f2c01 sago007 2017-03-15 17:56 1133
template <typename DocumentType, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1134
typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
6c5f2c01 sago007 2017-03-15 17:56 1135
    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
6c5f2c01 sago007 2017-03-15 17:56 1136
}
6c5f2c01 sago007 2017-03-15 17:56 1137
6c5f2c01 sago007 2017-03-15 17:56 1138
//////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 1139
6c5f2c01 sago007 2017-03-15 17:56 1140
template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 1141
typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
6c5f2c01 sago007 2017-03-15 17:56 1142
    return pointer.Get(root, unresolvedTokenIndex);
6c5f2c01 sago007 2017-03-15 17:56 1143
}
6c5f2c01 sago007 2017-03-15 17:56 1144
6c5f2c01 sago007 2017-03-15 17:56 1145
template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 1146
const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
6c5f2c01 sago007 2017-03-15 17:56 1147
    return pointer.Get(root, unresolvedTokenIndex);
6c5f2c01 sago007 2017-03-15 17:56 1148
}
6c5f2c01 sago007 2017-03-15 17:56 1149
6c5f2c01 sago007 2017-03-15 17:56 1150
template <typename T, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1151
typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
6c5f2c01 sago007 2017-03-15 17:56 1152
    return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
6c5f2c01 sago007 2017-03-15 17:56 1153
}
6c5f2c01 sago007 2017-03-15 17:56 1154
6c5f2c01 sago007 2017-03-15 17:56 1155
template <typename T, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1156
const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
6c5f2c01 sago007 2017-03-15 17:56 1157
    return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
6c5f2c01 sago007 2017-03-15 17:56 1158
}
6c5f2c01 sago007 2017-03-15 17:56 1159
6c5f2c01 sago007 2017-03-15 17:56 1160
//////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 1161
6c5f2c01 sago007 2017-03-15 17:56 1162
template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 1163
typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1164
    return pointer.GetWithDefault(root, defaultValue, a);
6c5f2c01 sago007 2017-03-15 17:56 1165
}
6c5f2c01 sago007 2017-03-15 17:56 1166
6c5f2c01 sago007 2017-03-15 17:56 1167
template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 1168
typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1169
    return pointer.GetWithDefault(root, defaultValue, a);
6c5f2c01 sago007 2017-03-15 17:56 1170
}
6c5f2c01 sago007 2017-03-15 17:56 1171
6c5f2c01 sago007 2017-03-15 17:56 1172
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 1173
template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 1174
typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1175
    return pointer.GetWithDefault(root, defaultValue, a);
6c5f2c01 sago007 2017-03-15 17:56 1176
}
6c5f2c01 sago007 2017-03-15 17:56 1177
#endif
6c5f2c01 sago007 2017-03-15 17:56 1178
6c5f2c01 sago007 2017-03-15 17:56 1179
template <typename T, typename T2>
6c5f2c01 sago007 2017-03-15 17:56 1180
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
6c5f2c01 sago007 2017-03-15 17:56 1181
GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1182
    return pointer.GetWithDefault(root, defaultValue, a);
6c5f2c01 sago007 2017-03-15 17:56 1183
}
6c5f2c01 sago007 2017-03-15 17:56 1184
6c5f2c01 sago007 2017-03-15 17:56 1185
template <typename T, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1186
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1187
    return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
6c5f2c01 sago007 2017-03-15 17:56 1188
}
6c5f2c01 sago007 2017-03-15 17:56 1189
6c5f2c01 sago007 2017-03-15 17:56 1190
template <typename T, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1191
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1192
    return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
6c5f2c01 sago007 2017-03-15 17:56 1193
}
6c5f2c01 sago007 2017-03-15 17:56 1194
6c5f2c01 sago007 2017-03-15 17:56 1195
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 1196
template <typename T, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1197
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1198
    return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
6c5f2c01 sago007 2017-03-15 17:56 1199
}
6c5f2c01 sago007 2017-03-15 17:56 1200
#endif
6c5f2c01 sago007 2017-03-15 17:56 1201
6c5f2c01 sago007 2017-03-15 17:56 1202
template <typename T, typename CharType, size_t N, typename T2>
6c5f2c01 sago007 2017-03-15 17:56 1203
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
6c5f2c01 sago007 2017-03-15 17:56 1204
GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1205
    return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
6c5f2c01 sago007 2017-03-15 17:56 1206
}
6c5f2c01 sago007 2017-03-15 17:56 1207
6c5f2c01 sago007 2017-03-15 17:56 1208
// No allocator parameter
6c5f2c01 sago007 2017-03-15 17:56 1209
6c5f2c01 sago007 2017-03-15 17:56 1210
template <typename DocumentType>
6c5f2c01 sago007 2017-03-15 17:56 1211
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
6c5f2c01 sago007 2017-03-15 17:56 1212
    return pointer.GetWithDefault(document, defaultValue);
6c5f2c01 sago007 2017-03-15 17:56 1213
}
6c5f2c01 sago007 2017-03-15 17:56 1214
6c5f2c01 sago007 2017-03-15 17:56 1215
template <typename DocumentType>
6c5f2c01 sago007 2017-03-15 17:56 1216
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
6c5f2c01 sago007 2017-03-15 17:56 1217
    return pointer.GetWithDefault(document, defaultValue);
6c5f2c01 sago007 2017-03-15 17:56 1218
}
6c5f2c01 sago007 2017-03-15 17:56 1219
6c5f2c01 sago007 2017-03-15 17:56 1220
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 1221
template <typename DocumentType>
6c5f2c01 sago007 2017-03-15 17:56 1222
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
6c5f2c01 sago007 2017-03-15 17:56 1223
    return pointer.GetWithDefault(document, defaultValue);
6c5f2c01 sago007 2017-03-15 17:56 1224
}
6c5f2c01 sago007 2017-03-15 17:56 1225
#endif
6c5f2c01 sago007 2017-03-15 17:56 1226
6c5f2c01 sago007 2017-03-15 17:56 1227
template <typename DocumentType, typename T2>
6c5f2c01 sago007 2017-03-15 17:56 1228
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
6c5f2c01 sago007 2017-03-15 17:56 1229
GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
6c5f2c01 sago007 2017-03-15 17:56 1230
    return pointer.GetWithDefault(document, defaultValue);
6c5f2c01 sago007 2017-03-15 17:56 1231
}
6c5f2c01 sago007 2017-03-15 17:56 1232
6c5f2c01 sago007 2017-03-15 17:56 1233
template <typename DocumentType, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1234
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
6c5f2c01 sago007 2017-03-15 17:56 1235
    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
6c5f2c01 sago007 2017-03-15 17:56 1236
}
6c5f2c01 sago007 2017-03-15 17:56 1237
6c5f2c01 sago007 2017-03-15 17:56 1238
template <typename DocumentType, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1239
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
6c5f2c01 sago007 2017-03-15 17:56 1240
    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
6c5f2c01 sago007 2017-03-15 17:56 1241
}
6c5f2c01 sago007 2017-03-15 17:56 1242
6c5f2c01 sago007 2017-03-15 17:56 1243
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 1244
template <typename DocumentType, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1245
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
6c5f2c01 sago007 2017-03-15 17:56 1246
    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
6c5f2c01 sago007 2017-03-15 17:56 1247
}
6c5f2c01 sago007 2017-03-15 17:56 1248
#endif
6c5f2c01 sago007 2017-03-15 17:56 1249
6c5f2c01 sago007 2017-03-15 17:56 1250
template <typename DocumentType, typename CharType, size_t N, typename T2>
6c5f2c01 sago007 2017-03-15 17:56 1251
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
6c5f2c01 sago007 2017-03-15 17:56 1252
GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
6c5f2c01 sago007 2017-03-15 17:56 1253
    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
6c5f2c01 sago007 2017-03-15 17:56 1254
}
6c5f2c01 sago007 2017-03-15 17:56 1255
6c5f2c01 sago007 2017-03-15 17:56 1256
//////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 1257
6c5f2c01 sago007 2017-03-15 17:56 1258
template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 1259
typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1260
    return pointer.Set(root, value, a);
6c5f2c01 sago007 2017-03-15 17:56 1261
}
6c5f2c01 sago007 2017-03-15 17:56 1262
6c5f2c01 sago007 2017-03-15 17:56 1263
template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 1264
typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1265
    return pointer.Set(root, value, a);
6c5f2c01 sago007 2017-03-15 17:56 1266
}
6c5f2c01 sago007 2017-03-15 17:56 1267
6c5f2c01 sago007 2017-03-15 17:56 1268
template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 1269
typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1270
    return pointer.Set(root, value, a);
6c5f2c01 sago007 2017-03-15 17:56 1271
}
6c5f2c01 sago007 2017-03-15 17:56 1272
6c5f2c01 sago007 2017-03-15 17:56 1273
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 1274
template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 1275
typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1276
    return pointer.Set(root, value, a);
6c5f2c01 sago007 2017-03-15 17:56 1277
}
6c5f2c01 sago007 2017-03-15 17:56 1278
#endif
6c5f2c01 sago007 2017-03-15 17:56 1279
6c5f2c01 sago007 2017-03-15 17:56 1280
template <typename T, typename T2>
6c5f2c01 sago007 2017-03-15 17:56 1281
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
6c5f2c01 sago007 2017-03-15 17:56 1282
SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1283
    return pointer.Set(root, value, a);
6c5f2c01 sago007 2017-03-15 17:56 1284
}
6c5f2c01 sago007 2017-03-15 17:56 1285
6c5f2c01 sago007 2017-03-15 17:56 1286
template <typename T, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1287
typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1288
    return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
6c5f2c01 sago007 2017-03-15 17:56 1289
}
6c5f2c01 sago007 2017-03-15 17:56 1290
6c5f2c01 sago007 2017-03-15 17:56 1291
template <typename T, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1292
typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1293
    return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
6c5f2c01 sago007 2017-03-15 17:56 1294
}
6c5f2c01 sago007 2017-03-15 17:56 1295
6c5f2c01 sago007 2017-03-15 17:56 1296
template <typename T, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1297
typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1298
    return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
6c5f2c01 sago007 2017-03-15 17:56 1299
}
6c5f2c01 sago007 2017-03-15 17:56 1300
6c5f2c01 sago007 2017-03-15 17:56 1301
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 1302
template <typename T, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1303
typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1304
    return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
6c5f2c01 sago007 2017-03-15 17:56 1305
}
6c5f2c01 sago007 2017-03-15 17:56 1306
#endif
6c5f2c01 sago007 2017-03-15 17:56 1307
6c5f2c01 sago007 2017-03-15 17:56 1308
template <typename T, typename CharType, size_t N, typename T2>
6c5f2c01 sago007 2017-03-15 17:56 1309
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
6c5f2c01 sago007 2017-03-15 17:56 1310
SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1311
    return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
6c5f2c01 sago007 2017-03-15 17:56 1312
}
6c5f2c01 sago007 2017-03-15 17:56 1313
6c5f2c01 sago007 2017-03-15 17:56 1314
// No allocator parameter
6c5f2c01 sago007 2017-03-15 17:56 1315
6c5f2c01 sago007 2017-03-15 17:56 1316
template <typename DocumentType>
6c5f2c01 sago007 2017-03-15 17:56 1317
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
6c5f2c01 sago007 2017-03-15 17:56 1318
    return pointer.Set(document, value);
6c5f2c01 sago007 2017-03-15 17:56 1319
}
6c5f2c01 sago007 2017-03-15 17:56 1320
6c5f2c01 sago007 2017-03-15 17:56 1321
template <typename DocumentType>
6c5f2c01 sago007 2017-03-15 17:56 1322
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
6c5f2c01 sago007 2017-03-15 17:56 1323
    return pointer.Set(document, value);
6c5f2c01 sago007 2017-03-15 17:56 1324
}
6c5f2c01 sago007 2017-03-15 17:56 1325
6c5f2c01 sago007 2017-03-15 17:56 1326
template <typename DocumentType>
6c5f2c01 sago007 2017-03-15 17:56 1327
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
6c5f2c01 sago007 2017-03-15 17:56 1328
    return pointer.Set(document, value);
6c5f2c01 sago007 2017-03-15 17:56 1329
}
6c5f2c01 sago007 2017-03-15 17:56 1330
6c5f2c01 sago007 2017-03-15 17:56 1331
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 1332
template <typename DocumentType>
6c5f2c01 sago007 2017-03-15 17:56 1333
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
6c5f2c01 sago007 2017-03-15 17:56 1334
    return pointer.Set(document, value);
6c5f2c01 sago007 2017-03-15 17:56 1335
}
6c5f2c01 sago007 2017-03-15 17:56 1336
#endif
6c5f2c01 sago007 2017-03-15 17:56 1337
6c5f2c01 sago007 2017-03-15 17:56 1338
template <typename DocumentType, typename T2>
6c5f2c01 sago007 2017-03-15 17:56 1339
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
6c5f2c01 sago007 2017-03-15 17:56 1340
SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
6c5f2c01 sago007 2017-03-15 17:56 1341
    return pointer.Set(document, value);
6c5f2c01 sago007 2017-03-15 17:56 1342
}
6c5f2c01 sago007 2017-03-15 17:56 1343
6c5f2c01 sago007 2017-03-15 17:56 1344
template <typename DocumentType, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1345
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
6c5f2c01 sago007 2017-03-15 17:56 1346
    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
6c5f2c01 sago007 2017-03-15 17:56 1347
}
6c5f2c01 sago007 2017-03-15 17:56 1348
6c5f2c01 sago007 2017-03-15 17:56 1349
template <typename DocumentType, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1350
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
6c5f2c01 sago007 2017-03-15 17:56 1351
    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
6c5f2c01 sago007 2017-03-15 17:56 1352
}
6c5f2c01 sago007 2017-03-15 17:56 1353
6c5f2c01 sago007 2017-03-15 17:56 1354
template <typename DocumentType, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1355
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
6c5f2c01 sago007 2017-03-15 17:56 1356
    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
6c5f2c01 sago007 2017-03-15 17:56 1357
}
6c5f2c01 sago007 2017-03-15 17:56 1358
6c5f2c01 sago007 2017-03-15 17:56 1359
#if CEREAL_RAPIDJSON_HAS_STDSTRING
6c5f2c01 sago007 2017-03-15 17:56 1360
template <typename DocumentType, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1361
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
6c5f2c01 sago007 2017-03-15 17:56 1362
    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
6c5f2c01 sago007 2017-03-15 17:56 1363
}
6c5f2c01 sago007 2017-03-15 17:56 1364
#endif
6c5f2c01 sago007 2017-03-15 17:56 1365
6c5f2c01 sago007 2017-03-15 17:56 1366
template <typename DocumentType, typename CharType, size_t N, typename T2>
6c5f2c01 sago007 2017-03-15 17:56 1367
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
6c5f2c01 sago007 2017-03-15 17:56 1368
SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
6c5f2c01 sago007 2017-03-15 17:56 1369
    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
6c5f2c01 sago007 2017-03-15 17:56 1370
}
6c5f2c01 sago007 2017-03-15 17:56 1371
6c5f2c01 sago007 2017-03-15 17:56 1372
//////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 1373
6c5f2c01 sago007 2017-03-15 17:56 1374
template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 1375
typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1376
    return pointer.Swap(root, value, a);
6c5f2c01 sago007 2017-03-15 17:56 1377
}
6c5f2c01 sago007 2017-03-15 17:56 1378
6c5f2c01 sago007 2017-03-15 17:56 1379
template <typename T, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1380
typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
6c5f2c01 sago007 2017-03-15 17:56 1381
    return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
6c5f2c01 sago007 2017-03-15 17:56 1382
}
6c5f2c01 sago007 2017-03-15 17:56 1383
6c5f2c01 sago007 2017-03-15 17:56 1384
template <typename DocumentType>
6c5f2c01 sago007 2017-03-15 17:56 1385
typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
6c5f2c01 sago007 2017-03-15 17:56 1386
    return pointer.Swap(document, value);
6c5f2c01 sago007 2017-03-15 17:56 1387
}
6c5f2c01 sago007 2017-03-15 17:56 1388
6c5f2c01 sago007 2017-03-15 17:56 1389
template <typename DocumentType, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1390
typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
6c5f2c01 sago007 2017-03-15 17:56 1391
    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
6c5f2c01 sago007 2017-03-15 17:56 1392
}
6c5f2c01 sago007 2017-03-15 17:56 1393
6c5f2c01 sago007 2017-03-15 17:56 1394
//////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 1395
6c5f2c01 sago007 2017-03-15 17:56 1396
template <typename T>
6c5f2c01 sago007 2017-03-15 17:56 1397
bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
6c5f2c01 sago007 2017-03-15 17:56 1398
    return pointer.Erase(root);
6c5f2c01 sago007 2017-03-15 17:56 1399
}
6c5f2c01 sago007 2017-03-15 17:56 1400
6c5f2c01 sago007 2017-03-15 17:56 1401
template <typename T, typename CharType, size_t N>
6c5f2c01 sago007 2017-03-15 17:56 1402
bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
6c5f2c01 sago007 2017-03-15 17:56 1403
    return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
6c5f2c01 sago007 2017-03-15 17:56 1404
}
6c5f2c01 sago007 2017-03-15 17:56 1405
6c5f2c01 sago007 2017-03-15 17:56 1406
//@}
6c5f2c01 sago007 2017-03-15 17:56 1407
6c5f2c01 sago007 2017-03-15 17:56 1408
CEREAL_RAPIDJSON_NAMESPACE_END
6c5f2c01 sago007 2017-03-15 17:56 1409
8f94a7f5 sago007 2020-05-10 10:26 1410
#if defined(__clang__) || defined(_MSC_VER)
6c5f2c01 sago007 2017-03-15 17:56 1411
CEREAL_RAPIDJSON_DIAG_POP
6c5f2c01 sago007 2017-03-15 17:56 1412
#endif
6c5f2c01 sago007 2017-03-15 17:56 1413
6c5f2c01 sago007 2017-03-15 17:56 1414
#endif // CEREAL_RAPIDJSON_POINTER_H_
1970-01-01 00:00 1415