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