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
21RAPIDJSON_NAMESPACE_BEGIN
22
23static 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*/
29enum 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*/
70template <typename ValueType, typename Allocator = CrtAllocator>
71class GenericPointer {
72public:
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
722private:
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).
1012typedef GenericPointer<Value> Pointer;
1013
1014//!@name Helper functions for GenericPointer
1015//@{
1016
1017//////////////////////////////////////////////////////////////////////////////
1018
1019template <typename T>
1020typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
1021    return pointer.Create(root, a);
1022}
1023
1024template <typename T, typename CharType, size_t N>
1025typename 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
1031template <typename DocumentType>
1032typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
1033    return pointer.Create(document);
1034}
1035
1036template <typename DocumentType, typename CharType, size_t N>
1037typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
1038    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
1039}
1040
1041//////////////////////////////////////////////////////////////////////////////
1042
1043template <typename T>
1044typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
1045    return pointer.Get(root);
1046}
1047
1048template <typename T>
1049const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer) {
1050    return pointer.Get(root);
1051}
1052
1053template <typename T, typename CharType, size_t N>
1054typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N]) {
1055    return GenericPointer<typename T::ValueType>(source, N - 1).Get(root);
1056}
1057
1058template <typename T, typename CharType, size_t N>
1059const 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
1065template <typename T>
1066typename 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
1070template <typename T>
1071typename 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
1076template <typename T>
1077typename 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
1082template <typename T, typename T2>
1083RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1084GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
1085    return pointer.GetWithDefault(root, defaultValue, a);
1086}
1087
1088template <typename T, typename CharType, size_t N>
1089typename 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
1093template <typename T, typename CharType, size_t N>
1094typename 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
1099template <typename T, typename CharType, size_t N>
1100typename 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
1105template <typename T, typename CharType, size_t N, typename T2>
1106RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1107GetValueByPointerWithDefault(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
1113template <typename DocumentType>
1114typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
1115    return pointer.GetWithDefault(document, defaultValue);
1116}
1117
1118template <typename DocumentType>
1119typename 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
1124template <typename DocumentType>
1125typename 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
1130template <typename DocumentType, typename T2>
1131RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1132GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
1133    return pointer.GetWithDefault(document, defaultValue);
1134}
1135
1136template <typename DocumentType, typename CharType, size_t N>
1137typename 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
1141template <typename DocumentType, typename CharType, size_t N>
1142typename 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
1147template <typename DocumentType, typename CharType, size_t N>
1148typename 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
1153template <typename DocumentType, typename CharType, size_t N, typename T2>
1154RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1155GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
1156    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1157}
1158
1159//////////////////////////////////////////////////////////////////////////////
1160
1161template <typename T>
1162typename 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
1166template <typename T>
1167typename 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
1171template <typename T>
1172typename 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
1177template <typename T>
1178typename 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
1183template <typename T, typename T2>
1184RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1185SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
1186    return pointer.Set(root, value, a);
1187}
1188
1189template <typename T, typename CharType, size_t N>
1190typename 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
1194template <typename T, typename CharType, size_t N>
1195typename 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
1199template <typename T, typename CharType, size_t N>
1200typename 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
1205template <typename T, typename CharType, size_t N>
1206typename 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
1211template <typename T, typename CharType, size_t N, typename T2>
1212RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1213SetValueByPointer(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
1219template <typename DocumentType>
1220typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1221    return pointer.Set(document, value);
1222}
1223
1224template <typename DocumentType>
1225typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
1226    return pointer.Set(document, value);
1227}
1228
1229template <typename DocumentType>
1230typename 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
1235template <typename DocumentType>
1236typename 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
1241template <typename DocumentType, typename T2>
1242RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1243SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
1244    return pointer.Set(document, value);
1245}
1246
1247template <typename DocumentType, typename CharType, size_t N>
1248typename 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
1252template <typename DocumentType, typename CharType, size_t N>
1253typename 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
1257template <typename DocumentType, typename CharType, size_t N>
1258typename 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
1263template <typename DocumentType, typename CharType, size_t N>
1264typename 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
1269template <typename DocumentType, typename CharType, size_t N, typename T2>
1270RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1271SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
1272    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1273}
1274
1275//////////////////////////////////////////////////////////////////////////////
1276
1277template <typename T>
1278typename 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
1282template <typename T, typename CharType, size_t N>
1283typename 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
1287template <typename DocumentType>
1288typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1289    return pointer.Swap(document, value);
1290}
1291
1292template <typename DocumentType, typename CharType, size_t N>
1293typename 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
1299template <typename T>
1300bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
1301    return pointer.Erase(root);
1302}
1303
1304template <typename T, typename CharType, size_t N>
1305bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
1306    return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
1307}
1308
1309//@}
1310
1311RAPIDJSON_NAMESPACE_END
1312
1313#endif // RAPIDJSON_POINTER_H_
1314