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)
24 #elif defined(_MSC_VER)
26 RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
29 RAPIDJSON_NAMESPACE_BEGIN
31 static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token
33 //! Error code of parsing.
34 /*! \ingroup RAPIDJSON_ERRORS
35 \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
37 enum PointerParseErrorCode {
38 kPointerParseErrorNone = 0, //!< The parse is successful
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
46 ///////////////////////////////////////////////////////////////////////////////
49 //! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
51 This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer"
52 (https://tools.ietf.org/html/rfc6901).
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.
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
63 Contrary to GenericValue, Pointer can be copy constructed and copy assigned.
64 Apart from assignment, a Pointer cannot be modified after construction.
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.
70 GenericPointer depends on GenericDocument and GenericValue.
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.
75 \note GenericPointer uses same encoding of ValueType.
76 However, Allocator of GenericPointer is independent of Allocator of Value.
78 template <typename ValueType, typename Allocator = CrtAllocator>
79 class GenericPointer {
81 typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
82 typedef typename ValueType::Ch Ch; //!< Character type from Value
84 //! A token is the basic units of internal representation.
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).
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).
94 This struct is public so that user can create a Pointer without parsing and
95 allocation, using a special constructor.
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.
103 //!@name Constructors and destructor.
106 //! Default constructor.
107 GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
109 //! Constructor that parses a string or URI fragment representation.
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.
114 explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
115 Parse(source, internal::StrLen(source));
118 #if RAPIDJSON_HAS_STDSTRING
119 //! Constructor that parses a string or URI fragment representation.
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.
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());
130 //! Constructor that parses a string or URI fragment representation, with length of the source string.
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.
137 GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
138 Parse(source, length);
141 //! Constructor with user-supplied tokens.
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.
147 \param tokens An constant array of tokens representing the JSON pointer.
148 \param tokenCount Number of tokens.
152 #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }
153 #define INDEX(i) { #i, sizeof(#i) - 1, i }
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");
163 GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
165 //! Copy constructor.
166 GenericPointer(const GenericPointer& rhs) : allocator_(rhs.allocator_), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
170 //! Copy constructor.
171 GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
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_);
182 //! Assignment operator.
183 GenericPointer& operator=(const GenericPointer& rhs) {
185 // Do not delete ownAllcator
187 Allocator::Free(tokens_);
189 tokenCount_ = rhs.tokenCount_;
190 parseErrorOffset_ = rhs.parseErrorOffset_;
191 parseErrorCode_ = rhs.parseErrorCode_;
194 CopyFromRaw(rhs); // Normally parsed tokens.
196 tokens_ = rhs.tokens_; // User supplied const tokens.
205 //!@name Append token
208 //! Append a token and return a new Pointer
210 \param token Token to be appended.
211 \param allocator Allocator for the newly return Pointer.
212 \return A new Pointer with appended token.
214 GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
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;
225 //! Append a name token with length, and return a new Pointer
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.
232 GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
233 Token token = { name, length, kPointerInvalidIndex };
234 return Append(token, allocator);
237 //! Append a name token without length, and return a new Pointer
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.
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);
249 #if RAPIDJSON_HAS_STDSTRING
250 //! Append a name token, and return a new Pointer
252 \param name Name to be appended.
253 \param allocator Allocator for the newly return Pointer.
254 \return A new Pointer with appended token.
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);
261 //! Append a index token, and return a new Pointer
263 \param index Index to be appended.
264 \param allocator Allocator for the newly return Pointer.
265 \return A new Pointer with appended token.
267 GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
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';
273 if (sizeof(Ch) == 1) {
274 Token token = { reinterpret_cast<Ch*>(buffer), length, index };
275 return Append(token, allocator);
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);
286 //! Append a token by value, and return a new Pointer
288 \param token token to be appended.
289 \param allocator Allocator for the newly return Pointer.
290 \return A new Pointer with appended token.
292 GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
293 if (token.IsString())
294 return Append(token.GetString(), token.GetStringLength(), allocator);
296 RAPIDJSON_ASSERT(token.IsUint64());
297 RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
298 return Append(static_cast<SizeType>(token.GetUint64()), allocator);
302 //!@name Handling Parse Error
305 //! Check whether this is a valid pointer.
306 bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
308 //! Get the parsing error offset in code unit.
309 size_t GetParseErrorOffset() const { return parseErrorOffset_; }
311 //! Get the parsing error code.
312 PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
316 //! Get the allocator of this pointer.
317 Allocator& GetAllocator() { return *allocator_; }
322 //! Get the token array (const version only).
323 const Token* GetTokens() const { return tokens_; }
325 //! Get the number of tokens.
326 size_t GetTokenCount() const { return tokenCount_; }
330 //!@name Equality/inequality operators
333 //! Equality operator.
335 \note When any pointers are invalid, always returns false.
337 bool operator==(const GenericPointer& rhs) const {
338 if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
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))
353 //! Inequality operator.
355 \note When any pointers are invalid, always returns true.
357 bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
364 //! Stringify the pointer into string representation.
366 \tparam OutputStream Type of output stream.
367 \param os The output stream.
369 template<typename OutputStream>
370 bool Stringify(OutputStream& os) const {
371 return Stringify<false, OutputStream>(os);
374 //! Stringify the pointer into URI fragment representation.
376 \tparam OutputStream Type of output stream.
377 \param os The output stream.
379 template<typename OutputStream>
380 bool StringifyUriFragment(OutputStream& os) const {
381 return Stringify<true, OutputStream>(os);
386 //!@name Create value
389 //! Create a value in a subtree.
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.
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.
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.
404 ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
405 RAPIDJSON_ASSERT(IsValid());
406 ValueType* v = &root;
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]);
415 if (t->index == kPointerInvalidIndex) { // must be object name
417 v->SetObject(); // Change to Object
419 else { // object name or array index
420 if (!v->IsArray() && !v->IsObject())
421 v->SetArray(); // Change to Array
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);
431 v = &((*v)[t->index]);
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
447 *alreadyExist = exist;
452 //! Creates a value in a document.
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.
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);
468 //! Query a value in a subtree.
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.
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.
480 Use unresolvedTokenIndex to retrieve the token index.
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()) {
489 typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
490 if (m == v->MemberEnd())
496 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
498 v = &((*v)[t->index]);
504 // Error: unresolved token
505 if (unresolvedTokenIndex)
506 *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
512 //! Query a const value in a const subtree.
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.
517 const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
518 return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
523 //!@name Query a value with default
526 //! Query a value in a subtree with default value.
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.
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.
536 ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
538 ValueType& v = Create(root, allocator, &alreadyExist);
539 return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
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 {
545 ValueType& v = Create(root, allocator, &alreadyExist);
546 return alreadyExist ? v : v.SetString(defaultValue, allocator);
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 {
553 ValueType& v = Create(root, allocator, &alreadyExist);
554 return alreadyExist ? v : v.SetString(defaultValue, allocator);
558 //! Query a value in a subtree with default primitive value.
560 \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
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);
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());
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());
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());
588 //! Query a value in a document with default primitive value.
590 \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
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());
603 //! Set a value in a subtree, with move semantics.
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.
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.
613 ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
614 return Create(root, allocator) = value;
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);
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();
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();
634 //! Set a primitive value in a subtree.
636 \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
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();
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;
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());
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();
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();
670 //! Set a primitive value in a document.
672 \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
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;
682 //!@name Swap a value
685 //! Swap a value with a value in a subtree.
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.
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.
695 ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
696 return Create(root, allocator).Swap(value);
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);
707 //! Erase a value in a subtree.
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.
712 \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false.
714 bool Erase(ValueType& root) const {
715 RAPIDJSON_ASSERT(IsValid());
716 if (tokenCount_ == 0) // Cannot erase the root
719 ValueType* v = &root;
720 const Token* last = tokens_ + (tokenCount_ - 1);
721 for (const Token *t = tokens_; t != last; ++t) {
722 switch (v->GetType()) {
725 typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
726 if (m == v->MemberEnd())
732 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
734 v = &((*v)[t->index]);
741 switch (v->GetType()) {
743 return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
745 if (last->index == kPointerInvalidIndex || last->index >= v->Size())
747 v->Erase(v->Begin() + last->index);
755 //! Clone the content from rhs to this.
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.
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)();
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;
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));
776 if (nameBufferSize > 0) {
777 std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
780 // Adjust pointers to name buffer
781 std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
782 for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
785 return nameBuffer_ + nameBufferSize;
788 //! Check whether a character should be percent-encoded.
790 According to RFC 3986 2.3 Unreserved Characters.
791 \param c The character (code unit) to be tested.
793 bool NeedPercentEncode(Ch c) const {
794 return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
797 //! Parse a JSON String or its URI fragment representation into tokens.
798 #ifndef __clang__ // -Wdocumentation
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.
805 void Parse(const Ch* source, size_t length) {
806 RAPIDJSON_ASSERT(source != NULL);
807 RAPIDJSON_ASSERT(nameBuffer_ == 0);
808 RAPIDJSON_ASSERT(tokens_ == 0);
810 // Create own allocator if user did not supply.
812 ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
814 // Count number of '/' as tokenCount
816 for (const Ch* s = source; s != source + length; s++)
820 Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
821 Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
824 // Detect if it is a URI fragment
825 bool uriFragment = false;
826 if (source[i] == '#') {
831 if (i != length && source[i] != '/') {
832 parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus;
837 RAPIDJSON_ASSERT(source[i] == '/');
841 bool isNumber = true;
843 while (i < length && source[i] != '/') {
846 // Decoding percent-encoding for URI fragment
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;
855 size_t len = os.PutEnd(begin);
866 else if (NeedPercentEncode(c)) {
867 parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode;
874 // Escaping "~0" -> '~', "~1" -> '/'
878 if (c == '0') c = '~';
879 else if (c == '1') c = '/';
881 parseErrorCode_ = kPointerParseErrorInvalidEscape;
887 parseErrorCode_ = kPointerParseErrorInvalidEscape;
892 // First check for index: all of characters are digit
893 if (c < '0' || c > '9')
898 token->length = static_cast<SizeType>(name - token->name);
899 if (token->length == 0)
901 *name++ = '\0'; // Null terminator
903 // Second check for index: more than one digit cannot have leading zero
904 if (isNumber && token->length > 1 && token->name[0] == '0')
907 // String to SizeType conversion
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
920 token->index = isNumber ? n : kPointerInvalidIndex;
924 RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
925 parseErrorCode_ = kPointerParseErrorNone;
929 Allocator::Free(tokens_);
933 parseErrorOffset_ = i;
937 //! Stringify to string or URI fragment representation.
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.
943 template<bool uriFragment, typename OutputStream>
944 bool Stringify(OutputStream& os) const {
945 RAPIDJSON_ASSERT(IsValid());
950 for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
952 for (size_t j = 0; j < t->length; j++) {
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))
968 j += source.Tell() - 1;
977 //! A helper stream for decoding a percent-encoded sequence into code unit.
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().
983 class PercentDecodeStream {
985 typedef typename ValueType::Ch Ch;
989 \param source Start of the stream
990 \param end Past-the-end of the stream.
992 PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
995 if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
1001 for (int j = 0; j < 2; j++) {
1002 c = static_cast<Ch>(c << 4);
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);
1016 size_t Tell() const { return static_cast<size_t>(src_ - head_); }
1017 bool IsValid() const { return valid_; }
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.
1026 //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
1027 template <typename OutputStream>
1028 class PercentEncodeStream {
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' };
1035 os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
1036 os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
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.
1051 //! GenericPointer for Value (UTF-8, default allocator).
1052 typedef GenericPointer<Value> Pointer;
1054 //!@name Helper functions for GenericPointer
1057 //////////////////////////////////////////////////////////////////////////////
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);
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);
1069 // No allocator parameter
1071 template <typename DocumentType>
1072 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
1073 return pointer.Create(document);
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);
1081 //////////////////////////////////////////////////////////////////////////////
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);
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);
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);
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);
1103 //////////////////////////////////////////////////////////////////////////////
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);
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);
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);
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);
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);
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);
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);
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);
1151 // No allocator parameter
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);
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);
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);
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);
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);
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);
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);
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);
1199 //////////////////////////////////////////////////////////////////////////////
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1257 // No allocator parameter
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1315 //////////////////////////////////////////////////////////////////////////////
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);
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);
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);
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);
1337 //////////////////////////////////////////////////////////////////////////////
1339 template <typename T>
1340 bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
1341 return pointer.Erase(root);
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);
1351 RAPIDJSON_NAMESPACE_END
1353 #if defined(__clang__) || defined(_MSC_VER)
1357 #endif // RAPIDJSON_POINTER_H_