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