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