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