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