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