NCBI C++ ToolKit
pointer.h
Go to the documentation of this file.

Go to the SVN repository for this file.

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