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 
22 #ifdef __clang__
23 RAPIDJSON_DIAG_PUSH
24 RAPIDJSON_DIAG_OFF(switch-enum)
25 #elif defined(_MSC_VER)
26 RAPIDJSON_DIAG_PUSH
27 RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
28 #endif
29 
30 RAPIDJSON_NAMESPACE_BEGIN
31 
32 static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token
33 
34 //! Error code of parsing.
35 /*! \ingroup RAPIDJSON_ERRORS
36  \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
37 */
39  kPointerParseErrorNone = 0, //!< The parse is successful
40 
41  kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/'
42  kPointerParseErrorInvalidEscape, //!< Invalid escape
43  kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment
44  kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment
45 };
46 
47 ///////////////////////////////////////////////////////////////////////////////
48 // GenericPointer
49 
50 //! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
51 /*!
52  This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer"
53  (https://tools.ietf.org/html/rfc6901).
54 
55  A JSON pointer is for identifying a specific value in a JSON document
56  (GenericDocument). It can simplify coding of DOM tree manipulation, because it
57  can access multiple-level depth of DOM tree with single API call.
58 
59  After it parses a string representation (e.g. "/foo/0" or URI fragment
60  representation (e.g. "#/foo/0") into its internal representation (tokens),
61  it can be used to resolve a specific value in multiple documents, or sub-tree
62  of documents.
63 
64  Contrary to GenericValue, Pointer can be copy constructed and copy assigned.
65  Apart from assignment, a Pointer cannot be modified after construction.
66 
67  Although Pointer is very convenient, please aware that constructing Pointer
68  involves parsing and dynamic memory allocation. A special constructor with user-
69  supplied tokens eliminates these.
70 
71  GenericPointer depends on GenericDocument and GenericValue.
72 
73  \tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> >
74  \tparam Allocator The allocator type for allocating memory for internal representation.
75 
76  \note GenericPointer uses same encoding of ValueType.
77  However, Allocator of GenericPointer is independent of Allocator of Value.
78 */
79 template <typename ValueType, typename Allocator = CrtAllocator>
80 class GenericPointer {
81 public:
82  typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
83  typedef typename ValueType::Ch Ch; //!< Character type from Value
85 
86 
87  //! A token is the basic units of internal representation.
88  /*!
89  A JSON pointer string representation "/foo/123" is parsed to two tokens:
90  "foo" and 123. 123 will be represented in both numeric form and string form.
91  They are resolved according to the actual value type (object or array).
92 
93  For token that are not numbers, or the numeric value is out of bound
94  (greater than limits of SizeType), they are only treated as string form
95  (i.e. the token's index will be equal to kPointerInvalidIndex).
96 
97  This struct is public so that user can create a Pointer without parsing and
98  allocation, using a special constructor.
99  */
100  struct Token {
101  const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character.
102  SizeType length; //!< Length of the name.
103  SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex.
104  };
105 
106  //!@name Constructors and destructor.
107  //@{
108 
109  //! Default constructor.
110  GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
111 
112  //! Constructor that parses a string or URI fragment representation.
113  /*!
114  \param source A null-terminated, string or URI fragment representation of JSON pointer.
115  \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
116  */
117  explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
118  Parse(source, internal::StrLen(source));
119  }
120 
121 #if RAPIDJSON_HAS_STDSTRING
122  //! Constructor that parses a string or URI fragment representation.
123  /*!
124  \param source A string or URI fragment representation of JSON pointer.
125  \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
126  \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
127  */
128  explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
129  Parse(source.c_str(), source.size());
130  }
131 #endif
132 
133  //! Constructor that parses a string or URI fragment representation, with length of the source string.
134  /*!
135  \param source A string or URI fragment representation of JSON pointer.
136  \param length Length of source.
137  \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
138  \note Slightly faster than the overload without length.
139  */
140  GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
141  Parse(source, length);
142  }
143 
144  //! Constructor with user-supplied tokens.
145  /*!
146  This constructor let user supplies const array of tokens.
147  This prevents the parsing process and eliminates allocation.
148  This is preferred for memory constrained environments.
149 
150  \param tokens An constant array of tokens representing the JSON pointer.
151  \param tokenCount Number of tokens.
152 
153  \b Example
154  \code
155  #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }
156  #define INDEX(i) { #i, sizeof(#i) - 1, i }
157 
158  static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) };
159  static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
160  // Equivalent to static const Pointer p("/foo/123");
161 
162  #undef NAME
163  #undef INDEX
164  \endcode
165  */
166  GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
167 
168  //! Copy constructor.
169  GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
170  *this = rhs;
171  }
172 
173  //! Copy constructor.
174  GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
175  *this = rhs;
176  }
177 
178  //! Destructor.
180  if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
181  Allocator::Free(tokens_);
182  RAPIDJSON_DELETE(ownAllocator_);
183  }
184 
185  //! Assignment operator.
187  if (this != &rhs) {
188  // Do not delete ownAllcator
189  if (nameBuffer_)
190  Allocator::Free(tokens_);
191 
192  tokenCount_ = rhs.tokenCount_;
193  parseErrorOffset_ = rhs.parseErrorOffset_;
194  parseErrorCode_ = rhs.parseErrorCode_;
195 
196  if (rhs.nameBuffer_)
197  CopyFromRaw(rhs); // Normally parsed tokens.
198  else {
199  tokens_ = rhs.tokens_; // User supplied const tokens.
200  nameBuffer_ = 0;
201  }
202  }
203  return *this;
204  }
205 
206  //! Swap the content of this pointer with an other.
207  /*!
208  \param other The pointer to swap with.
209  \note Constant complexity.
210  */
211  GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT {
212  internal::Swap(allocator_, other.allocator_);
213  internal::Swap(ownAllocator_, other.ownAllocator_);
214  internal::Swap(nameBuffer_, other.nameBuffer_);
215  internal::Swap(tokens_, other.tokens_);
216  internal::Swap(tokenCount_, other.tokenCount_);
217  internal::Swap(parseErrorOffset_, other.parseErrorOffset_);
218  internal::Swap(parseErrorCode_, other.parseErrorCode_);
219  return *this;
220  }
221 
222  //! free-standing swap function helper
223  /*!
224  Helper function to enable support for common swap implementation pattern based on \c std::swap:
225  \code
226  void swap(MyClass& a, MyClass& b) {
227  using std::swap;
228  swap(a.pointer, b.pointer);
229  // ...
230  }
231  \endcode
232  \see Swap()
233  */
234  friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
235 
236  //@}
237 
238  //!@name Append token
239  //@{
240 
241  //! Append a token and return a new Pointer
242  /*!
243  \param token Token to be appended.
244  \param allocator Allocator for the newly return Pointer.
245  \return A new Pointer with appended token.
246  */
247  GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
248  GenericPointer r;
249  r.allocator_ = allocator;
250  Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
251  std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
252  r.tokens_[tokenCount_].name = p;
253  r.tokens_[tokenCount_].length = token.length;
254  r.tokens_[tokenCount_].index = token.index;
255  return r;
256  }
257 
258  //! Append a name token with length, and return a new Pointer
259  /*!
260  \param name Name to be appended.
261  \param length Length of name.
262  \param allocator Allocator for the newly return Pointer.
263  \return A new Pointer with appended token.
264  */
265  GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
266  Token token = { name, length, kPointerInvalidIndex };
267  return Append(token, allocator);
268  }
269 
270  //! Append a name token without length, and return a new Pointer
271  /*!
272  \param name Name (const Ch*) to be appended.
273  \param allocator Allocator for the newly return Pointer.
274  \return A new Pointer with appended token.
275  */
276  template <typename T>
277  RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
278  Append(T* name, Allocator* allocator = 0) const {
279  return Append(name, internal::StrLen(name), allocator);
280  }
281 
282 #if RAPIDJSON_HAS_STDSTRING
283  //! Append a name token, and return a new Pointer
284  /*!
285  \param name Name to be appended.
286  \param allocator Allocator for the newly return Pointer.
287  \return A new Pointer with appended token.
288  */
289  GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
290  return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
291  }
292 #endif
293 
294  //! Append a index token, and return a new Pointer
295  /*!
296  \param index Index to be appended.
297  \param allocator Allocator for the newly return Pointer.
298  \return A new Pointer with appended token.
299  */
300  GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
301  char buffer[21];
302  char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
303  SizeType length = static_cast<SizeType>(end - buffer);
304  buffer[length] = '\0';
305 
306  if (sizeof(Ch) == 1) {
307  Token token = { reinterpret_cast<Ch*>(buffer), length, index };
308  return Append(token, allocator);
309  }
310  else {
311  Ch name[21];
312  for (size_t i = 0; i <= length; i++)
313  name[i] = static_cast<Ch>(buffer[i]);
314  Token token = { name, length, index };
315  return Append(token, allocator);
316  }
317  }
318 
319  //! Append a token by value, and return a new Pointer
320  /*!
321  \param token token to be appended.
322  \param allocator Allocator for the newly return Pointer.
323  \return A new Pointer with appended token.
324  */
325  GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
326  if (token.IsString())
327  return Append(token.GetString(), token.GetStringLength(), allocator);
328  else {
329  RAPIDJSON_ASSERT(token.IsUint64());
330  RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
331  return Append(static_cast<SizeType>(token.GetUint64()), allocator);
332  }
333  }
334 
335  //!@name Handling Parse Error
336  //@{
337 
338  //! Check whether this is a valid pointer.
339  bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
340 
341  //! Get the parsing error offset in code unit.
342  size_t GetParseErrorOffset() const { return parseErrorOffset_; }
343 
344  //! Get the parsing error code.
345  PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
346 
347  //@}
348 
349  //! Get the allocator of this pointer.
350  Allocator& GetAllocator() { return *allocator_; }
351 
352  //!@name Tokens
353  //@{
354 
355  //! Get the token array (const version only).
356  const Token* GetTokens() const { return tokens_; }
357 
358  //! Get the number of tokens.
359  size_t GetTokenCount() const { return tokenCount_; }
360 
361  //@}
362 
363  //!@name Equality/inequality operators
364  //@{
365 
366  //! Equality operator.
367  /*!
368  \note When any pointers are invalid, always returns false.
369  */
370  bool operator==(const GenericPointer& rhs) const {
371  if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
372  return false;
373 
374  for (size_t i = 0; i < tokenCount_; i++) {
375  if (tokens_[i].index != rhs.tokens_[i].index ||
376  tokens_[i].length != rhs.tokens_[i].length ||
377  (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
378  {
379  return false;
380  }
381  }
382 
383  return true;
384  }
385 
386  //! Inequality operator.
387  /*!
388  \note When any pointers are invalid, always returns true.
389  */
390  bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
391 
392  //! Less than operator.
393  /*!
394  \note Invalid pointers are always greater than valid ones.
395  */
396  bool operator<(const GenericPointer& rhs) const {
397  if (!IsValid())
398  return false;
399  if (!rhs.IsValid())
400  return true;
401 
402  if (tokenCount_ != rhs.tokenCount_)
403  return tokenCount_ < rhs.tokenCount_;
404 
405  for (size_t i = 0; i < tokenCount_; i++) {
406  if (tokens_[i].index != rhs.tokens_[i].index)
407  return tokens_[i].index < rhs.tokens_[i].index;
408 
409  if (tokens_[i].length != rhs.tokens_[i].length)
410  return tokens_[i].length < rhs.tokens_[i].length;
411 
412  if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length))
413  return cmp < 0;
414  }
415 
416  return false;
417  }
418 
419  //@}
420 
421  //!@name Stringify
422  //@{
423 
424  //! Stringify the pointer into string representation.
425  /*!
426  \tparam OutputStream Type of output stream.
427  \param os The output stream.
428  */
429  template<typename OutputStream>
430  bool Stringify(OutputStream& os) const {
431  return Stringify<false, OutputStream>(os);
432  }
433 
434  //! Stringify the pointer into URI fragment representation.
435  /*!
436  \tparam OutputStream Type of output stream.
437  \param os The output stream.
438  */
439  template<typename OutputStream>
440  bool StringifyUriFragment(OutputStream& os) const {
441  return Stringify<true, OutputStream>(os);
442  }
443 
444  //@}
445 
446  //!@name Create value
447  //@{
448 
449  //! Create a value in a subtree.
450  /*!
451  If the value is not exist, it creates all parent values and a JSON Null value.
452  So it always succeed and return the newly created or existing value.
453 
454  Remind that it may change types of parents according to tokens, so it
455  potentially removes previously stored values. For example, if a document
456  was an array, and "/foo" is used to create a value, then the document
457  will be changed to an object, and all existing array elements are lost.
458 
459  \param root Root value of a DOM subtree to be resolved. It can be any value other than document root.
460  \param allocator Allocator for creating the values if the specified value or its parents are not exist.
461  \param alreadyExist If non-null, it stores whether the resolved value is already exist.
462  \return The resolved newly created (a JSON Null value), or already exists value.
463  */
464  ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
465  RAPIDJSON_ASSERT(IsValid());
466  ValueType* v = &root;
467  bool exist = true;
468  for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
469  if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
470  v->PushBack(ValueType().Move(), allocator);
471  v = &((*v)[v->Size() - 1]);
472  exist = false;
473  }
474  else {
475  if (t->index == kPointerInvalidIndex) { // must be object name
476  if (!v->IsObject())
477  v->SetObject(); // Change to Object
478  }
479  else { // object name or array index
480  if (!v->IsArray() && !v->IsObject())
481  v->SetArray(); // Change to Array
482  }
483 
484  if (v->IsArray()) {
485  if (t->index >= v->Size()) {
486  v->Reserve(t->index + 1, allocator);
487  while (t->index >= v->Size())
488  v->PushBack(ValueType().Move(), allocator);
489  exist = false;
490  }
491  v = &((*v)[t->index]);
492  }
493  else {
494  typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
495  if (m == v->MemberEnd()) {
496  v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
497  m = v->MemberEnd();
498  v = &(--m)->value; // Assumes AddMember() appends at the end
499  exist = false;
500  }
501  else
502  v = &m->value;
503  }
504  }
505  }
506 
507  if (alreadyExist)
508  *alreadyExist = exist;
509 
510  return *v;
511  }
512 
513  //! Creates a value in a document.
514  /*!
515  \param document A document to be resolved.
516  \param alreadyExist If non-null, it stores whether the resolved value is already exist.
517  \return The resolved newly created, or already exists value.
518  */
519  template <typename stackAllocator>
521  return Create(document, document.GetAllocator(), alreadyExist);
522  }
523 
524  //@}
525 
526  //!@name Compute URI
527  //@{
528 
529  //! Compute the in-scope URI for a subtree.
530  // For use with JSON pointers into JSON schema documents.
531  /*!
532  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
533  \param rootUri Root URI
534  \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
535  \param allocator Allocator for Uris
536  \return Uri if it can be resolved. Otherwise null.
537 
538  \note
539  There are only 3 situations when a URI cannot be resolved:
540  1. A value in the path is not an array nor object.
541  2. An object value does not contain the token.
542  3. A token is out of range of an array value.
543 
544  Use unresolvedTokenIndex to retrieve the token index.
545  */
546  UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
547  static const Ch kIdString[] = { 'i', 'd', '\0' };
548  static const ValueType kIdValue(kIdString, 2);
549  UriType base = UriType(rootUri, allocator);
550  RAPIDJSON_ASSERT(IsValid());
551  ValueType* v = &root;
552  for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
553  switch (v->GetType()) {
554  case kObjectType:
555  {
556  // See if we have an id, and if so resolve with the current base
557  typename ValueType::MemberIterator m = v->FindMember(kIdValue);
558  if (m != v->MemberEnd() && (m->value).IsString()) {
559  UriType here = UriType(m->value, allocator).Resolve(base, allocator);
560  base = here;
561  }
562  m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
563  if (m == v->MemberEnd())
564  break;
565  v = &m->value;
566  }
567  continue;
568  case kArrayType:
569  if (t->index == kPointerInvalidIndex || t->index >= v->Size())
570  break;
571  v = &((*v)[t->index]);
572  continue;
573  default:
574  break;
575  }
576 
577  // Error: unresolved token
578  if (unresolvedTokenIndex)
579  *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
580  return UriType(allocator);
581  }
582  return base;
583  }
584 
585  UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
586  return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex, allocator);
587  }
588 
589 
590  //!@name Query value
591  //@{
592 
593  //! Query a value in a subtree.
594  /*!
595  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
596  \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
597  \return Pointer to the value if it can be resolved. Otherwise null.
598 
599  \note
600  There are only 3 situations when a value cannot be resolved:
601  1. A value in the path is not an array nor object.
602  2. An object value does not contain the token.
603  3. A token is out of range of an array value.
604 
605  Use unresolvedTokenIndex to retrieve the token index.
606  */
607  ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
608  RAPIDJSON_ASSERT(IsValid());
609  ValueType* v = &root;
610  for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
611  switch (v->GetType()) {
612  case kObjectType:
613  {
614  typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
615  if (m == v->MemberEnd())
616  break;
617  v = &m->value;
618  }
619  continue;
620  case kArrayType:
621  if (t->index == kPointerInvalidIndex || t->index >= v->Size())
622  break;
623  v = &((*v)[t->index]);
624  continue;
625  default:
626  break;
627  }
628 
629  // Error: unresolved token
630  if (unresolvedTokenIndex)
631  *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
632  return 0;
633  }
634  return v;
635  }
636 
637  //! Query a const value in a const subtree.
638  /*!
639  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
640  \return Pointer to the value if it can be resolved. Otherwise null.
641  */
642  const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
643  return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
644  }
645 
646  //@}
647 
648  //!@name Query a value with default
649  //@{
650 
651  //! Query a value in a subtree with default value.
652  /*!
653  Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value.
654  So that this function always succeed.
655 
656  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
657  \param defaultValue Default value to be cloned if the value was not exists.
658  \param allocator Allocator for creating the values if the specified value or its parents are not exist.
659  \see Create()
660  */
661  ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
662  bool alreadyExist;
663  ValueType& v = Create(root, allocator, &alreadyExist);
664  return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
665  }
666 
667  //! Query a value in a subtree with default null-terminated string.
668  ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
669  bool alreadyExist;
670  ValueType& v = Create(root, allocator, &alreadyExist);
671  return alreadyExist ? v : v.SetString(defaultValue, allocator);
672  }
673 
674 #if RAPIDJSON_HAS_STDSTRING
675  //! Query a value in a subtree with default std::basic_string.
676  ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
677  bool alreadyExist;
678  ValueType& v = Create(root, allocator, &alreadyExist);
679  return alreadyExist ? v : v.SetString(defaultValue, allocator);
680  }
681 #endif
682 
683  //! Query a value in a subtree with default primitive value.
684  /*!
685  \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
686  */
687  template <typename T>
688  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
689  GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
690  return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
691  }
692 
693  //! Query a value in a document with default value.
694  template <typename stackAllocator>
696  return GetWithDefault(document, defaultValue, document.GetAllocator());
697  }
698 
699  //! Query a value in a document with default null-terminated string.
700  template <typename stackAllocator>
702  return GetWithDefault(document, defaultValue, document.GetAllocator());
703  }
704 
705 #if RAPIDJSON_HAS_STDSTRING
706  //! Query a value in a document with default std::basic_string.
707  template <typename stackAllocator>
708  ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
709  return GetWithDefault(document, defaultValue, document.GetAllocator());
710  }
711 #endif
712 
713  //! Query a value in a document with default primitive value.
714  /*!
715  \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
716  */
717  template <typename T, typename stackAllocator>
718  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
719  GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
720  return GetWithDefault(document, defaultValue, document.GetAllocator());
721  }
722 
723  //@}
724 
725  //!@name Set a value
726  //@{
727 
728  //! Set a value in a subtree, with move semantics.
729  /*!
730  It creates all parents if they are not exist or types are different to the tokens.
731  So this function always succeeds but potentially remove existing values.
732 
733  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
734  \param value Value to be set.
735  \param allocator Allocator for creating the values if the specified value or its parents are not exist.
736  \see Create()
737  */
738  ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
739  return Create(root, allocator) = value;
740  }
741 
742  //! Set a value in a subtree, with copy semantics.
743  ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
744  return Create(root, allocator).CopyFrom(value, allocator);
745  }
746 
747  //! Set a null-terminated string in a subtree.
748  ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
749  return Create(root, allocator) = ValueType(value, allocator).Move();
750  }
751 
752 #if RAPIDJSON_HAS_STDSTRING
753  //! Set a std::basic_string in a subtree.
754  ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
755  return Create(root, allocator) = ValueType(value, allocator).Move();
756  }
757 #endif
758 
759  //! Set a primitive value in a subtree.
760  /*!
761  \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
762  */
763  template <typename T>
764  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
765  Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
766  return Create(root, allocator) = ValueType(value).Move();
767  }
768 
769  //! Set a value in a document, with move semantics.
770  template <typename stackAllocator>
772  return Create(document) = value;
773  }
774 
775  //! Set a value in a document, with copy semantics.
776  template <typename stackAllocator>
777  ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {
778  return Create(document).CopyFrom(value, document.GetAllocator());
779  }
780 
781  //! Set a null-terminated string in a document.
782  template <typename stackAllocator>
784  return Create(document) = ValueType(value, document.GetAllocator()).Move();
785  }
786 
787 #if RAPIDJSON_HAS_STDSTRING
788  //! Sets a std::basic_string in a document.
789  template <typename stackAllocator>
790  ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
791  return Create(document) = ValueType(value, document.GetAllocator()).Move();
792  }
793 #endif
794 
795  //! Set a primitive value in a document.
796  /*!
797  \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
798  */
799  template <typename T, typename stackAllocator>
800  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
801  Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
802  return Create(document) = value;
803  }
804 
805  //@}
806 
807  //!@name Swap a value
808  //@{
809 
810  //! Swap a value with a value in a subtree.
811  /*!
812  It creates all parents if they are not exist or types are different to the tokens.
813  So this function always succeeds but potentially remove existing values.
814 
815  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
816  \param value Value to be swapped.
817  \param allocator Allocator for creating the values if the specified value or its parents are not exist.
818  \see Create()
819  */
820  ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
821  return Create(root, allocator).Swap(value);
822  }
823 
824  //! Swap a value with a value in a document.
825  template <typename stackAllocator>
827  return Create(document).Swap(value);
828  }
829 
830  //@}
831 
832  //! Erase a value in a subtree.
833  /*!
834  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
835  \return Whether the resolved value is found and erased.
836 
837  \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false.
838  */
839  bool Erase(ValueType& root) const {
840  RAPIDJSON_ASSERT(IsValid());
841  if (tokenCount_ == 0) // Cannot erase the root
842  return false;
843 
844  ValueType* v = &root;
845  const Token* last = tokens_ + (tokenCount_ - 1);
846  for (const Token *t = tokens_; t != last; ++t) {
847  switch (v->GetType()) {
848  case kObjectType:
849  {
850  typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
851  if (m == v->MemberEnd())
852  return false;
853  v = &m->value;
854  }
855  break;
856  case kArrayType:
857  if (t->index == kPointerInvalidIndex || t->index >= v->Size())
858  return false;
859  v = &((*v)[t->index]);
860  break;
861  default:
862  return false;
863  }
864  }
865 
866  switch (v->GetType()) {
867  case kObjectType:
868  return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
869  case kArrayType:
870  if (last->index == kPointerInvalidIndex || last->index >= v->Size())
871  return false;
872  v->Erase(v->Begin() + last->index);
873  return true;
874  default:
875  return false;
876  }
877  }
878 
879 private:
880  //! Clone the content from rhs to this.
881  /*!
882  \param rhs Source pointer.
883  \param extraToken Extra tokens to be allocated.
884  \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated.
885  \return Start of non-occupied name buffer, for storing extra names.
886  */
887  Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
888  if (!allocator_) // allocator is independently owned.
889  ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
890 
891  size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
892  for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
893  nameBufferSize += t->length;
894 
895  tokenCount_ = rhs.tokenCount_ + extraToken;
896  tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
897  nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
898  if (rhs.tokenCount_ > 0) {
899  std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
900  }
901  if (nameBufferSize > 0) {
902  std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
903  }
904 
905  // Adjust pointers to name buffer
906  std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
907  for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
908  t->name += diff;
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:174
Invalid escape
Definition: pointer.h:42
ValueType * Get(ValueType &root, size_t *unresolvedTokenIndex=0) const
Query a value in a subtree.
Definition: pointer.h:607
PointerParseErrorCode
Error code of parsing.
Definition: pointer.h:38
GenericPointer(const Token *tokens, size_t tokenCount)
Constructor with user-supplied tokens.
Definition: pointer.h:166
const Ch * name
Name of the token. It has null character at the end but it can contain null character.
Definition: pointer.h:101
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:140
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:695
bool operator==(const GenericPointer &rhs) const
Equality operator.
Definition: pointer.h:370
bool operator<(const GenericPointer &rhs) const
Less than operator.
Definition: pointer.h:396
~GenericPointer()
Destructor.
Definition: pointer.h:179
ValueType & Swap(ValueType &root, ValueType &value, typename ValueType::AllocatorType &allocator) const
Swap a value with a value in a subtree.
Definition: pointer.h:820
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:350
ValueType & Set(ValueType &root, ValueType &value, typename ValueType::AllocatorType &allocator) const
Set a value in a subtree, with move semantics.
Definition: pointer.h:738
bool Stringify(OutputStream &os) const
Stringify the pointer into string representation.
Definition: pointer.h:430
unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:415
The parse is successful
Definition: pointer.h:39
A character must percent encoded in URI fragment
Definition: pointer.h:44
SizeType length
Length of the name.
Definition: pointer.h:102
PointerParseErrorCode GetParseErrorCode() const
Get the parsing error code.
Definition: pointer.h:345
ValueType & Set(ValueType &root, const Ch *value, typename ValueType::AllocatorType &allocator) const
Set a null-terminated string in a subtree.
Definition: pointer.h:748
ValueType::Ch Ch
Character type from Value
Definition: pointer.h:83
A token must begin with a &#39;/&#39;
Definition: pointer.h:41
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:783
size_t GetTokenCount() const
Get the number of tokens.
Definition: pointer.h:359
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:708
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:676
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:754
ValueType::EncodingType EncodingType
Encoding type from Value
Definition: pointer.h:82
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition: rapidjson.h:712
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:701
bool StringifyUriFragment(OutputStream &os) const
Stringify the pointer into URI fragment representation.
Definition: pointer.h:440
ValueType & Create(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, bool *alreadyExist=0) const
Creates a value in a document.
Definition: pointer.h:520
GenericPointer(const Ch *source, Allocator *allocator=0)
Constructor that parses a string or URI fragment representation.
Definition: pointer.h:117
GenericPointer Append(const ValueType &token, Allocator *allocator=0) const
Append a token by value, and return a new Pointer
Definition: pointer.h:325
Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
Definition: fwd.h:126
Type
Type of JSON value
Definition: rapidjson.h:729
GenericPointer & operator=(const GenericPointer &rhs)
Assignment operator.
Definition: pointer.h:186
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:790
object
Definition: rapidjson.h:733
GenericPointer(Allocator *allocator=0)
Default constructor.
Definition: pointer.h:110
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:265
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:668
size_t GetParseErrorOffset() const
Get the parsing error offset in code unit.
Definition: pointer.h:342
friend void swap(GenericPointer &a, GenericPointer &b) RAPIDJSON_NOEXCEPT
free-standing swap function helper
Definition: pointer.h:234
A document for parsing JSON text as DOM.
Definition: document.h:69
array
Definition: rapidjson.h:734
GenericPointer Append(const std::basic_string< Ch > &name, Allocator *allocator=0) const
Append a name token, and return a new Pointer
Definition: pointer.h:289
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:716
ValueType & Swap(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, ValueType &value) const
Swap a value with a value in a document.
Definition: pointer.h:826
GenericPointer(const GenericPointer &rhs)
Copy constructor.
Definition: pointer.h:169
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:546
Allocator & GetAllocator()
Get the allocator of this document.
Definition: document.h:2795
GenericUri Resolve(const GenericUri &baseuri, Allocator *allocator=0)
Resolve this URI against another (base) URI in accordance with URI resolution rules.
Definition: uri.h:156
ValueType & Set(ValueType &root, const ValueType &value, typename ValueType::AllocatorType &allocator) const
Set a value in a subtree, with copy semantics.
Definition: pointer.h:743
GenericPointer Append(const Token &token, Allocator *allocator=0) const
Append a token and return a new Pointer
Definition: pointer.h:247
GenericPointer(const std::basic_string< Ch > &source, Allocator *allocator=0)
Constructor that parses a string or URI fragment representation.
Definition: pointer.h:128
A token is the basic units of internal representation.
Definition: pointer.h:100
const ValueType * Get(const ValueType &root, size_t *unresolvedTokenIndex=0) const
Query a const value in a const subtree.
Definition: pointer.h:642
GenericPointer & Swap(GenericPointer &other) RAPIDJSON_NOEXCEPT
Swap the content of this pointer with an other.
Definition: pointer.h:211
bool Erase(ValueType &root) const
Erase a value in a subtree.
Definition: pointer.h:839
bool operator!=(const GenericPointer &rhs) const
Inequality operator.
Definition: pointer.h:390
SizeType index
A valid array index, if it is not equal to kPointerInvalidIndex.
Definition: pointer.h:103
const Token * GetTokens() const
Get the token array (const version only).
Definition: pointer.h:356
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: pointer.h:43
ValueType & Create(ValueType &root, typename ValueType::AllocatorType &allocator, bool *alreadyExist=0) const
Create a value in a subtree.
Definition: pointer.h:464
bool IsValid() const
Check whether this is a valid pointer.
Definition: pointer.h:339
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:437
ValueType & GetWithDefault(ValueType &root, const ValueType &defaultValue, typename ValueType::AllocatorType &allocator) const
Query a value in a subtree with default value.
Definition: pointer.h:661
ValueType & Set(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, ValueType &value) const
Set a value in a document, with move semantics.
Definition: pointer.h:771
GenericPointer Append(SizeType index, Allocator *allocator=0) const
Append a index token, and return a new Pointer
Definition: pointer.h:300
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:777