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