all repos — mgba @ 7ef0c5074c7064e0a3509d8d9ecd03061f1abf07

mGBA Game Boy Advance Emulator

src/third-party/discord-rpc/include/rapidjson/pointer.h (view raw)

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