1 // Tencent is pleased to support the open source community by making RapidJSON available.
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
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
8 // http://opensource.org/licenses/MIT
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.
15 #ifndef RAPIDJSON_POINTER_H_
16 #define RAPIDJSON_POINTER_H_
19 #include "internal/itoa.h"
23 RAPIDJSON_DIAG_OFF(switch-enum)
28 RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
31 RAPIDJSON_NAMESPACE_BEGIN
33 static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token
35 //! Error code of parsing.
36 /*! \ingroup RAPIDJSON_ERRORS
37 \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
39 enum PointerParseErrorCode {
40 kPointerParseErrorNone = 0, //!< The parse is successful
42 kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/'
43 kPointerParseErrorInvalidEscape, //!< Invalid escape
44 kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment
45 kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment
48 ///////////////////////////////////////////////////////////////////////////////
51 //! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
53 This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer"
54 (https://tools.ietf.org/html/rfc6901).
56 A JSON pointer is for identifying a specific value in a JSON document
57 (GenericDocument). It can simplify coding of DOM tree manipulation, because it
58 can access multiple-level depth of DOM tree with single API call.
60 After it parses a string representation (e.g. "/foo/0" or URI fragment
61 representation (e.g. "#/foo/0") into its internal representation (tokens),
62 it can be used to resolve a specific value in multiple documents, or sub-tree
65 Contrary to GenericValue, Pointer can be copy constructed and copy assigned.
66 Apart from assignment, a Pointer cannot be modified after construction.
68 Although Pointer is very convenient, please aware that constructing Pointer
69 involves parsing and dynamic memory allocation. A special constructor with user-
70 supplied tokens eliminates these.
72 GenericPointer depends on GenericDocument and GenericValue.
74 \tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> >
75 \tparam Allocator The allocator type for allocating memory for internal representation.
77 \note GenericPointer uses same encoding of ValueType.
78 However, Allocator of GenericPointer is independent of Allocator of Value.
80 template <typename ValueType, typename Allocator = CrtAllocator>
81 class GenericPointer {
83 typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
84 typedef typename ValueType::Ch Ch; //!< Character type from Value
86 //! A token is the basic units of internal representation.
88 A JSON pointer string representation "/foo/123" is parsed to two tokens:
89 "foo" and 123. 123 will be represented in both numeric form and string form.
90 They are resolved according to the actual value type (object or array).
92 For token that are not numbers, or the numeric value is out of bound
93 (greater than limits of SizeType), they are only treated as string form
94 (i.e. the token's index will be equal to kPointerInvalidIndex).
96 This struct is public so that user can create a Pointer without parsing and
97 allocation, using a special constructor.
100 const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character.
101 SizeType length; //!< Length of the name.
102 SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex.
105 //!@name Constructors and destructor.
108 //! Default constructor.
109 GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
111 //! Constructor that parses a string or URI fragment representation.
113 \param source A null-terminated, string or URI fragment representation of JSON pointer.
114 \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
116 explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
117 Parse(source, internal::StrLen(source));
120 #if RAPIDJSON_HAS_STDSTRING
121 //! Constructor that parses a string or URI fragment representation.
123 \param source A string or URI fragment representation of JSON pointer.
124 \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
125 \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
127 explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
128 Parse(source.c_str(), source.size());
132 //! Constructor that parses a string or URI fragment representation, with length of the source string.
134 \param source A string or URI fragment representation of JSON pointer.
135 \param length Length of source.
136 \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
137 \note Slightly faster than the overload without length.
139 GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
140 Parse(source, length);
143 //! Constructor with user-supplied tokens.
145 This constructor let user supplies const array of tokens.
146 This prevents the parsing process and eliminates allocation.
147 This is preferred for memory constrained environments.
149 \param tokens An constant array of tokens representing the JSON pointer.
150 \param tokenCount Number of tokens.
154 #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }
155 #define INDEX(i) { #i, sizeof(#i) - 1, i }
157 static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) };
158 static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
159 // Equivalent to static const Pointer p("/foo/123");
165 GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
167 //! Copy constructor.
168 GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
174 if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
175 Allocator::Free(tokens_);
176 RAPIDJSON_DELETE(ownAllocator_);
179 //! Assignment operator.
180 GenericPointer& operator=(const GenericPointer& rhs) {
182 // Do not delete ownAllcator
184 Allocator::Free(tokens_);
186 tokenCount_ = rhs.tokenCount_;
187 parseErrorOffset_ = rhs.parseErrorOffset_;
188 parseErrorCode_ = rhs.parseErrorCode_;
191 CopyFromRaw(rhs); // Normally parsed tokens.
193 tokens_ = rhs.tokens_; // User supplied const tokens.
202 //!@name Append token
205 //! Append a token and return a new Pointer
207 \param token Token to be appended.
208 \param allocator Allocator for the newly return Pointer.
209 \return A new Pointer with appended token.
211 GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
213 r.allocator_ = allocator;
214 Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
215 std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
216 r.tokens_[tokenCount_].name = p;
217 r.tokens_[tokenCount_].length = token.length;
218 r.tokens_[tokenCount_].index = token.index;
222 //! Append a name token with length, and return a new Pointer
224 \param name Name to be appended.
225 \param length Length of name.
226 \param allocator Allocator for the newly return Pointer.
227 \return A new Pointer with appended token.
229 GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
230 Token token = { name, length, kPointerInvalidIndex };
231 return Append(token, allocator);
234 //! Append a name token without length, and return a new Pointer
236 \param name Name (const Ch*) to be appended.
237 \param allocator Allocator for the newly return Pointer.
238 \return A new Pointer with appended token.
240 template <typename T>
241 RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
242 Append(T* name, Allocator* allocator = 0) const {
243 return Append(name, StrLen(name), allocator);
246 #if RAPIDJSON_HAS_STDSTRING
247 //! Append a name token, and return a new Pointer
249 \param name Name to be appended.
250 \param allocator Allocator for the newly return Pointer.
251 \return A new Pointer with appended token.
253 GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
254 return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
258 //! Append a index token, and return a new Pointer
260 \param index Index to be appended.
261 \param allocator Allocator for the newly return Pointer.
262 \return A new Pointer with appended token.
264 GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
266 char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
267 SizeType length = static_cast<SizeType>(end - buffer);
268 buffer[length] = '\0';
270 if (sizeof(Ch) == 1) {
271 Token token = { reinterpret_cast<Ch*>(buffer), length, index };
272 return Append(token, allocator);
276 for (size_t i = 0; i <= length; i++)
278 Token token = { name, length, index };
279 return Append(token, allocator);
283 //! Append a token by value, and return a new Pointer
285 \param token token to be appended.
286 \param allocator Allocator for the newly return Pointer.
287 \return A new Pointer with appended token.
289 GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
290 if (token.IsString())
291 return Append(token.GetString(), token.GetStringLength(), allocator);
293 RAPIDJSON_ASSERT(token.IsUint64());
294 RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
295 return Append(static_cast<SizeType>(token.GetUint64()), allocator);
299 //!@name Handling Parse Error
302 //! Check whether this is a valid pointer.
303 bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
305 //! Get the parsing error offset in code unit.
306 size_t GetParseErrorOffset() const { return parseErrorOffset_; }
308 //! Get the parsing error code.
309 PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
313 //! Get the allocator of this pointer.
314 Allocator& GetAllocator() { return *allocator_; }
319 //! Get the token array (const version only).
320 const Token* GetTokens() const { return tokens_; }
322 //! Get the number of tokens.
323 size_t GetTokenCount() const { return tokenCount_; }
327 //!@name Equality/inequality operators
330 //! Equality operator.
332 \note When any pointers are invalid, always returns false.
334 bool operator==(const GenericPointer& rhs) const {
335 if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
338 for (size_t i = 0; i < tokenCount_; i++) {
339 if (tokens_[i].index != rhs.tokens_[i].index ||
340 tokens_[i].length != rhs.tokens_[i].length ||
341 (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
350 //! Inequality operator.
352 \note When any pointers are invalid, always returns true.
354 bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
361 //! Stringify the pointer into string representation.
363 \tparam OutputStream Type of output stream.
364 \param os The output stream.
366 template<typename OutputStream>
367 bool Stringify(OutputStream& os) const {
368 return Stringify<false, OutputStream>(os);
371 //! Stringify the pointer into URI fragment representation.
373 \tparam OutputStream Type of output stream.
374 \param os The output stream.
376 template<typename OutputStream>
377 bool StringifyUriFragment(OutputStream& os) const {
378 return Stringify<true, OutputStream>(os);
383 //!@name Create value
386 //! Create a value in a subtree.
388 If the value is not exist, it creates all parent values and a JSON Null value.
389 So it always succeed and return the newly created or existing value.
391 Remind that it may change types of parents according to tokens, so it
392 potentially removes previously stored values. For example, if a document
393 was an array, and "/foo" is used to create a value, then the document
394 will be changed to an object, and all existing array elements are lost.
396 \param root Root value of a DOM subtree to be resolved. It can be any value other than document root.
397 \param allocator Allocator for creating the values if the specified value or its parents are not exist.
398 \param alreadyExist If non-null, it stores whether the resolved value is already exist.
399 \return The resolved newly created (a JSON Null value), or already exists value.
401 ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
402 RAPIDJSON_ASSERT(IsValid());
403 ValueType* v = &root;
405 for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
406 if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
407 v->PushBack(ValueType().Move(), allocator);
408 v = &((*v)[v->Size() - 1]);
412 if (t->index == kPointerInvalidIndex) { // must be object name
414 v->SetObject(); // Change to Object
416 else { // object name or array index
417 if (!v->IsArray() && !v->IsObject())
418 v->SetArray(); // Change to Array
422 if (t->index >= v->Size()) {
423 v->Reserve(t->index + 1, allocator);
424 while (t->index >= v->Size())
425 v->PushBack(ValueType().Move(), allocator);
428 v = &((*v)[t->index]);
431 typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
432 if (m == v->MemberEnd()) {
433 v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
434 v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
444 *alreadyExist = exist;
449 //! Creates a value in a document.
451 \param document A document to be resolved.
452 \param alreadyExist If non-null, it stores whether the resolved value is already exist.
453 \return The resolved newly created, or already exists value.
455 template <typename stackAllocator>
456 ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
457 return Create(document, document.GetAllocator(), alreadyExist);
465 //! Query a value in a subtree.
467 \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
468 \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
469 \return Pointer to the value if it can be resolved. Otherwise null.
472 There are only 3 situations when a value cannot be resolved:
473 1. A value in the path is not an array nor object.
474 2. An object value does not contain the token.
475 3. A token is out of range of an array value.
477 Use unresolvedTokenIndex to retrieve the token index.
479 ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
480 RAPIDJSON_ASSERT(IsValid());
481 ValueType* v = &root;
482 for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
483 switch (v->GetType()) {
486 typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
487 if (m == v->MemberEnd())
493 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
495 v = &((*v)[t->index]);
501 // Error: unresolved token
502 if (unresolvedTokenIndex)
503 *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
509 //! Query a const value in a const subtree.
511 \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
512 \return Pointer to the value if it can be resolved. Otherwise null.
514 const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
515 return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
520 //!@name Query a value with default
523 //! Query a value in a subtree with default value.
525 Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value.
526 So that this function always succeed.
528 \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
529 \param defaultValue Default value to be cloned if the value was not exists.
530 \param allocator Allocator for creating the values if the specified value or its parents are not exist.
533 ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
535 Value& v = Create(root, allocator, &alreadyExist);
536 return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
539 //! Query a value in a subtree with default null-terminated string.
540 ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
542 Value& v = Create(root, allocator, &alreadyExist);
543 return alreadyExist ? v : v.SetString(defaultValue, allocator);
546 #if RAPIDJSON_HAS_STDSTRING
547 //! Query a value in a subtree with default std::basic_string.
548 ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
550 Value& v = Create(root, allocator, &alreadyExist);
551 return alreadyExist ? v : v.SetString(defaultValue, allocator);
555 //! Query a value in a subtree with default primitive value.
557 \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
559 template <typename T>
560 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
561 GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
562 return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
565 //! Query a value in a document with default value.
566 template <typename stackAllocator>
567 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const {
568 return GetWithDefault(document, defaultValue, document.GetAllocator());
571 //! Query a value in a document with default null-terminated string.
572 template <typename stackAllocator>
573 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
574 return GetWithDefault(document, defaultValue, document.GetAllocator());
577 #if RAPIDJSON_HAS_STDSTRING
578 //! Query a value in a document with default std::basic_string.
579 template <typename stackAllocator>
580 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
581 return GetWithDefault(document, defaultValue, document.GetAllocator());
585 //! Query a value in a document with default primitive value.
587 \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
589 template <typename T, typename stackAllocator>
590 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
591 GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
592 return GetWithDefault(document, defaultValue, document.GetAllocator());
600 //! Set a value in a subtree, with move semantics.
602 It creates all parents if they are not exist or types are different to the tokens.
603 So this function always succeeds but potentially remove existing values.
605 \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
606 \param value Value to be set.
607 \param allocator Allocator for creating the values if the specified value or its parents are not exist.
610 ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
611 return Create(root, allocator) = value;
614 //! Set a value in a subtree, with copy semantics.
615 ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
616 return Create(root, allocator).CopyFrom(value, allocator);
619 //! Set a null-terminated string in a subtree.
620 ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
621 return Create(root, allocator) = ValueType(value, allocator).Move();
624 #if RAPIDJSON_HAS_STDSTRING
625 //! Set a std::basic_string in a subtree.
626 ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
627 return Create(root, allocator) = ValueType(value, allocator).Move();
631 //! Set a primitive value in a subtree.
633 \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
635 template <typename T>
636 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
637 Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
638 return Create(root, allocator) = ValueType(value).Move();
641 //! Set a value in a document, with move semantics.
642 template <typename stackAllocator>
643 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
644 return Create(document) = value;
647 //! Set a value in a document, with copy semantics.
648 template <typename stackAllocator>
649 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {
650 return Create(document).CopyFrom(value, document.GetAllocator());
653 //! Set a null-terminated string in a document.
654 template <typename stackAllocator>
655 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const {
656 return Create(document) = ValueType(value, document.GetAllocator()).Move();
659 #if RAPIDJSON_HAS_STDSTRING
660 //! Sets a std::basic_string in a document.
661 template <typename stackAllocator>
662 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
663 return Create(document) = ValueType(value, document.GetAllocator()).Move();
667 //! Set a primitive value in a document.
669 \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
671 template <typename T, typename stackAllocator>
672 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
673 Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
674 return Create(document) = value;
679 //!@name Swap a value
682 //! Swap a value with a value in a subtree.
684 It creates all parents if they are not exist or types are different to the tokens.
685 So this function always succeeds but potentially remove existing values.
687 \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
688 \param value Value to be swapped.
689 \param allocator Allocator for creating the values if the specified value or its parents are not exist.
692 ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
693 return Create(root, allocator).Swap(value);
696 //! Swap a value with a value in a document.
697 template <typename stackAllocator>
698 ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
699 return Create(document).Swap(value);
704 //! Erase a value in a subtree.
706 \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
707 \return Whether the resolved value is found and erased.
709 \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false.
711 bool Erase(ValueType& root) const {
712 RAPIDJSON_ASSERT(IsValid());
713 if (tokenCount_ == 0) // Cannot erase the root
716 ValueType* v = &root;
717 const Token* last = tokens_ + (tokenCount_ - 1);
718 for (const Token *t = tokens_; t != last; ++t) {
719 switch (v->GetType()) {
722 typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
723 if (m == v->MemberEnd())
729 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
731 v = &((*v)[t->index]);
738 switch (v->GetType()) {
740 return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
742 if (last->index == kPointerInvalidIndex || last->index >= v->Size())
744 v->Erase(v->Begin() + last->index);
752 //! Clone the content from rhs to this.
754 \param rhs Source pointer.
755 \param extraToken Extra tokens to be allocated.
756 \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated.
757 \return Start of non-occupied name buffer, for storing extra names.
759 Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
760 if (!allocator_) // allocator is independently owned.
761 ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
763 size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
764 for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
765 nameBufferSize += t->length;
767 tokenCount_ = rhs.tokenCount_ + extraToken;
768 tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
769 nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
770 if (rhs.tokenCount_ > 0) {
771 std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
773 if (nameBufferSize > 0) {
774 std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
777 // Adjust pointers to name buffer
778 std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
779 for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
782 return nameBuffer_ + nameBufferSize;
785 //! Check whether a character should be percent-encoded.
787 According to RFC 3986 2.3 Unreserved Characters.
788 \param c The character (code unit) to be tested.
790 bool NeedPercentEncode(Ch c) const {
791 return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
794 //! Parse a JSON String or its URI fragment representation into tokens.
795 #ifndef __clang__ // -Wdocumentation
797 \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated.
798 \param length Length of the source string.
799 \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped.
802 void Parse(const Ch* source, size_t length) {
803 RAPIDJSON_ASSERT(source != NULL);
804 RAPIDJSON_ASSERT(nameBuffer_ == 0);
805 RAPIDJSON_ASSERT(tokens_ == 0);
807 // Create own allocator if user did not supply.
809 ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
811 // Count number of '/' as tokenCount
813 for (const Ch* s = source; s != source + length; s++)
817 Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
818 Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
821 // Detect if it is a URI fragment
822 bool uriFragment = false;
823 if (source[i] == '#') {
828 if (i != length && source[i] != '/') {
829 parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus;
834 RAPIDJSON_ASSERT(source[i] == '/');
838 bool isNumber = true;
840 while (i < length && source[i] != '/') {
843 // Decoding percent-encoding for URI fragment
845 PercentDecodeStream is(&source[i], source + length);
846 GenericInsituStringStream<EncodingType> os(name);
847 Ch* begin = os.PutBegin();
848 if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
849 parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding;
852 size_t len = os.PutEnd(begin);
863 else if (NeedPercentEncode(c)) {
864 parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode;
871 // Escaping "~0" -> '~', "~1" -> '/'
875 if (c == '0') c = '~';
876 else if (c == '1') c = '/';
878 parseErrorCode_ = kPointerParseErrorInvalidEscape;
884 parseErrorCode_ = kPointerParseErrorInvalidEscape;
889 // First check for index: all of characters are digit
890 if (c < '0' || c > '9')
895 token->length = static_cast<SizeType>(name - token->name);
896 if (token->length == 0)
898 *name++ = '\0'; // Null terminator
900 // Second check for index: more than one digit cannot have leading zero
901 if (isNumber && token->length > 1 && token->name[0] == '0')
904 // String to SizeType conversion
907 for (size_t j = 0; j < token->length; j++) {
908 SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
909 if (m < n) { // overflow detection
917 token->index = isNumber ? n : kPointerInvalidIndex;
921 RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
922 parseErrorCode_ = kPointerParseErrorNone;
926 Allocator::Free(tokens_);
930 parseErrorOffset_ = i;
934 //! Stringify to string or URI fragment representation.
936 \tparam uriFragment True for stringifying to URI fragment representation. False for string representation.
937 \tparam OutputStream type of output stream.
938 \param os The output stream.
940 template<bool uriFragment, typename OutputStream>
941 bool Stringify(OutputStream& os) const {
942 RAPIDJSON_ASSERT(IsValid());
947 for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
949 for (size_t j = 0; j < t->length; j++) {
959 else if (uriFragment && NeedPercentEncode(c)) {
960 // Transcode to UTF8 sequence
961 GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
962 PercentEncodeStream<OutputStream> target(os);
963 if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
965 j += source.Tell() - 1;
974 //! A helper stream for decoding a percent-encoded sequence into code unit.
976 This stream decodes %XY triplet into code unit (0-255).
977 If it encounters invalid characters, it sets output code unit as 0 and
978 mark invalid, and to be checked by IsValid().
980 class PercentDecodeStream {
982 typedef typename ValueType::Ch Ch;
986 \param source Start of the stream
987 \param end Past-the-end of the stream.
989 PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
992 if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
998 for (int j = 0; j < 2; j++) {
999 c = static_cast<Ch>(c << 4);
1001 if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
1002 else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
1003 else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
1013 size_t Tell() const { return static_cast<size_t>(src_ - head_); }
1014 bool IsValid() const { return valid_; }
1017 const Ch* src_; //!< Current read position.
1018 const Ch* head_; //!< Original head of the string.
1019 const Ch* end_; //!< Past-the-end position.
1020 bool valid_; //!< Whether the parsing is valid.
1023 //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
1024 template <typename OutputStream>
1025 class PercentEncodeStream {
1027 PercentEncodeStream(OutputStream& os) : os_(os) {}
1028 void Put(char c) { // UTF-8 must be byte
1029 unsigned char u = static_cast<unsigned char>(c);
1030 static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1032 os_.Put(hexDigits[u >> 4]);
1033 os_.Put(hexDigits[u & 15]);
1039 Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
1040 Allocator* ownAllocator_; //!< Allocator owned by this Pointer.
1041 Ch* nameBuffer_; //!< A buffer containing all names in tokens.
1042 Token* tokens_; //!< A list of tokens.
1043 size_t tokenCount_; //!< Number of tokens in tokens_.
1044 size_t parseErrorOffset_; //!< Offset in code unit when parsing fail.
1045 PointerParseErrorCode parseErrorCode_; //!< Parsing error code.
1048 //! GenericPointer for Value (UTF-8, default allocator).
1049 typedef GenericPointer<Value> Pointer;
1051 //!@name Helper functions for GenericPointer
1054 //////////////////////////////////////////////////////////////////////////////
1056 template <typename T>
1057 typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
1058 return pointer.Create(root, a);
1061 template <typename T, typename CharType, size_t N>
1062 typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
1063 return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
1066 // No allocator parameter
1068 template <typename DocumentType>
1069 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
1070 return pointer.Create(document);
1073 template <typename DocumentType, typename CharType, size_t N>
1074 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
1075 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
1078 //////////////////////////////////////////////////////////////////////////////
1080 template <typename T>
1081 typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1082 return pointer.Get(root, unresolvedTokenIndex);
1085 template <typename T>
1086 const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1087 return pointer.Get(root, unresolvedTokenIndex);
1090 template <typename T, typename CharType, size_t N>
1091 typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
1092 return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1095 template <typename T, typename CharType, size_t N>
1096 const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
1097 return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1100 //////////////////////////////////////////////////////////////////////////////
1102 template <typename T>
1103 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1104 return pointer.GetWithDefault(root, defaultValue, a);
1107 template <typename T>
1108 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1109 return pointer.GetWithDefault(root, defaultValue, a);
1112 #if RAPIDJSON_HAS_STDSTRING
1113 template <typename T>
1114 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1115 return pointer.GetWithDefault(root, defaultValue, a);
1119 template <typename T, typename T2>
1120 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1121 GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
1122 return pointer.GetWithDefault(root, defaultValue, a);
1125 template <typename T, typename CharType, size_t N>
1126 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1127 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1130 template <typename T, typename CharType, size_t N>
1131 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1132 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1135 #if RAPIDJSON_HAS_STDSTRING
1136 template <typename T, typename CharType, size_t N>
1137 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1138 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1142 template <typename T, typename CharType, size_t N, typename T2>
1143 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1144 GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
1145 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1148 // No allocator parameter
1150 template <typename DocumentType>
1151 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
1152 return pointer.GetWithDefault(document, defaultValue);
1155 template <typename DocumentType>
1156 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
1157 return pointer.GetWithDefault(document, defaultValue);
1160 #if RAPIDJSON_HAS_STDSTRING
1161 template <typename DocumentType>
1162 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1163 return pointer.GetWithDefault(document, defaultValue);
1167 template <typename DocumentType, typename T2>
1168 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1169 GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
1170 return pointer.GetWithDefault(document, defaultValue);
1173 template <typename DocumentType, typename CharType, size_t N>
1174 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
1175 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1178 template <typename DocumentType, typename CharType, size_t N>
1179 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
1180 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1183 #if RAPIDJSON_HAS_STDSTRING
1184 template <typename DocumentType, typename CharType, size_t N>
1185 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1186 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1190 template <typename DocumentType, typename CharType, size_t N, typename T2>
1191 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1192 GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
1193 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1196 //////////////////////////////////////////////////////////////////////////////
1198 template <typename T>
1199 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1200 return pointer.Set(root, value, a);
1203 template <typename T>
1204 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
1205 return pointer.Set(root, value, a);
1208 template <typename T>
1209 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
1210 return pointer.Set(root, value, a);
1213 #if RAPIDJSON_HAS_STDSTRING
1214 template <typename T>
1215 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1216 return pointer.Set(root, value, a);
1220 template <typename T, typename T2>
1221 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1222 SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
1223 return pointer.Set(root, value, a);
1226 template <typename T, typename CharType, size_t N>
1227 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1228 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1231 template <typename T, typename CharType, size_t N>
1232 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
1233 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1236 template <typename T, typename CharType, size_t N>
1237 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
1238 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1241 #if RAPIDJSON_HAS_STDSTRING
1242 template <typename T, typename CharType, size_t N>
1243 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1244 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1248 template <typename T, typename CharType, size_t N, typename T2>
1249 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1250 SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
1251 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1254 // No allocator parameter
1256 template <typename DocumentType>
1257 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1258 return pointer.Set(document, value);
1261 template <typename DocumentType>
1262 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
1263 return pointer.Set(document, value);
1266 template <typename DocumentType>
1267 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
1268 return pointer.Set(document, value);
1271 #if RAPIDJSON_HAS_STDSTRING
1272 template <typename DocumentType>
1273 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
1274 return pointer.Set(document, value);
1278 template <typename DocumentType, typename T2>
1279 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1280 SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
1281 return pointer.Set(document, value);
1284 template <typename DocumentType, typename CharType, size_t N>
1285 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1286 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1289 template <typename DocumentType, typename CharType, size_t N>
1290 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
1291 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1294 template <typename DocumentType, typename CharType, size_t N>
1295 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
1296 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1299 #if RAPIDJSON_HAS_STDSTRING
1300 template <typename DocumentType, typename CharType, size_t N>
1301 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
1302 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1306 template <typename DocumentType, typename CharType, size_t N, typename T2>
1307 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1308 SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
1309 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1312 //////////////////////////////////////////////////////////////////////////////
1314 template <typename T>
1315 typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1316 return pointer.Swap(root, value, a);
1319 template <typename T, typename CharType, size_t N>
1320 typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1321 return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
1324 template <typename DocumentType>
1325 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1326 return pointer.Swap(document, value);
1329 template <typename DocumentType, typename CharType, size_t N>
1330 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1331 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
1334 //////////////////////////////////////////////////////////////////////////////
1336 template <typename T>
1337 bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
1338 return pointer.Erase(root);
1341 template <typename T, typename CharType, size_t N>
1342 bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
1343 return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
1348 RAPIDJSON_NAMESPACE_END
1358 #endif // RAPIDJSON_POINTER_H_