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 "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(GenericValue<EncodingType>(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                         m = v->MemberEnd();
495                         v = &(--m)->value; // Assumes AddMember() appends at the end
496                         exist = false;
497                     }
498                     else
499                         v = &m->value;
500                 }
501             }
502         }
503 
504         if (alreadyExist)
505             *alreadyExist = exist;
506 
507         return *v;
508     }
509 
510     //! Creates a value in a document.
511     /*!
512         \param document A document to be resolved.
513         \param alreadyExist If non-null, it stores whether the resolved value is already exist.
514         \return The resolved newly created, or already exists value.
515     */
516     template <typename stackAllocator>
517     ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
518         return Create(document, document.GetAllocator(), alreadyExist);
519     }
520 
521     //@}
522 
523     //!@name Query value
524     //@{
525 
526     //! Query a value in a subtree.
527     /*!
528         \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
529         \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
530         \return Pointer to the value if it can be resolved. Otherwise null.
531 
532         \note
533         There are only 3 situations when a value cannot be resolved:
534         1. A value in the path is not an array nor object.
535         2. An object value does not contain the token.
536         3. A token is out of range of an array value.
537 
538         Use unresolvedTokenIndex to retrieve the token index.
539     */
540     ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
541         RAPIDJSON_ASSERT(IsValid());
542         ValueType* v = &root;
543         for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
544             switch (v->GetType()) {
545             case kObjectType:
546                 {
547                     typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
548                     if (m == v->MemberEnd())
549                         break;
550                     v = &m->value;
551                 }
552                 continue;
553             case kArrayType:
554                 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
555                     break;
556                 v = &((*v)[t->index]);
557                 continue;
558             default:
559                 break;
560             }
561 
562             // Error: unresolved token
563             if (unresolvedTokenIndex)
564                 *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
565             return 0;
566         }
567         return v;
568     }
569 
570     //! Query a const value in a const subtree.
571     /*!
572         \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
573         \return Pointer to the value if it can be resolved. Otherwise null.
574     */
575     const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
576         return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
577     }
578 
579     //@}
580 
581     //!@name Query a value with default
582     //@{
583 
584     //! Query a value in a subtree with default value.
585     /*!
586         Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value.
587         So that this function always succeed.
588 
589         \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
590         \param defaultValue Default value to be cloned if the value was not exists.
591         \param allocator Allocator for creating the values if the specified value or its parents are not exist.
592         \see Create()
593     */
GetWithDefault(ValueType & root,const ValueType & defaultValue,typename ValueType::AllocatorType & allocator)594     ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
595         bool alreadyExist;
596         ValueType& v = Create(root, allocator, &alreadyExist);
597         return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
598     }
599 
600     //! Query a value in a subtree with default null-terminated string.
GetWithDefault(ValueType & root,const Ch * defaultValue,typename ValueType::AllocatorType & allocator)601     ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
602         bool alreadyExist;
603         ValueType& v = Create(root, allocator, &alreadyExist);
604         return alreadyExist ? v : v.SetString(defaultValue, allocator);
605     }
606 
607 #if RAPIDJSON_HAS_STDSTRING
608     //! Query a value in a subtree with default std::basic_string.
GetWithDefault(ValueType & root,const std::basic_string<Ch> & defaultValue,typename ValueType::AllocatorType & allocator)609     ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
610         bool alreadyExist;
611         ValueType& v = Create(root, allocator, &alreadyExist);
612         return alreadyExist ? v : v.SetString(defaultValue, allocator);
613     }
614 #endif
615 
616     //! Query a value in a subtree with default primitive value.
617     /*!
618         \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
619     */
620     template <typename T>
621     RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
GetWithDefault(ValueType & root,T defaultValue,typename ValueType::AllocatorType & allocator)622     GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
623         return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
624     }
625 
626     //! Query a value in a document with default value.
627     template <typename stackAllocator>
GetWithDefault(GenericDocument<EncodingType,typename ValueType::AllocatorType,stackAllocator> & document,const ValueType & defaultValue)628     ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const {
629         return GetWithDefault(document, defaultValue, document.GetAllocator());
630     }
631 
632     //! Query a value in a document with default null-terminated string.
633     template <typename stackAllocator>
GetWithDefault(GenericDocument<EncodingType,typename ValueType::AllocatorType,stackAllocator> & document,const Ch * defaultValue)634     ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
635         return GetWithDefault(document, defaultValue, document.GetAllocator());
636     }
637 
638 #if RAPIDJSON_HAS_STDSTRING
639     //! Query a value in a document with default std::basic_string.
640     template <typename stackAllocator>
GetWithDefault(GenericDocument<EncodingType,typename ValueType::AllocatorType,stackAllocator> & document,const std::basic_string<Ch> & defaultValue)641     ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
642         return GetWithDefault(document, defaultValue, document.GetAllocator());
643     }
644 #endif
645 
646     //! Query a value in a document with default primitive value.
647     /*!
648         \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
649     */
650     template <typename T, typename stackAllocator>
651     RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
GetWithDefault(GenericDocument<EncodingType,typename ValueType::AllocatorType,stackAllocator> & document,T defaultValue)652     GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
653         return GetWithDefault(document, defaultValue, document.GetAllocator());
654     }
655 
656     //@}
657 
658     //!@name Set a value
659     //@{
660 
661     //! Set a value in a subtree, with move semantics.
662     /*!
663         It creates all parents if they are not exist or types are different to the tokens.
664         So this function always succeeds but potentially remove existing values.
665 
666         \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
667         \param value Value to be set.
668         \param allocator Allocator for creating the values if the specified value or its parents are not exist.
669         \see Create()
670     */
Set(ValueType & root,ValueType & value,typename ValueType::AllocatorType & allocator)671     ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
672         return Create(root, allocator) = value;
673     }
674 
675     //! Set a value in a subtree, with copy semantics.
Set(ValueType & root,const ValueType & value,typename ValueType::AllocatorType & allocator)676     ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
677         return Create(root, allocator).CopyFrom(value, allocator);
678     }
679 
680     //! Set a null-terminated string in a subtree.
Set(ValueType & root,const Ch * value,typename ValueType::AllocatorType & allocator)681     ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
682         return Create(root, allocator) = ValueType(value, allocator).Move();
683     }
684 
685 #if RAPIDJSON_HAS_STDSTRING
686     //! Set a std::basic_string in a subtree.
Set(ValueType & root,const std::basic_string<Ch> & value,typename ValueType::AllocatorType & allocator)687     ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
688         return Create(root, allocator) = ValueType(value, allocator).Move();
689     }
690 #endif
691 
692     //! Set a primitive value in a subtree.
693     /*!
694         \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
695     */
696     template <typename T>
697     RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
Set(ValueType & root,T value,typename ValueType::AllocatorType & allocator)698     Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
699         return Create(root, allocator) = ValueType(value).Move();
700     }
701 
702     //! Set a value in a document, with move semantics.
703     template <typename stackAllocator>
Set(GenericDocument<EncodingType,typename ValueType::AllocatorType,stackAllocator> & document,ValueType & value)704     ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
705         return Create(document) = value;
706     }
707 
708     //! Set a value in a document, with copy semantics.
709     template <typename stackAllocator>
Set(GenericDocument<EncodingType,typename ValueType::AllocatorType,stackAllocator> & document,const ValueType & value)710     ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {
711         return Create(document).CopyFrom(value, document.GetAllocator());
712     }
713 
714     //! Set a null-terminated string in a document.
715     template <typename stackAllocator>
Set(GenericDocument<EncodingType,typename ValueType::AllocatorType,stackAllocator> & document,const Ch * value)716     ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const {
717         return Create(document) = ValueType(value, document.GetAllocator()).Move();
718     }
719 
720 #if RAPIDJSON_HAS_STDSTRING
721     //! Sets a std::basic_string in a document.
722     template <typename stackAllocator>
Set(GenericDocument<EncodingType,typename ValueType::AllocatorType,stackAllocator> & document,const std::basic_string<Ch> & value)723     ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
724         return Create(document) = ValueType(value, document.GetAllocator()).Move();
725     }
726 #endif
727 
728     //! Set a primitive value in a document.
729     /*!
730     \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
731     */
732     template <typename T, typename stackAllocator>
733     RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
Set(GenericDocument<EncodingType,typename ValueType::AllocatorType,stackAllocator> & document,T value)734         Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
735             return Create(document) = value;
736     }
737 
738     //@}
739 
740     //!@name Swap a value
741     //@{
742 
743     //! Swap a value with a value in a subtree.
744     /*!
745         It creates all parents if they are not exist or types are different to the tokens.
746         So this function always succeeds but potentially remove existing values.
747 
748         \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
749         \param value Value to be swapped.
750         \param allocator Allocator for creating the values if the specified value or its parents are not exist.
751         \see Create()
752     */
Swap(ValueType & root,ValueType & value,typename ValueType::AllocatorType & allocator)753     ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
754         return Create(root, allocator).Swap(value);
755     }
756 
757     //! Swap a value with a value in a document.
758     template <typename stackAllocator>
Swap(GenericDocument<EncodingType,typename ValueType::AllocatorType,stackAllocator> & document,ValueType & value)759     ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
760         return Create(document).Swap(value);
761     }
762 
763     //@}
764 
765     //! Erase a value in a subtree.
766     /*!
767         \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
768         \return Whether the resolved value is found and erased.
769 
770         \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false.
771     */
Erase(ValueType & root)772     bool Erase(ValueType& root) const {
773         RAPIDJSON_ASSERT(IsValid());
774         if (tokenCount_ == 0) // Cannot erase the root
775             return false;
776 
777         ValueType* v = &root;
778         const Token* last = tokens_ + (tokenCount_ - 1);
779         for (const Token *t = tokens_; t != last; ++t) {
780             switch (v->GetType()) {
781             case kObjectType:
782                 {
783                     typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
784                     if (m == v->MemberEnd())
785                         return false;
786                     v = &m->value;
787                 }
788                 break;
789             case kArrayType:
790                 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
791                     return false;
792                 v = &((*v)[t->index]);
793                 break;
794             default:
795                 return false;
796             }
797         }
798 
799         switch (v->GetType()) {
800         case kObjectType:
801             return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
802         case kArrayType:
803             if (last->index == kPointerInvalidIndex || last->index >= v->Size())
804                 return false;
805             v->Erase(v->Begin() + last->index);
806             return true;
807         default:
808             return false;
809         }
810     }
811 
812 private:
813     //! Clone the content from rhs to this.
814     /*!
815         \param rhs Source pointer.
816         \param extraToken Extra tokens to be allocated.
817         \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated.
818         \return Start of non-occupied name buffer, for storing extra names.
819     */
820     Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
821         if (!allocator_) // allocator is independently owned.
822             ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
823 
824         size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
825         for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
826             nameBufferSize += t->length;
827 
828         tokenCount_ = rhs.tokenCount_ + extraToken;
829         tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
830         nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
831         if (rhs.tokenCount_ > 0) {
832             std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
833         }
834         if (nameBufferSize > 0) {
835             std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
836         }
837 
838         // Adjust pointers to name buffer
839         std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
840         for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
841             t->name += diff;
842 
843         return nameBuffer_ + nameBufferSize;
844     }
845 
846     //! Check whether a character should be percent-encoded.
847     /*!
848         According to RFC 3986 2.3 Unreserved Characters.
849         \param c The character (code unit) to be tested.
850     */
NeedPercentEncode(Ch c)851     bool NeedPercentEncode(Ch c) const {
852         return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
853     }
854 
855     //! Parse a JSON String or its URI fragment representation into tokens.
856 #ifndef __clang__ // -Wdocumentation
857     /*!
858         \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated.
859         \param length Length of the source string.
860         \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped.
861     */
862 #endif
Parse(const Ch * source,size_t length)863     void Parse(const Ch* source, size_t length) {
864         RAPIDJSON_ASSERT(source != NULL);
865         RAPIDJSON_ASSERT(nameBuffer_ == 0);
866         RAPIDJSON_ASSERT(tokens_ == 0);
867 
868         // Create own allocator if user did not supply.
869         if (!allocator_)
870             ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
871 
872         // Count number of '/' as tokenCount
873         tokenCount_ = 0;
874         for (const Ch* s = source; s != source + length; s++)
875             if (*s == '/')
876                 tokenCount_++;
877 
878         Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
879         Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
880         size_t i = 0;
881 
882         // Detect if it is a URI fragment
883         bool uriFragment = false;
884         if (source[i] == '#') {
885             uriFragment = true;
886             i++;
887         }
888 
889         if (i != length && source[i] != '/') {
890             parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus;
891             goto error;
892         }
893 
894         while (i < length) {
895             RAPIDJSON_ASSERT(source[i] == '/');
896             i++; // consumes '/'
897 
898             token->name = name;
899             bool isNumber = true;
900 
901             while (i < length && source[i] != '/') {
902                 Ch c = source[i];
903                 if (uriFragment) {
904                     // Decoding percent-encoding for URI fragment
905                     if (c == '%') {
906                         PercentDecodeStream is(&source[i], source + length);
907                         GenericInsituStringStream<EncodingType> os(name);
908                         Ch* begin = os.PutBegin();
909                         if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
910                             parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding;
911                             goto error;
912                         }
913                         size_t len = os.PutEnd(begin);
914                         i += is.Tell() - 1;
915                         if (len == 1)
916                             c = *name;
917                         else {
918                             name += len;
919                             isNumber = false;
920                             i++;
921                             continue;
922                         }
923                     }
924                     else if (NeedPercentEncode(c)) {
925                         parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode;
926                         goto error;
927                     }
928                 }
929 
930                 i++;
931 
932                 // Escaping "~0" -> '~', "~1" -> '/'
933                 if (c == '~') {
934                     if (i < length) {
935                         c = source[i];
936                         if (c == '0')       c = '~';
937                         else if (c == '1')  c = '/';
938                         else {
939                             parseErrorCode_ = kPointerParseErrorInvalidEscape;
940                             goto error;
941                         }
942                         i++;
943                     }
944                     else {
945                         parseErrorCode_ = kPointerParseErrorInvalidEscape;
946                         goto error;
947                     }
948                 }
949 
950                 // First check for index: all of characters are digit
951                 if (c < '0' || c > '9')
952                     isNumber = false;
953 
954                 *name++ = c;
955             }
956             token->length = static_cast<SizeType>(name - token->name);
957             if (token->length == 0)
958                 isNumber = false;
959             *name++ = '\0'; // Null terminator
960 
961             // Second check for index: more than one digit cannot have leading zero
962             if (isNumber && token->length > 1 && token->name[0] == '0')
963                 isNumber = false;
964 
965             // String to SizeType conversion
966             SizeType n = 0;
967             if (isNumber) {
968                 for (size_t j = 0; j < token->length; j++) {
969                     SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
970                     if (m < n) {   // overflow detection
971                         isNumber = false;
972                         break;
973                     }
974                     n = m;
975                 }
976             }
977 
978             token->index = isNumber ? n : kPointerInvalidIndex;
979             token++;
980         }
981 
982         RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
983         parseErrorCode_ = kPointerParseErrorNone;
984         return;
985 
986     error:
987         Allocator::Free(tokens_);
988         nameBuffer_ = 0;
989         tokens_ = 0;
990         tokenCount_ = 0;
991         parseErrorOffset_ = i;
992         return;
993     }
994 
995     //! Stringify to string or URI fragment representation.
996     /*!
997         \tparam uriFragment True for stringifying to URI fragment representation. False for string representation.
998         \tparam OutputStream type of output stream.
999         \param os The output stream.
1000     */
1001     template<bool uriFragment, typename OutputStream>
Stringify(OutputStream & os)1002     bool Stringify(OutputStream& os) const {
1003         RAPIDJSON_ASSERT(IsValid());
1004 
1005         if (uriFragment)
1006             os.Put('#');
1007 
1008         for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
1009             os.Put('/');
1010             for (size_t j = 0; j < t->length; j++) {
1011                 Ch c = t->name[j];
1012                 if (c == '~') {
1013                     os.Put('~');
1014                     os.Put('0');
1015                 }
1016                 else if (c == '/') {
1017                     os.Put('~');
1018                     os.Put('1');
1019                 }
1020                 else if (uriFragment && NeedPercentEncode(c)) {
1021                     // Transcode to UTF8 sequence
1022                     GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
1023                     PercentEncodeStream<OutputStream> target(os);
1024                     if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
1025                         return false;
1026                     j += source.Tell() - 1;
1027                 }
1028                 else
1029                     os.Put(c);
1030             }
1031         }
1032         return true;
1033     }
1034 
1035     //! A helper stream for decoding a percent-encoded sequence into code unit.
1036     /*!
1037         This stream decodes %XY triplet into code unit (0-255).
1038         If it encounters invalid characters, it sets output code unit as 0 and
1039         mark invalid, and to be checked by IsValid().
1040     */
1041     class PercentDecodeStream {
1042     public:
1043         typedef typename ValueType::Ch Ch;
1044 
1045         //! Constructor
1046         /*!
1047             \param source Start of the stream
1048             \param end Past-the-end of the stream.
1049         */
PercentDecodeStream(const Ch * source,const Ch * end)1050         PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
1051 
Take()1052         Ch Take() {
1053             if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
1054                 valid_ = false;
1055                 return 0;
1056             }
1057             src_++;
1058             Ch c = 0;
1059             for (int j = 0; j < 2; j++) {
1060                 c = static_cast<Ch>(c << 4);
1061                 Ch h = *src_;
1062                 if      (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
1063                 else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
1064                 else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
1065                 else {
1066                     valid_ = false;
1067                     return 0;
1068                 }
1069                 src_++;
1070             }
1071             return c;
1072         }
1073 
Tell()1074         size_t Tell() const { return static_cast<size_t>(src_ - head_); }
IsValid()1075         bool IsValid() const { return valid_; }
1076 
1077     private:
1078         const Ch* src_;     //!< Current read position.
1079         const Ch* head_;    //!< Original head of the string.
1080         const Ch* end_;     //!< Past-the-end position.
1081         bool valid_;        //!< Whether the parsing is valid.
1082     };
1083 
1084     //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
1085     template <typename OutputStream>
1086     class PercentEncodeStream {
1087     public:
PercentEncodeStream(OutputStream & os)1088         PercentEncodeStream(OutputStream& os) : os_(os) {}
Put(char c)1089         void Put(char c) { // UTF-8 must be byte
1090             unsigned char u = static_cast<unsigned char>(c);
1091             static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1092             os_.Put('%');
1093             os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
1094             os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
1095         }
1096     private:
1097         OutputStream& os_;
1098     };
1099 
1100     Allocator* allocator_;                  //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
1101     Allocator* ownAllocator_;               //!< Allocator owned by this Pointer.
1102     Ch* nameBuffer_;                        //!< A buffer containing all names in tokens.
1103     Token* tokens_;                         //!< A list of tokens.
1104     size_t tokenCount_;                     //!< Number of tokens in tokens_.
1105     size_t parseErrorOffset_;               //!< Offset in code unit when parsing fail.
1106     PointerParseErrorCode parseErrorCode_;  //!< Parsing error code.
1107 };
1108 
1109 //! GenericPointer for Value (UTF-8, default allocator).
1110 typedef GenericPointer<Value> Pointer;
1111 
1112 //!@name Helper functions for GenericPointer
1113 //@{
1114 
1115 //////////////////////////////////////////////////////////////////////////////
1116 
1117 template <typename T>
CreateValueByPointer(T & root,const GenericPointer<typename T::ValueType> & pointer,typename T::AllocatorType & a)1118 typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
1119     return pointer.Create(root, a);
1120 }
1121 
1122 template <typename T, typename CharType, size_t N>
CreateValueByPointer(T & root,const CharType (& source)[N],typename T::AllocatorType & a)1123 typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
1124     return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
1125 }
1126 
1127 // No allocator parameter
1128 
1129 template <typename DocumentType>
CreateValueByPointer(DocumentType & document,const GenericPointer<typename DocumentType::ValueType> & pointer)1130 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
1131     return pointer.Create(document);
1132 }
1133 
1134 template <typename DocumentType, typename CharType, size_t N>
CreateValueByPointer(DocumentType & document,const CharType (& source)[N])1135 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
1136     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
1137 }
1138 
1139 //////////////////////////////////////////////////////////////////////////////
1140 
1141 template <typename T>
1142 typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1143     return pointer.Get(root, unresolvedTokenIndex);
1144 }
1145 
1146 template <typename T>
1147 const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1148     return pointer.Get(root, unresolvedTokenIndex);
1149 }
1150 
1151 template <typename T, typename CharType, size_t N>
1152 typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
1153     return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1154 }
1155 
1156 template <typename T, typename CharType, size_t N>
1157 const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
1158     return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1159 }
1160 
1161 //////////////////////////////////////////////////////////////////////////////
1162 
1163 template <typename T>
GetValueByPointerWithDefault(T & root,const GenericPointer<typename T::ValueType> & pointer,const typename T::ValueType & defaultValue,typename T::AllocatorType & a)1164 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1165     return pointer.GetWithDefault(root, defaultValue, a);
1166 }
1167 
1168 template <typename T>
GetValueByPointerWithDefault(T & root,const GenericPointer<typename T::ValueType> & pointer,const typename T::Ch * defaultValue,typename T::AllocatorType & a)1169 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1170     return pointer.GetWithDefault(root, defaultValue, a);
1171 }
1172 
1173 #if RAPIDJSON_HAS_STDSTRING
1174 template <typename T>
GetValueByPointerWithDefault(T & root,const GenericPointer<typename T::ValueType> & pointer,const std::basic_string<typename T::Ch> & defaultValue,typename T::AllocatorType & a)1175 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1176     return pointer.GetWithDefault(root, defaultValue, a);
1177 }
1178 #endif
1179 
1180 template <typename T, typename T2>
1181 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)1182 GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
1183     return pointer.GetWithDefault(root, defaultValue, a);
1184 }
1185 
1186 template <typename T, typename CharType, size_t N>
GetValueByPointerWithDefault(T & root,const CharType (& source)[N],const typename T::ValueType & defaultValue,typename T::AllocatorType & a)1187 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1188     return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1189 }
1190 
1191 template <typename T, typename CharType, size_t N>
GetValueByPointerWithDefault(T & root,const CharType (& source)[N],const typename T::Ch * defaultValue,typename T::AllocatorType & a)1192 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1193     return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1194 }
1195 
1196 #if RAPIDJSON_HAS_STDSTRING
1197 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)1198 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1199     return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1200 }
1201 #endif
1202 
1203 template <typename T, typename CharType, size_t N, typename T2>
1204 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)1205 GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
1206     return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1207 }
1208 
1209 // No allocator parameter
1210 
1211 template <typename DocumentType>
GetValueByPointerWithDefault(DocumentType & document,const GenericPointer<typename DocumentType::ValueType> & pointer,const typename DocumentType::ValueType & defaultValue)1212 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
1213     return pointer.GetWithDefault(document, defaultValue);
1214 }
1215 
1216 template <typename DocumentType>
GetValueByPointerWithDefault(DocumentType & document,const GenericPointer<typename DocumentType::ValueType> & pointer,const typename DocumentType::Ch * defaultValue)1217 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
1218     return pointer.GetWithDefault(document, defaultValue);
1219 }
1220 
1221 #if RAPIDJSON_HAS_STDSTRING
1222 template <typename DocumentType>
GetValueByPointerWithDefault(DocumentType & document,const GenericPointer<typename DocumentType::ValueType> & pointer,const std::basic_string<typename DocumentType::Ch> & defaultValue)1223 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1224     return pointer.GetWithDefault(document, defaultValue);
1225 }
1226 #endif
1227 
1228 template <typename DocumentType, typename T2>
1229 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)1230 GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
1231     return pointer.GetWithDefault(document, defaultValue);
1232 }
1233 
1234 template <typename DocumentType, typename CharType, size_t N>
GetValueByPointerWithDefault(DocumentType & document,const CharType (& source)[N],const typename DocumentType::ValueType & defaultValue)1235 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
1236     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1237 }
1238 
1239 template <typename DocumentType, typename CharType, size_t N>
GetValueByPointerWithDefault(DocumentType & document,const CharType (& source)[N],const typename DocumentType::Ch * defaultValue)1240 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
1241     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1242 }
1243 
1244 #if RAPIDJSON_HAS_STDSTRING
1245 template <typename DocumentType, typename CharType, size_t N>
GetValueByPointerWithDefault(DocumentType & document,const CharType (& source)[N],const std::basic_string<typename DocumentType::Ch> & defaultValue)1246 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1247     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1248 }
1249 #endif
1250 
1251 template <typename DocumentType, typename CharType, size_t N, typename T2>
1252 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
GetValueByPointerWithDefault(DocumentType & document,const CharType (& source)[N],T2 defaultValue)1253 GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
1254     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1255 }
1256 
1257 //////////////////////////////////////////////////////////////////////////////
1258 
1259 template <typename T>
SetValueByPointer(T & root,const GenericPointer<typename T::ValueType> & pointer,typename T::ValueType & value,typename T::AllocatorType & a)1260 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1261     return pointer.Set(root, value, a);
1262 }
1263 
1264 template <typename T>
SetValueByPointer(T & root,const GenericPointer<typename T::ValueType> & pointer,const typename T::ValueType & value,typename T::AllocatorType & a)1265 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
1266     return pointer.Set(root, value, a);
1267 }
1268 
1269 template <typename T>
SetValueByPointer(T & root,const GenericPointer<typename T::ValueType> & pointer,const typename T::Ch * value,typename T::AllocatorType & a)1270 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
1271     return pointer.Set(root, value, a);
1272 }
1273 
1274 #if RAPIDJSON_HAS_STDSTRING
1275 template <typename T>
SetValueByPointer(T & root,const GenericPointer<typename T::ValueType> & pointer,const std::basic_string<typename T::Ch> & value,typename T::AllocatorType & a)1276 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1277     return pointer.Set(root, value, a);
1278 }
1279 #endif
1280 
1281 template <typename T, typename T2>
1282 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)1283 SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
1284     return pointer.Set(root, value, a);
1285 }
1286 
1287 template <typename T, typename CharType, size_t N>
SetValueByPointer(T & root,const CharType (& source)[N],typename T::ValueType & value,typename T::AllocatorType & a)1288 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1289     return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1290 }
1291 
1292 template <typename T, typename CharType, size_t N>
SetValueByPointer(T & root,const CharType (& source)[N],const typename T::ValueType & value,typename T::AllocatorType & a)1293 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
1294     return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1295 }
1296 
1297 template <typename T, typename CharType, size_t N>
SetValueByPointer(T & root,const CharType (& source)[N],const typename T::Ch * value,typename T::AllocatorType & a)1298 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
1299     return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1300 }
1301 
1302 #if RAPIDJSON_HAS_STDSTRING
1303 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)1304 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1305     return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1306 }
1307 #endif
1308 
1309 template <typename T, typename CharType, size_t N, typename T2>
1310 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)1311 SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
1312     return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1313 }
1314 
1315 // No allocator parameter
1316 
1317 template <typename DocumentType>
SetValueByPointer(DocumentType & document,const GenericPointer<typename DocumentType::ValueType> & pointer,typename DocumentType::ValueType & value)1318 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1319     return pointer.Set(document, value);
1320 }
1321 
1322 template <typename DocumentType>
SetValueByPointer(DocumentType & document,const GenericPointer<typename DocumentType::ValueType> & pointer,const typename DocumentType::ValueType & value)1323 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
1324     return pointer.Set(document, value);
1325 }
1326 
1327 template <typename DocumentType>
SetValueByPointer(DocumentType & document,const GenericPointer<typename DocumentType::ValueType> & pointer,const typename DocumentType::Ch * value)1328 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
1329     return pointer.Set(document, value);
1330 }
1331 
1332 #if RAPIDJSON_HAS_STDSTRING
1333 template <typename DocumentType>
SetValueByPointer(DocumentType & document,const GenericPointer<typename DocumentType::ValueType> & pointer,const std::basic_string<typename DocumentType::Ch> & value)1334 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
1335     return pointer.Set(document, value);
1336 }
1337 #endif
1338 
1339 template <typename DocumentType, typename T2>
1340 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)1341 SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
1342     return pointer.Set(document, value);
1343 }
1344 
1345 template <typename DocumentType, typename CharType, size_t N>
SetValueByPointer(DocumentType & document,const CharType (& source)[N],typename DocumentType::ValueType & value)1346 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1347     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1348 }
1349 
1350 template <typename DocumentType, typename CharType, size_t N>
SetValueByPointer(DocumentType & document,const CharType (& source)[N],const typename DocumentType::ValueType & value)1351 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
1352     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1353 }
1354 
1355 template <typename DocumentType, typename CharType, size_t N>
SetValueByPointer(DocumentType & document,const CharType (& source)[N],const typename DocumentType::Ch * value)1356 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
1357     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1358 }
1359 
1360 #if RAPIDJSON_HAS_STDSTRING
1361 template <typename DocumentType, typename CharType, size_t N>
SetValueByPointer(DocumentType & document,const CharType (& source)[N],const std::basic_string<typename DocumentType::Ch> & value)1362 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
1363     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1364 }
1365 #endif
1366 
1367 template <typename DocumentType, typename CharType, size_t N, typename T2>
1368 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
SetValueByPointer(DocumentType & document,const CharType (& source)[N],T2 value)1369 SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
1370     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1371 }
1372 
1373 //////////////////////////////////////////////////////////////////////////////
1374 
1375 template <typename T>
SwapValueByPointer(T & root,const GenericPointer<typename T::ValueType> & pointer,typename T::ValueType & value,typename T::AllocatorType & a)1376 typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1377     return pointer.Swap(root, value, a);
1378 }
1379 
1380 template <typename T, typename CharType, size_t N>
SwapValueByPointer(T & root,const CharType (& source)[N],typename T::ValueType & value,typename T::AllocatorType & a)1381 typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1382     return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
1383 }
1384 
1385 template <typename DocumentType>
SwapValueByPointer(DocumentType & document,const GenericPointer<typename DocumentType::ValueType> & pointer,typename DocumentType::ValueType & value)1386 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1387     return pointer.Swap(document, value);
1388 }
1389 
1390 template <typename DocumentType, typename CharType, size_t N>
SwapValueByPointer(DocumentType & document,const CharType (& source)[N],typename DocumentType::ValueType & value)1391 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1392     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
1393 }
1394 
1395 //////////////////////////////////////////////////////////////////////////////
1396 
1397 template <typename T>
EraseValueByPointer(T & root,const GenericPointer<typename T::ValueType> & pointer)1398 bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
1399     return pointer.Erase(root);
1400 }
1401 
1402 template <typename T, typename CharType, size_t N>
EraseValueByPointer(T & root,const CharType (& source)[N])1403 bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
1404     return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
1405 }
1406 
1407 //@}
1408 
1409 RAPIDJSON_NAMESPACE_END
1410 
1411 #if defined(__clang__) || defined(_MSC_VER)
1412 RAPIDJSON_DIAG_POP
1413 #endif
1414 
1415 #endif // RAPIDJSON_POINTER_H_
1416