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