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