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