cphot 0.1
A C++ tool for computing photometry from spectra.
pointer.h
Go to the documentation of 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>
81 class GenericPointer {
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 {
212  GenericPointer r;
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] = 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 {
402  RAPIDJSON_ASSERT(IsValid());
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  v->PushBack(ValueType().Move(), allocator);
408  v = &((*v)[v->Size() - 1]);
409  exist = false;
410  }
411  else {
412  if (t->index == kPointerInvalidIndex) { // must be object name
413  if (!v->IsObject())
414  v->SetObject(); // Change to Object
415  }
416  else { // object name or array index
417  if (!v->IsArray() && !v->IsObject())
418  v->SetArray(); // Change to Array
419  }
420 
421  if (v->IsArray()) {
422  if (t->index >= v->Size()) {
423  v->Reserve(t->index + 1, allocator);
424  while (t->index >= v->Size())
425  v->PushBack(ValueType().Move(), allocator);
426  exist = false;
427  }
428  v = &((*v)[t->index]);
429  }
430  else {
431  typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
432  if (m == v->MemberEnd()) {
433  v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
434  v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
435  exist = false;
436  }
437  else
438  v = &m->value;
439  }
440  }
441  }
442 
443  if (alreadyExist)
444  *alreadyExist = exist;
445 
446  return *v;
447  }
448 
449  //! Creates a value in a document.
450  /*!
451  \param document A document to be resolved.
452  \param alreadyExist If non-null, it stores whether the resolved value is already exist.
453  \return The resolved newly created, or already exists value.
454  */
455  template <typename stackAllocator>
456  ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
457  return Create(document, document.GetAllocator(), alreadyExist);
458  }
459 
460  //@}
461 
462  //!@name Query value
463  //@{
464 
465  //! Query a value in a subtree.
466  /*!
467  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
468  \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
469  \return Pointer to the value if it can be resolved. Otherwise null.
470 
471  \note
472  There are only 3 situations when a value cannot be resolved:
473  1. A value in the path is not an array nor object.
474  2. An object value does not contain the token.
475  3. A token is out of range of an array value.
476 
477  Use unresolvedTokenIndex to retrieve the token index.
478  */
479  ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
480  RAPIDJSON_ASSERT(IsValid());
481  ValueType* v = &root;
482  for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
483  switch (v->GetType()) {
484  case kObjectType:
485  {
486  typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
487  if (m == v->MemberEnd())
488  break;
489  v = &m->value;
490  }
491  continue;
492  case kArrayType:
493  if (t->index == kPointerInvalidIndex || t->index >= v->Size())
494  break;
495  v = &((*v)[t->index]);
496  continue;
497  default:
498  break;
499  }
500 
501  // Error: unresolved token
502  if (unresolvedTokenIndex)
503  *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
504  return 0;
505  }
506  return v;
507  }
508 
509  //! Query a const value in a const subtree.
510  /*!
511  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
512  \return Pointer to the value if it can be resolved. Otherwise null.
513  */
514  const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
515  return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
516  }
517 
518  //@}
519 
520  //!@name Query a value with default
521  //@{
522 
523  //! Query a value in a subtree with default value.
524  /*!
525  Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value.
526  So that this function always succeed.
527 
528  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
529  \param defaultValue Default value to be cloned if the value was not exists.
530  \param allocator Allocator for creating the values if the specified value or its parents are not exist.
531  \see Create()
532  */
533  ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
534  bool alreadyExist;
535  Value& v = Create(root, allocator, &alreadyExist);
536  return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
537  }
538 
539  //! Query a value in a subtree with default null-terminated string.
540  ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
541  bool alreadyExist;
542  Value& v = Create(root, allocator, &alreadyExist);
543  return alreadyExist ? v : v.SetString(defaultValue, allocator);
544  }
545 
546 #if RAPIDJSON_HAS_STDSTRING
547  //! Query a value in a subtree with default std::basic_string.
548  ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
549  bool alreadyExist;
550  Value& v = Create(root, allocator, &alreadyExist);
551  return alreadyExist ? v : v.SetString(defaultValue, allocator);
552  }
553 #endif
554 
555  //! Query a value in a subtree with default primitive value.
556  /*!
557  \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
558  */
559  template <typename T>
560  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
561  GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
562  return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
563  }
564 
565  //! Query a value in a document with default value.
566  template <typename stackAllocator>
568  return GetWithDefault(document, defaultValue, document.GetAllocator());
569  }
570 
571  //! Query a value in a document with default null-terminated string.
572  template <typename stackAllocator>
574  return GetWithDefault(document, defaultValue, document.GetAllocator());
575  }
576 
577 #if RAPIDJSON_HAS_STDSTRING
578  //! Query a value in a document with default std::basic_string.
579  template <typename stackAllocator>
580  ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
581  return GetWithDefault(document, defaultValue, document.GetAllocator());
582  }
583 #endif
584 
585  //! Query a value in a document with default primitive value.
586  /*!
587  \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
588  */
589  template <typename T, typename stackAllocator>
590  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
591  GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
592  return GetWithDefault(document, defaultValue, document.GetAllocator());
593  }
594 
595  //@}
596 
597  //!@name Set a value
598  //@{
599 
600  //! Set a value in a subtree, with move semantics.
601  /*!
602  It creates all parents if they are not exist or types are different to the tokens.
603  So this function always succeeds but potentially remove existing values.
604 
605  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
606  \param value Value to be set.
607  \param allocator Allocator for creating the values if the specified value or its parents are not exist.
608  \see Create()
609  */
610  ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
611  return Create(root, allocator) = value;
612  }
613 
614  //! Set a value in a subtree, with copy semantics.
615  ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
616  return Create(root, allocator).CopyFrom(value, allocator);
617  }
618 
619  //! Set a null-terminated string in a subtree.
620  ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
621  return Create(root, allocator) = ValueType(value, allocator).Move();
622  }
623 
624 #if RAPIDJSON_HAS_STDSTRING
625  //! Set a std::basic_string in a subtree.
626  ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
627  return Create(root, allocator) = ValueType(value, allocator).Move();
628  }
629 #endif
630 
631  //! Set a primitive value in a subtree.
632  /*!
633  \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
634  */
635  template <typename T>
636  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
637  Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
638  return Create(root, allocator) = ValueType(value).Move();
639  }
640 
641  //! Set a value in a document, with move semantics.
642  template <typename stackAllocator>
644  return Create(document) = value;
645  }
646 
647  //! Set a value in a document, with copy semantics.
648  template <typename stackAllocator>
650  return Create(document).CopyFrom(value, document.GetAllocator());
651  }
652 
653  //! Set a null-terminated string in a document.
654  template <typename stackAllocator>
656  return Create(document) = ValueType(value, document.GetAllocator()).Move();
657  }
658 
659 #if RAPIDJSON_HAS_STDSTRING
660  //! Sets a std::basic_string in a document.
661  template <typename stackAllocator>
663  return Create(document) = ValueType(value, document.GetAllocator()).Move();
664  }
665 #endif
666 
667  //! Set a primitive value in a document.
668  /*!
669  \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
670  */
671  template <typename T, typename stackAllocator>
672  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
673  Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
674  return Create(document) = value;
675  }
676 
677  //@}
678 
679  //!@name Swap a value
680  //@{
681 
682  //! Swap a value with a value in a subtree.
683  /*!
684  It creates all parents if they are not exist or types are different to the tokens.
685  So this function always succeeds but potentially remove existing values.
686 
687  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
688  \param value Value to be swapped.
689  \param allocator Allocator for creating the values if the specified value or its parents are not exist.
690  \see Create()
691  */
692  ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
693  return Create(root, allocator).Swap(value);
694  }
695 
696  //! Swap a value with a value in a document.
697  template <typename stackAllocator>
699  return Create(document).Swap(value);
700  }
701 
702  //@}
703 
704  //! Erase a value in a subtree.
705  /*!
706  \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
707  \return Whether the resolved value is found and erased.
708 
709  \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false.
710  */
711  bool Erase(ValueType& root) const {
712  RAPIDJSON_ASSERT(IsValid());
713  if (tokenCount_ == 0) // Cannot erase the root
714  return false;
715 
716  ValueType* v = &root;
717  const Token* last = tokens_ + (tokenCount_ - 1);
718  for (const Token *t = tokens_; t != last; ++t) {
719  switch (v->GetType()) {
720  case kObjectType:
721  {
722  typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
723  if (m == v->MemberEnd())
724  return false;
725  v = &m->value;
726  }
727  break;
728  case kArrayType:
729  if (t->index == kPointerInvalidIndex || t->index >= v->Size())
730  return false;
731  v = &((*v)[t->index]);
732  break;
733  default:
734  return false;
735  }
736  }
737 
738  switch (v->GetType()) {
739  case kObjectType:
740  return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
741  case kArrayType:
742  if (last->index == kPointerInvalidIndex || last->index >= v->Size())
743  return false;
744  v->Erase(v->Begin() + last->index);
745  return true;
746  default:
747  return false;
748  }
749  }
750 
751 private:
752  //! Clone the content from rhs to this.
753  /*!
754  \param rhs Source pointer.
755  \param extraToken Extra tokens to be allocated.
756  \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated.
757  \return Start of non-occupied name buffer, for storing extra names.
758  */
759  Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
760  if (!allocator_) // allocator is independently owned.
761  ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
762 
763  size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
764  for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
765  nameBufferSize += t->length;
766 
767  tokenCount_ = rhs.tokenCount_ + extraToken;
768  tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
769  nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
770  if (rhs.tokenCount_ > 0) {
771  std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
772  }
773  if (nameBufferSize > 0) {
774  std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
775  }
776 
777  // Adjust pointers to name buffer
778  std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
779  for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
780  t->name += diff;
781 
782  return nameBuffer_ + nameBufferSize;
783  }
784 
785  //! Check whether a character should be percent-encoded.
786  /*!
787  According to RFC 3986 2.3 Unreserved Characters.
788  \param c The character (code unit) to be tested.
789  */
790  bool NeedPercentEncode(Ch c) const {
791  return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
792  }
793 
794  //! Parse a JSON String or its URI fragment representation into tokens.
795 #ifndef __clang__ // -Wdocumentation
796  /*!
797  \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated.
798  \param length Length of the source string.
799  \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped.
800  */
801 #endif
802  void Parse(const Ch* source, size_t length) {
803  RAPIDJSON_ASSERT(source != NULL);
804  RAPIDJSON_ASSERT(nameBuffer_ == 0);
805  RAPIDJSON_ASSERT(tokens_ == 0);
806 
807  // Create own allocator if user did not supply.
808  if (!allocator_)
809  ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
810 
811  // Count number of '/' as tokenCount
812  tokenCount_ = 0;
813  for (const Ch* s = source; s != source + length; s++)
814  if (*s == '/')
815  tokenCount_++;
816 
817  Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
818  Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
819  size_t i = 0;
820 
821  // Detect if it is a URI fragment
822  bool uriFragment = false;
823  if (source[i] == '#') {
824  uriFragment = true;
825  i++;
826  }
827 
828  if (i != length && source[i] != '/') {
830  goto error;
831  }
832 
833  while (i < length) {
834  RAPIDJSON_ASSERT(source[i] == '/');
835  i++; // consumes '/'
836 
837  token->name = name;
838  bool isNumber = true;
839 
840  while (i < length && source[i] != '/') {
841  Ch c = source[i];
842  if (uriFragment) {
843  // Decoding percent-encoding for URI fragment
844  if (c == '%') {
845  PercentDecodeStream is(&source[i], source + length);
847  Ch* begin = os.PutBegin();
848  if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
850  goto error;
851  }
852  size_t len = os.PutEnd(begin);
853  i += is.Tell() - 1;
854  if (len == 1)
855  c = *name;
856  else {
857  name += len;
858  isNumber = false;
859  i++;
860  continue;
861  }
862  }
863  else if (NeedPercentEncode(c)) {
865  goto error;
866  }
867  }
868 
869  i++;
870 
871  // Escaping "~0" -> '~', "~1" -> '/'
872  if (c == '~') {
873  if (i < length) {
874  c = source[i];
875  if (c == '0') c = '~';
876  else if (c == '1') c = '/';
877  else {
878  parseErrorCode_ = kPointerParseErrorInvalidEscape;
879  goto error;
880  }
881  i++;
882  }
883  else {
884  parseErrorCode_ = kPointerParseErrorInvalidEscape;
885  goto error;
886  }
887  }
888 
889  // First check for index: all of characters are digit
890  if (c < '0' || c > '9')
891  isNumber = false;
892 
893  *name++ = c;
894  }
895  token->length = static_cast<SizeType>(name - token->name);
896  if (token->length == 0)
897  isNumber = false;
898  *name++ = '\0'; // Null terminator
899 
900  // Second check for index: more than one digit cannot have leading zero
901  if (isNumber && token->length > 1 && token->name[0] == '0')
902  isNumber = false;
903 
904  // String to SizeType conversion
905  SizeType n = 0;
906  if (isNumber) {
907  for (size_t j = 0; j < token->length; j++) {
908  SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
909  if (m < n) { // overflow detection
910  isNumber = false;
911  break;
912  }
913  n = m;
914  }
915  }
916 
917  token->index = isNumber ? n : kPointerInvalidIndex;
918  token++;
919  }
920 
921  RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
922  parseErrorCode_ = kPointerParseErrorNone;
923  return;
924 
925  error:
926  Allocator::Free(tokens_);
927  nameBuffer_ = 0;
928  tokens_ = 0;
929  tokenCount_ = 0;
930  parseErrorOffset_ = i;
931  return;
932  }
933 
934  //! Stringify to string or URI fragment representation.
935  /*!
936  \tparam uriFragment True for stringifying to URI fragment representation. False for string representation.
937  \tparam OutputStream type of output stream.
938  \param os The output stream.
939  */
940  template<bool uriFragment, typename OutputStream>
941  bool Stringify(OutputStream& os) const {
942  RAPIDJSON_ASSERT(IsValid());
943 
944  if (uriFragment)
945  os.Put('#');
946 
947  for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
948  os.Put('/');
949  for (size_t j = 0; j < t->length; j++) {
950  Ch c = t->name[j];
951  if (c == '~') {
952  os.Put('~');
953  os.Put('0');
954  }
955  else if (c == '/') {
956  os.Put('~');
957  os.Put('1');
958  }
959  else if (uriFragment && NeedPercentEncode(c)) {
960  // Transcode to UTF8 sequence
962  PercentEncodeStream<OutputStream> target(os);
963  if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
964  return false;
965  j += source.Tell() - 1;
966  }
967  else
968  os.Put(c);
969  }
970  }
971  return true;
972  }
973 
974  //! A helper stream for decoding a percent-encoded sequence into code unit.
975  /*!
976  This stream decodes %XY triplet into code unit (0-255).
977  If it encounters invalid characters, it sets output code unit as 0 and
978  mark invalid, and to be checked by IsValid().
979  */
980  class PercentDecodeStream {
981  public:
982  typedef typename ValueType::Ch Ch;
983 
984  //! Constructor
985  /*!
986  \param source Start of the stream
987  \param end Past-the-end of the stream.
988  */
989  PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
990 
991  Ch Take() {
992  if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
993  valid_ = false;
994  return 0;
995  }
996  src_++;
997  Ch c = 0;
998  for (int j = 0; j < 2; j++) {
999  c = static_cast<Ch>(c << 4);
1000  Ch h = *src_;
1001  if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
1002  else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
1003  else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
1004  else {
1005  valid_ = false;
1006  return 0;
1007  }
1008  src_++;
1009  }
1010  return c;
1011  }
1012 
1013  size_t Tell() const { return static_cast<size_t>(src_ - head_); }
1014  bool IsValid() const { return valid_; }
1015 
1016  private:
1017  const Ch* src_; //!< Current read position.
1018  const Ch* head_; //!< Original head of the string.
1019  const Ch* end_; //!< Past-the-end position.
1020  bool valid_; //!< Whether the parsing is valid.
1021  };
1022 
1023  //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
1024  template <typename OutputStream>
1025  class PercentEncodeStream {
1026  public:
1027  PercentEncodeStream(OutputStream& os) : os_(os) {}
1028  void Put(char c) { // UTF-8 must be byte
1029  unsigned char u = static_cast<unsigned char>(c);
1030  static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1031  os_.Put('%');
1032  os_.Put(hexDigits[u >> 4]);
1033  os_.Put(hexDigits[u & 15]);
1034  }
1035  private:
1036  OutputStream& os_;
1037  };
1038 
1039  Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
1040  Allocator* ownAllocator_; //!< Allocator owned by this Pointer.
1041  Ch* nameBuffer_; //!< A buffer containing all names in tokens.
1042  Token* tokens_; //!< A list of tokens.
1043  size_t tokenCount_; //!< Number of tokens in tokens_.
1044  size_t parseErrorOffset_; //!< Offset in code unit when parsing fail.
1045  PointerParseErrorCode parseErrorCode_; //!< Parsing error code.
1046 };
1047 
1048 //! GenericPointer for Value (UTF-8, default allocator).
1050 
1051 //!@name Helper functions for GenericPointer
1052 //@{
1053 
1054 //////////////////////////////////////////////////////////////////////////////
1055 
1056 template <typename T>
1057 typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
1058  return pointer.Create(root, a);
1059 }
1060 
1061 template <typename T, typename CharType, size_t N>
1062 typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
1063  return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
1064 }
1065 
1066 // No allocator parameter
1067 
1068 template <typename DocumentType>
1069 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
1070  return pointer.Create(document);
1071 }
1072 
1073 template <typename DocumentType, typename CharType, size_t N>
1074 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
1075  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
1076 }
1077 
1078 //////////////////////////////////////////////////////////////////////////////
1079 
1080 template <typename T>
1081 typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1082  return pointer.Get(root, unresolvedTokenIndex);
1083 }
1084 
1085 template <typename T>
1086 const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1087  return pointer.Get(root, unresolvedTokenIndex);
1088 }
1089 
1090 template <typename T, typename CharType, size_t N>
1091 typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
1092  return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1093 }
1094 
1095 template <typename T, typename CharType, size_t N>
1096 const typename T::ValueType* GetValueByPointer(const 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 //////////////////////////////////////////////////////////////////////////////
1101 
1102 template <typename T>
1103 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1104  return pointer.GetWithDefault(root, defaultValue, a);
1105 }
1106 
1107 template <typename T>
1108 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1109  return pointer.GetWithDefault(root, defaultValue, a);
1110 }
1111 
1112 #if RAPIDJSON_HAS_STDSTRING
1113 template <typename T>
1114 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1115  return pointer.GetWithDefault(root, defaultValue, a);
1116 }
1117 #endif
1118 
1119 template <typename T, typename T2>
1120 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1121 GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
1122  return pointer.GetWithDefault(root, defaultValue, a);
1123 }
1124 
1125 template <typename T, typename CharType, size_t N>
1126 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1127  return GenericPointer<typename T::ValueType>(source, N - 1).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::Ch* defaultValue, typename T::AllocatorType& a) {
1132  return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1133 }
1134 
1135 #if RAPIDJSON_HAS_STDSTRING
1136 template <typename T, typename CharType, size_t N>
1137 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1138  return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1139 }
1140 #endif
1141 
1142 template <typename T, typename CharType, size_t N, typename T2>
1143 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1144 GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
1145  return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1146 }
1147 
1148 // No allocator parameter
1149 
1150 template <typename DocumentType>
1151 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
1152  return pointer.GetWithDefault(document, defaultValue);
1153 }
1154 
1155 template <typename DocumentType>
1156 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
1157  return pointer.GetWithDefault(document, defaultValue);
1158 }
1159 
1160 #if RAPIDJSON_HAS_STDSTRING
1161 template <typename DocumentType>
1162 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1163  return pointer.GetWithDefault(document, defaultValue);
1164 }
1165 #endif
1166 
1167 template <typename DocumentType, typename T2>
1168 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1170  return pointer.GetWithDefault(document, defaultValue);
1171 }
1172 
1173 template <typename DocumentType, typename CharType, size_t N>
1174 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
1175  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).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::Ch* defaultValue) {
1180  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1181 }
1182 
1183 #if RAPIDJSON_HAS_STDSTRING
1184 template <typename DocumentType, typename CharType, size_t N>
1185 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1186  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1187 }
1188 #endif
1189 
1190 template <typename DocumentType, typename CharType, size_t N, typename T2>
1191 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1192 GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
1193  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1194 }
1195 
1196 //////////////////////////////////////////////////////////////////////////////
1197 
1198 template <typename T>
1199 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1200  return pointer.Set(root, value, a);
1201 }
1202 
1203 template <typename T>
1204 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const 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::Ch* value, typename T::AllocatorType& a) {
1210  return pointer.Set(root, value, a);
1211 }
1212 
1213 #if RAPIDJSON_HAS_STDSTRING
1214 template <typename T>
1215 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1216  return pointer.Set(root, value, a);
1217 }
1218 #endif
1219 
1220 template <typename T, typename T2>
1221 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1222 SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
1223  return pointer.Set(root, value, a);
1224 }
1225 
1226 template <typename T, typename CharType, size_t N>
1227 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1228  return GenericPointer<typename T::ValueType>(source, N - 1).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], const typename T::ValueType& value, typename T::AllocatorType& a) {
1233  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, 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::Ch* value, typename T::AllocatorType& a) {
1238  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1239 }
1240 
1241 #if RAPIDJSON_HAS_STDSTRING
1242 template <typename T, typename CharType, size_t N>
1243 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1244  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1245 }
1246 #endif
1247 
1248 template <typename T, typename CharType, size_t N, typename T2>
1249 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1250 SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
1251  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1252 }
1253 
1254 // No allocator parameter
1255 
1256 template <typename DocumentType>
1257 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1258  return pointer.Set(document, value);
1259 }
1260 
1261 template <typename DocumentType>
1262 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const 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::Ch* value) {
1268  return pointer.Set(document, value);
1269 }
1270 
1271 #if RAPIDJSON_HAS_STDSTRING
1272 template <typename DocumentType>
1273 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
1274  return pointer.Set(document, value);
1275 }
1276 #endif
1277 
1278 template <typename DocumentType, typename T2>
1279 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1281  return pointer.Set(document, value);
1282 }
1283 
1284 template <typename DocumentType, typename CharType, size_t N>
1285 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1287 }
1288 
1289 template <typename DocumentType, typename CharType, size_t N>
1290 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const 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::Ch* value) {
1297 }
1298 
1299 #if RAPIDJSON_HAS_STDSTRING
1300 template <typename DocumentType, typename CharType, size_t N>
1301 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
1303 }
1304 #endif
1305 
1306 template <typename DocumentType, typename CharType, size_t N, typename T2>
1307 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1308 SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
1310 }
1311 
1312 //////////////////////////////////////////////////////////////////////////////
1313 
1314 template <typename T>
1315 typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1316  return pointer.Swap(root, value, a);
1317 }
1318 
1319 template <typename T, typename CharType, size_t N>
1320 typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1321  return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
1322 }
1323 
1324 template <typename DocumentType>
1325 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1326  return pointer.Swap(document, value);
1327 }
1328 
1329 template <typename DocumentType, typename CharType, size_t N>
1330 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1332 }
1333 
1334 //////////////////////////////////////////////////////////////////////////////
1335 
1336 template <typename T>
1338  return pointer.Erase(root);
1339 }
1340 
1341 template <typename T, typename CharType, size_t N>
1342 bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
1343  return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
1344 }
1345 
1346 //@}
1347 
1349 
1350 #ifdef __clang__
1351 RAPIDJSON_DIAG_POP
1352 #endif
1353 
1354 #ifdef _MSC_VER
1355 RAPIDJSON_DIAG_POP
1356 #endif
1357 
1358 #endif // RAPIDJSON_POINTER_H_
GenericPointer
Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
Definition: fwd.h:126
RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:119
GenericPointer::value
T value
Definition: pointer.h:637
kPointerParseErrorTokenMustBeginWithSolidus
@ kPointerParseErrorTokenMustBeginWithSolidus
A token must begin with a '/'.
Definition: pointer.h:42
RAPIDJSON_NAMESPACE_BEGIN
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:116
GetValueByPointerWithDefault
T::ValueType & GetValueByPointerWithDefault(T &root, const GenericPointer< typename T::ValueType > &pointer, const typename T::ValueType &defaultValue, typename T::AllocatorType &a)
Definition: pointer.h:1103
internal::IsGenericValue
Definition: document.h:401
GenericDocument
A document for parsing JSON text as DOM.
Definition: document.h:62
Allocator
Concept for allocating, resizing and freeing memory block.
kArrayType
@ kArrayType
array
Definition: rapidjson.h:608
Transcoder
Encoding conversion.
Definition: encodings.h:658
Type
Type
Type of JSON value.
Definition: rapidjson.h:603
GenericPointer::Set
ValueType & Set(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, const Ch *value) const
Set a null-terminated string in a document.
Definition: pointer.h:655
kPointerParseErrorInvalidPercentEncoding
@ kPointerParseErrorInvalidPercentEncoding
Invalid percent encoding in URI fragment.
Definition: pointer.h:44
PointerParseErrorCode
PointerParseErrorCode
Error code of parsing.
Definition: pointer.h:39
document.h
GenericPointer::Set
ValueType & Set(ValueType &root, const ValueType &value, typename ValueType::AllocatorType &allocator) const
Set a value in a subtree, with copy semantics.
Definition: pointer.h:615
GenericPointer::Append
GenericPointer Append(const Ch *name, SizeType length, Allocator *allocator=0) const
Append a name token with length, and return a new Pointer.
Definition: pointer.h:229
GenericPointer::Append
GenericPointer Append(const Token &token, Allocator *allocator=0) const
Append a token and return a new Pointer.
Definition: pointer.h:211
kObjectType
@ kObjectType
object
Definition: rapidjson.h:607
GenericPointer::Swap
ValueType & Swap(ValueType &root, ValueType &value, typename ValueType::AllocatorType &allocator) const
Swap a value with a value in a subtree.
Definition: pointer.h:692
GenericPointer::GenericPointer
GenericPointer(Allocator *allocator=0)
Default constructor.
Definition: pointer.h:109
GenericPointer::Token
A token is the basic units of internal representation.
Definition: pointer.h:99
operator==
constexpr bool operator==(const RQuantity< M, l, T, A, C, L, S, D > &lhs, const RQuantity< M, l, T, A, C, L, S, D > &rhs)
Definition: rquantities.hpp:221
SwapValueByPointer
T::ValueType & SwapValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::ValueType &value, typename T::AllocatorType &a)
Definition: pointer.h:1315
kPointerParseErrorInvalidEscape
@ kPointerParseErrorInvalidEscape
Invalid escape.
Definition: pointer.h:43
GenericInsituStringStream
A read-write string stream.
Definition: fwd.h:52
kPointerInvalidIndex
static const RAPIDJSON_NAMESPACE_BEGIN SizeType kPointerInvalidIndex
Represents an invalid index in GenericPointer::Token.
Definition: pointer.h:33
GenericPointer::Set
ValueType & Set(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, ValueType &value) const
Set a value in a document, with move semantics.
Definition: pointer.h:643
SizeType
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:380
GenericPointer::Swap
ValueType & Swap(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, ValueType &value) const
Swap a value with a value in a document.
Definition: pointer.h:698
Pointer
GenericPointer< Value > Pointer
GenericPointer for Value (UTF-8, default allocator).
Definition: pointer.h:1049
GenericPointer::GenericPointer
GenericPointer(const GenericPointer &rhs, Allocator *allocator=0)
Copy constructor.
Definition: pointer.h:168
GenericStringStream
Read-only string stream.
Definition: fwd.h:47
GenericPointer::RAPIDJSON_DISABLEIF_RETURN
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.
RAPIDJSON_ASSERT
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:402
itoa.h
GenericPointer::Set
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:649
GenericPointer::document
Allocator stackAllocator stackAllocator & document
Definition: pointer.h:591
GenericPointer::Token::length
SizeType length
Length of the name.
Definition: pointer.h:101
CreateValueByPointer
T::ValueType & CreateValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::AllocatorType &a)
Definition: pointer.h:1057
GenericPointer::operator=
GenericPointer & operator=(const GenericPointer &rhs)
Assignment operator.
Definition: pointer.h:180
a
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1121
GenericPointer::Set
ValueType & Set(ValueType &root, ValueType &value, typename ValueType::AllocatorType &allocator) const
Set a value in a subtree, with move semantics.
Definition: pointer.h:610
kPointerParseErrorNone
@ kPointerParseErrorNone
The parse is successful.
Definition: pointer.h:40
c
constexpr QSpeed c
Definition: rquantities.hpp:351
GenericPointer::GenericPointer
GenericPointer(const Ch *source, Allocator *allocator=0)
Constructor that parses a string or URI fragment representation.
Definition: pointer.h:116
GenericPointer::Token::index
SizeType index
A valid array index, if it is not equal to kPointerInvalidIndex.
Definition: pointer.h:102
GenericPointer::~GenericPointer
~GenericPointer()
Destructor.
Definition: pointer.h:173
kPointerParseErrorCharacterMustPercentEncode
@ kPointerParseErrorCharacterMustPercentEncode
A character must percent encoded in URI fragment.
Definition: pointer.h:45
GenericPointer::GenericPointer
GenericPointer(const Ch *source, size_t length, Allocator *allocator=0)
Constructor that parses a string or URI fragment representation, with length of the source string.
Definition: pointer.h:139
RAPIDJSON_NEW
#define RAPIDJSON_NEW(x)
! customization point for global new
Definition: rapidjson.h:586
GenericPointer::Token::name
const Ch * name
Name of the token.
Definition: pointer.h:100
RAPIDJSON_DELETE
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:590
defaultValue
const GenericPointer< typename T::ValueType > T2 defaultValue
Definition: pointer.h:1121
GenericValue
Represents a JSON value. Use Value for UTF8 encoding and default allocator.
Definition: document.h:59
UTF8
UTF-8 encoding.
Definition: encodings.h:96
operator!=
constexpr bool operator!=(const RQuantity< M, l, T, A, C, L, S, D > &lhs, const RQuantity< M, l, T, A, C, L, S, D > &rhs)
Definition: rquantities.hpp:226
pointer
const GenericPointer< typename T::ValueType > & pointer
Definition: pointer.h:1121
GenericPointer::allocator
Allocator * allocator
Definition: pointer.h:242
RAPIDJSON_DISABLEIF_RETURN
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr< internal::IsPointer< T2 >, internal::IsGenericValue< T2 > >),(typename T::ValueType &)) GetValueByPointerWithDefault(T &root
GenericStringRef
Reference to a constant string (not taking a copy)
Definition: document.h:249
GenericPointer::GenericPointer
GenericPointer(const Token *tokens, size_t tokenCount)
Constructor with user-supplied tokens.
Definition: pointer.h:165
GetValueByPointer
T::ValueType * GetValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, size_t *unresolvedTokenIndex=0)
Definition: pointer.h:1081
internal::u64toa
char * u64toa(uint64_t value, char *buffer)
Definition: itoa.h:123
GenericPointer::EncodingType
ValueType::EncodingType EncodingType
Encoding type from Value.
Definition: pointer.h:83
GenericPointer::Set
ValueType & Set(ValueType &root, const Ch *value, typename ValueType::AllocatorType &allocator) const
Set a null-terminated string in a subtree.
Definition: pointer.h:620
internal::u32toa
char * u32toa(uint32_t value, char *buffer)
Definition: itoa.h:39
GenericPointer::defaultValue
Allocator stackAllocator stackAllocator T const defaultValue
Definition: pointer.h:591
GenericPointer::Erase
bool Erase(ValueType &root) const
Erase a value in a subtree.
Definition: pointer.h:711
value
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1222
EraseValueByPointer
bool EraseValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer)
Definition: pointer.h:1337
GenericPointer::Ch
ValueType::Ch Ch
Character type from Value.
Definition: pointer.h:84
internal::StrLen
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
Definition: strfunc.h:30
SetValueByPointer
T::ValueType & SetValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::ValueType &value, typename T::AllocatorType &a)
Definition: pointer.h:1199
source
const CharType(& source)[N]
Definition: pointer.h:1144