COSC345-Eventures
pointer.h
1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // http://opensource.org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #ifndef RAPIDJSON_POINTER_H_
16 #define RAPIDJSON_POINTER_H_
17 
18 #include "document.h"
19 #include "uri.h"
20 #include "internal/itoa.h"
21 #include "error/error.h" // PointerParseErrorCode
22 
23 #ifdef __clang__
24 RAPIDJSON_DIAG_PUSH
25 RAPIDJSON_DIAG_OFF(switch-enum)
26 #elif defined(_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);
34 
36 // GenericPointer
37 
39 
67 template <typename ValueType, typename Allocator = CrtAllocator>
68 class GenericPointer {
69 public:
70  typedef typename ValueType::EncodingType EncodingType;
71  typedef typename ValueType::Ch Ch;
73 
74 
76 
88  struct Token {
89  const Ch* name;
92  };
93 
95 
96 
99 
101 
105  explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
106  Parse(source, internal::StrLen(source));
107  }
108 
109 #if RAPIDJSON_HAS_STDSTRING
110 
116  explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
117  Parse(source.c_str(), source.size());
118  }
119 #endif
120 
122 
128  GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
129  Parse(source, length);
130  }
131 
133 
154  GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
155 
158  *this = rhs;
159  }
160 
163  *this = rhs;
164  }
165 
168  if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
169  Allocator::Free(tokens_);
171  }
172 
175  if (this != &rhs) {
176  // Do not delete ownAllcator
177  if (nameBuffer_)
178  Allocator::Free(tokens_);
179 
180  tokenCount_ = rhs.tokenCount_;
183 
184  if (rhs.nameBuffer_)
185  CopyFromRaw(rhs); // Normally parsed tokens.
186  else {
187  tokens_ = rhs.tokens_; // User supplied const tokens.
188  nameBuffer_ = 0;
189  }
190  }
191  return *this;
192  }
193 
195 
199  GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT {
200  internal::Swap(allocator_, other.allocator_);
201  internal::Swap(ownAllocator_, other.ownAllocator_);
202  internal::Swap(nameBuffer_, other.nameBuffer_);
203  internal::Swap(tokens_, other.tokens_);
204  internal::Swap(tokenCount_, other.tokenCount_);
205  internal::Swap(parseErrorOffset_, other.parseErrorOffset_);
206  internal::Swap(parseErrorCode_, other.parseErrorCode_);
207  return *this;
208  }
209 
211 
222  friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
223 
225 
227 
228 
230 
235  GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
236  GenericPointer r;
237  r.allocator_ = allocator;
238  Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
239  std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
240  r.tokens_[tokenCount_].name = p;
241  r.tokens_[tokenCount_].length = token.length;
242  r.tokens_[tokenCount_].index = token.index;
243  return r;
244  }
245 
247 
253  GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
254  Token token = { name, length, kPointerInvalidIndex };
255  return Append(token, allocator);
256  }
257 
259 
264  template <typename T>
265  RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
266  Append(T* name, Allocator* allocator = 0) const {
267  return Append(name, internal::StrLen(name), allocator);
268  }
269 
270 #if RAPIDJSON_HAS_STDSTRING
271 
277  GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
278  return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
279  }
280 #endif
281 
283 
288  GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
289  char buffer[21];
290  char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
291  SizeType length = static_cast<SizeType>(end - buffer);
292  buffer[length] = '\0';
293 
294  if (sizeof(Ch) == 1) {
295  Token token = { reinterpret_cast<Ch*>(buffer), length, index };
296  return Append(token, allocator);
297  }
298  else {
299  Ch name[21];
300  for (size_t i = 0; i <= length; i++)
301  name[i] = static_cast<Ch>(buffer[i]);
302  Token token = { name, length, index };
303  return Append(token, allocator);
304  }
305  }
306 
308 
313  GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
314  if (token.IsString())
315  return Append(token.GetString(), token.GetStringLength(), allocator);
316  else {
317  RAPIDJSON_ASSERT(token.IsUint64());
318  RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
319  return Append(static_cast<SizeType>(token.GetUint64()), allocator);
320  }
321  }
322 
324 
325 
327  bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
328 
330  size_t GetParseErrorOffset() const { return parseErrorOffset_; }
331 
333  PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
334 
336 
338  Allocator& GetAllocator() { return *allocator_; }
339 
341 
342 
344  const Token* GetTokens() const { return tokens_; }
345 
347  size_t GetTokenCount() const { return tokenCount_; }
348 
350 
352 
353 
355 
358  bool operator==(const GenericPointer& rhs) const {
359  if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
360  return false;
361 
362  for (size_t i = 0; i < tokenCount_; i++) {
363  if (tokens_[i].index != rhs.tokens_[i].index ||
364  tokens_[i].length != rhs.tokens_[i].length ||
365  (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
366  {
367  return false;
368  }
369  }
370 
371  return true;
372  }
373 
375 
378  bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
379 
381 
384  bool operator<(const GenericPointer& rhs) const {
385  if (!IsValid())
386  return false;
387  if (!rhs.IsValid())
388  return true;
389 
390  if (tokenCount_ != rhs.tokenCount_)
391  return tokenCount_ < rhs.tokenCount_;
392 
393  for (size_t i = 0; i < tokenCount_; i++) {
394  if (tokens_[i].index != rhs.tokens_[i].index)
395  return tokens_[i].index < rhs.tokens_[i].index;
396 
397  if (tokens_[i].length != rhs.tokens_[i].length)
398  return tokens_[i].length < rhs.tokens_[i].length;
399 
400  if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length))
401  return cmp < 0;
402  }
403 
404  return false;
405  }
406 
408 
410 
411 
413 
417  template<typename OutputStream>
418  bool Stringify(OutputStream& os) const {
419  return Stringify<false, OutputStream>(os);
420  }
421 
423 
427  template<typename OutputStream>
428  bool StringifyUriFragment(OutputStream& os) const {
429  return Stringify<true, OutputStream>(os);
430  }
431 
433 
435 
436 
438 
452  ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
453  RAPIDJSON_ASSERT(IsValid());
454  ValueType* v = &root;
455  bool exist = true;
456  for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
457  if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
458  v->PushBack(ValueType().Move(), allocator);
459  v = &((*v)[v->Size() - 1]);
460  exist = false;
461  }
462  else {
463  if (t->index == kPointerInvalidIndex) { // must be object name
464  if (!v->IsObject())
465  v->SetObject(); // Change to Object
466  }
467  else { // object name or array index
468  if (!v->IsArray() && !v->IsObject())
469  v->SetArray(); // Change to Array
470  }
471 
472  if (v->IsArray()) {
473  if (t->index >= v->Size()) {
474  v->Reserve(t->index + 1, allocator);
475  while (t->index >= v->Size())
476  v->PushBack(ValueType().Move(), allocator);
477  exist = false;
478  }
479  v = &((*v)[t->index]);
480  }
481  else {
482  typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
483  if (m == v->MemberEnd()) {
484  v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
485  m = v->MemberEnd();
486  v = &(--m)->value; // Assumes AddMember() appends at the end
487  exist = false;
488  }
489  else
490  v = &m->value;
491  }
492  }
493  }
494 
495  if (alreadyExist)
496  *alreadyExist = exist;
497 
498  return *v;
499  }
500 
502 
507  template <typename stackAllocator>
508  ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
509  return Create(document, document.GetAllocator(), alreadyExist);
510  }
511 
513 
515 
516 
518  // For use with JSON pointers into JSON schema documents.
534  UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
535  static const Ch kIdString[] = { 'i', 'd', '\0' };
536  static const ValueType kIdValue(kIdString, 2);
537  UriType base = UriType(rootUri, allocator);
538  RAPIDJSON_ASSERT(IsValid());
539  ValueType* v = &root;
540  for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
541  switch (v->GetType()) {
542  case kObjectType:
543  {
544  // See if we have an id, and if so resolve with the current base
545  typename ValueType::MemberIterator m = v->FindMember(kIdValue);
546  if (m != v->MemberEnd() && (m->value).IsString()) {
547  UriType here = UriType(m->value, allocator).Resolve(base, allocator);
548  base = here;
549  }
550  m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
551  if (m == v->MemberEnd())
552  break;
553  v = &m->value;
554  }
555  continue;
556  case kArrayType:
557  if (t->index == kPointerInvalidIndex || t->index >= v->Size())
558  break;
559  v = &((*v)[t->index]);
560  continue;
561  default:
562  break;
563  }
564 
565  // Error: unresolved token
566  if (unresolvedTokenIndex)
567  *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
568  return UriType(allocator);
569  }
570  return base;
571  }
572 
573  UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
574  return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex, allocator);
575  }
576 
577 
579 
580 
582 
595  ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
596  RAPIDJSON_ASSERT(IsValid());
597  ValueType* v = &root;
598  for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
599  switch (v->GetType()) {
600  case kObjectType:
601  {
602  typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
603  if (m == v->MemberEnd())
604  break;
605  v = &m->value;
606  }
607  continue;
608  case kArrayType:
609  if (t->index == kPointerInvalidIndex || t->index >= v->Size())
610  break;
611  v = &((*v)[t->index]);
612  continue;
613  default:
614  break;
615  }
616 
617  // Error: unresolved token
618  if (unresolvedTokenIndex)
619  *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
620  return 0;
621  }
622  return v;
623  }
624 
626 
630  const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
631  return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
632  }
633 
635 
637 
638 
640 
649  ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
650  bool alreadyExist;
651  ValueType& v = Create(root, allocator, &alreadyExist);
652  return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
653  }
654 
656  ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
657  bool alreadyExist;
658  ValueType& v = Create(root, allocator, &alreadyExist);
659  return alreadyExist ? v : v.SetString(defaultValue, allocator);
660  }
661 
662 #if RAPIDJSON_HAS_STDSTRING
663  ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
665  bool alreadyExist;
666  ValueType& v = Create(root, allocator, &alreadyExist);
667  return alreadyExist ? v : v.SetString(defaultValue, allocator);
668  }
669 #endif
670 
672 
675  template <typename T>
676  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
677  GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
678  return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
679  }
680 
682  template <typename stackAllocator>
683  ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const {
684  return GetWithDefault(document, defaultValue, document.GetAllocator());
685  }
686 
688  template <typename stackAllocator>
689  ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
690  return GetWithDefault(document, defaultValue, document.GetAllocator());
691  }
692 
693 #if RAPIDJSON_HAS_STDSTRING
694  template <typename stackAllocator>
696  ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
697  return GetWithDefault(document, defaultValue, document.GetAllocator());
698  }
699 #endif
700 
702 
705  template <typename T, typename stackAllocator>
706  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
707  GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
708  return GetWithDefault(document, defaultValue, document.GetAllocator());
709  }
710 
712 
714 
715 
717 
726  ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
727  return Create(root, allocator) = value;
728  }
729 
731  ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
732  return Create(root, allocator).CopyFrom(value, allocator);
733  }
734 
736  ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
737  return Create(root, allocator) = ValueType(value, allocator).Move();
738  }
739 
740 #if RAPIDJSON_HAS_STDSTRING
741  ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
743  return Create(root, allocator) = ValueType(value, allocator).Move();
744  }
745 #endif
746 
748 
751  template <typename T>
752  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
753  Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
754  return Create(root, allocator) = ValueType(value).Move();
755  }
756 
758  template <typename stackAllocator>
759  ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
760  return Create(document) = value;
761  }
762 
764  template <typename stackAllocator>
765  ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {
766  return Create(document).CopyFrom(value, document.GetAllocator());
767  }
768 
770  template <typename stackAllocator>
771  ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const {
772  return Create(document) = ValueType(value, document.GetAllocator()).Move();
773  }
774 
775 #if RAPIDJSON_HAS_STDSTRING
776  template <typename stackAllocator>
778  ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
779  return Create(document) = ValueType(value, document.GetAllocator()).Move();
780  }
781 #endif
782 
784 
787  template <typename T, typename stackAllocator>
788  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
790  return Create(document) = value;
791  }
792 
794 
796 
797 
799 
808  ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
809  return Create(root, allocator).Swap(value);
810  }
811 
813  template <typename stackAllocator>
814  ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
815  return Create(document).Swap(value);
816  }
817 
819 
821 
827  bool Erase(ValueType& root) const {
828  RAPIDJSON_ASSERT(IsValid());
829  if (tokenCount_ == 0) // Cannot erase the root
830  return false;
831 
832  ValueType* v = &root;
833  const Token* last = tokens_ + (tokenCount_ - 1);
834  for (const Token *t = tokens_; t != last; ++t) {
835  switch (v->GetType()) {
836  case kObjectType:
837  {
838  typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
839  if (m == v->MemberEnd())
840  return false;
841  v = &m->value;
842  }
843  break;
844  case kArrayType:
845  if (t->index == kPointerInvalidIndex || t->index >= v->Size())
846  return false;
847  v = &((*v)[t->index]);
848  break;
849  default:
850  return false;
851  }
852  }
853 
854  switch (v->GetType()) {
855  case kObjectType:
856  return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
857  case kArrayType:
858  if (last->index == kPointerInvalidIndex || last->index >= v->Size())
859  return false;
860  v->Erase(v->Begin() + last->index);
861  return true;
862  default:
863  return false;
864  }
865  }
866 
867 private:
869 
875  Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
876  if (!allocator_) // allocator is independently owned.
877  ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
878 
879  size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
880  for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
881  nameBufferSize += t->length;
882 
883  tokenCount_ = rhs.tokenCount_ + extraToken;
884  tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
885  nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
886  if (rhs.tokenCount_ > 0) {
887  std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
888  }
889  if (nameBufferSize > 0) {
890  std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
891  }
892 
893  // The names of each token point to a string in the nameBuffer_. The
894  // previous memcpy copied over string pointers into the rhs.nameBuffer_,
895  // but they should point to the strings in the new nameBuffer_.
896  for (size_t i = 0; i < rhs.tokenCount_; ++i) {
897  // The offset between the string address and the name buffer should
898  // still be constant, so we can just get this offset and set each new
899  // token name according the new buffer start + the known offset.
900  std::ptrdiff_t name_offset = rhs.tokens_[i].name - rhs.nameBuffer_;
901  tokens_[i].name = nameBuffer_ + name_offset;
902  }
903 
904  return nameBuffer_ + nameBufferSize;
905  }
906 
908 
912  bool NeedPercentEncode(Ch c) const {
913  return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
914  }
915 
917 #ifndef __clang__ // -Wdocumentation
918 
923 #endif
924  void Parse(const Ch* source, size_t length) {
925  RAPIDJSON_ASSERT(source != NULL);
928 
929  // Create own allocator if user did not supply.
930  if (!allocator_)
931  ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
932 
933  // Count number of '/' as tokenCount
934  tokenCount_ = 0;
935  for (const Ch* s = source; s != source + length; s++)
936  if (*s == '/')
937  tokenCount_++;
938 
939  Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
940  Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
941  size_t i = 0;
942 
943  // Detect if it is a URI fragment
944  bool uriFragment = false;
945  if (source[i] == '#') {
946  uriFragment = true;
947  i++;
948  }
949 
950  if (i != length && source[i] != '/') {
952  goto error;
953  }
954 
955  while (i < length) {
956  RAPIDJSON_ASSERT(source[i] == '/');
957  i++; // consumes '/'
958 
959  token->name = name;
960  bool isNumber = true;
961 
962  while (i < length && source[i] != '/') {
963  Ch c = source[i];
964  if (uriFragment) {
965  // Decoding percent-encoding for URI fragment
966  if (c == '%') {
967  PercentDecodeStream is(&source[i], source + length);
969  Ch* begin = os.PutBegin();
970  if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
972  goto error;
973  }
974  size_t len = os.PutEnd(begin);
975  i += is.Tell() - 1;
976  if (len == 1)
977  c = *name;
978  else {
979  name += len;
980  isNumber = false;
981  i++;
982  continue;
983  }
984  }
985  else if (NeedPercentEncode(c)) {
987  goto error;
988  }
989  }
990 
991  i++;
992 
993  // Escaping "~0" -> '~', "~1" -> '/'
994  if (c == '~') {
995  if (i < length) {
996  c = source[i];
997  if (c == '0') c = '~';
998  else if (c == '1') c = '/';
999  else {
1001  goto error;
1002  }
1003  i++;
1004  }
1005  else {
1007  goto error;
1008  }
1009  }
1010 
1011  // First check for index: all of characters are digit
1012  if (c < '0' || c > '9')
1013  isNumber = false;
1014 
1015  *name++ = c;
1016  }
1017  token->length = static_cast<SizeType>(name - token->name);
1018  if (token->length == 0)
1019  isNumber = false;
1020  *name++ = '\0'; // Null terminator
1021 
1022  // Second check for index: more than one digit cannot have leading zero
1023  if (isNumber && token->length > 1 && token->name[0] == '0')
1024  isNumber = false;
1025 
1026  // String to SizeType conversion
1027  SizeType n = 0;
1028  if (isNumber) {
1029  for (size_t j = 0; j < token->length; j++) {
1030  SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
1031  if (m < n) { // overflow detection
1032  isNumber = false;
1033  break;
1034  }
1035  n = m;
1036  }
1037  }
1038 
1039  token->index = isNumber ? n : kPointerInvalidIndex;
1040  token++;
1041  }
1042 
1043  RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
1045  return;
1046 
1047  error:
1048  Allocator::Free(tokens_);
1049  nameBuffer_ = 0;
1050  tokens_ = 0;
1051  tokenCount_ = 0;
1052  parseErrorOffset_ = i;
1053  return;
1054  }
1055 
1057 
1062  template<bool uriFragment, typename OutputStream>
1063  bool Stringify(OutputStream& os) const {
1064  RAPIDJSON_ASSERT(IsValid());
1065 
1066  if (uriFragment)
1067  os.Put('#');
1068 
1069  for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
1070  os.Put('/');
1071  for (size_t j = 0; j < t->length; j++) {
1072  Ch c = t->name[j];
1073  if (c == '~') {
1074  os.Put('~');
1075  os.Put('0');
1076  }
1077  else if (c == '/') {
1078  os.Put('~');
1079  os.Put('1');
1080  }
1081  else if (uriFragment && NeedPercentEncode(c)) {
1082  // Transcode to UTF8 sequence
1085  if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
1086  return false;
1087  j += source.Tell() - 1;
1088  }
1089  else
1090  os.Put(c);
1091  }
1092  }
1093  return true;
1094  }
1095 
1097 
1102  class PercentDecodeStream {
1103  public:
1104  typedef typename ValueType::Ch Ch;
1105 
1107 
1111  PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
1112 
1113  Ch Take() {
1114  if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
1115  valid_ = false;
1116  return 0;
1117  }
1118  src_++;
1119  Ch c = 0;
1120  for (int j = 0; j < 2; j++) {
1121  c = static_cast<Ch>(c << 4);
1122  Ch h = *src_;
1123  if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
1124  else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
1125  else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
1126  else {
1127  valid_ = false;
1128  return 0;
1129  }
1130  src_++;
1131  }
1132  return c;
1133  }
1134 
1135  size_t Tell() const { return static_cast<size_t>(src_ - head_); }
1136  bool IsValid() const { return valid_; }
1137 
1138  private:
1139  const Ch* src_;
1140  const Ch* head_;
1141  const Ch* end_;
1142  bool valid_;
1143  };
1144 
1146  template <typename OutputStream>
1148  public:
1149  PercentEncodeStream(OutputStream& os) : os_(os) {}
1150  void Put(char c) { // UTF-8 must be byte
1151  unsigned char u = static_cast<unsigned char>(c);
1152  static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1153  os_.Put('%');
1154  os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
1155  os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
1156  }
1157  private:
1158  OutputStream& os_;
1159  };
1160 
1161  Allocator* allocator_;
1162  Allocator* ownAllocator_;
1165  size_t tokenCount_;
1168 };
1169 
1172 
1174 
1175 
1177 
1178 template <typename T>
1179 typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
1180  return pointer.Create(root, a);
1181 }
1182 
1183 template <typename T, typename CharType, size_t N>
1184 typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
1185  return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
1186 }
1187 
1188 // No allocator parameter
1189 
1190 template <typename DocumentType>
1191 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
1192  return pointer.Create(document);
1193 }
1194 
1195 template <typename DocumentType, typename CharType, size_t N>
1196 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
1197  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
1198 }
1199 
1201 
1202 template <typename T>
1203 typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1204  return pointer.Get(root, unresolvedTokenIndex);
1205 }
1206 
1207 template <typename T>
1208 const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1209  return pointer.Get(root, unresolvedTokenIndex);
1210 }
1211 
1212 template <typename T, typename CharType, size_t N>
1213 typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
1214  return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1215 }
1216 
1217 template <typename T, typename CharType, size_t N>
1218 const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
1219  return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1220 }
1221 
1223 
1224 template <typename T>
1225 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1226  return pointer.GetWithDefault(root, defaultValue, a);
1227 }
1228 
1229 template <typename T>
1230 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1231  return pointer.GetWithDefault(root, defaultValue, a);
1232 }
1233 
1234 #if RAPIDJSON_HAS_STDSTRING
1235 template <typename T>
1236 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1237  return pointer.GetWithDefault(root, defaultValue, a);
1238 }
1239 #endif
1240 
1241 template <typename T, typename T2>
1242 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1243 GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
1244  return pointer.GetWithDefault(root, defaultValue, a);
1245 }
1246 
1247 template <typename T, typename CharType, size_t N>
1248 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1249  return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1250 }
1251 
1252 template <typename T, typename CharType, size_t N>
1253 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1254  return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1255 }
1256 
1257 #if RAPIDJSON_HAS_STDSTRING
1258 template <typename T, typename CharType, size_t N>
1259 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1260  return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1261 }
1262 #endif
1263 
1264 template <typename T, typename CharType, size_t N, typename T2>
1265 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1266 GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
1267  return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1268 }
1269 
1270 // No allocator parameter
1271 
1272 template <typename DocumentType>
1273 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
1274  return pointer.GetWithDefault(document, defaultValue);
1275 }
1276 
1277 template <typename DocumentType>
1278 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
1279  return pointer.GetWithDefault(document, defaultValue);
1280 }
1281 
1282 #if RAPIDJSON_HAS_STDSTRING
1283 template <typename DocumentType>
1284 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1285  return pointer.GetWithDefault(document, defaultValue);
1286 }
1287 #endif
1288 
1289 template <typename DocumentType, typename T2>
1290 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1291 GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
1292  return pointer.GetWithDefault(document, defaultValue);
1293 }
1294 
1295 template <typename DocumentType, typename CharType, size_t N>
1296 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
1297  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1298 }
1299 
1300 template <typename DocumentType, typename CharType, size_t N>
1301 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
1302  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1303 }
1304 
1305 #if RAPIDJSON_HAS_STDSTRING
1306 template <typename DocumentType, typename CharType, size_t N>
1307 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1308  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1309 }
1310 #endif
1311 
1312 template <typename DocumentType, typename CharType, size_t N, typename T2>
1313 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1314 GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
1315  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1316 }
1317 
1319 
1320 template <typename T>
1321 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1322  return pointer.Set(root, value, a);
1323 }
1324 
1325 template <typename T>
1326 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
1327  return pointer.Set(root, value, a);
1328 }
1329 
1330 template <typename T>
1331 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
1332  return pointer.Set(root, value, a);
1333 }
1334 
1335 #if RAPIDJSON_HAS_STDSTRING
1336 template <typename T>
1337 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1338  return pointer.Set(root, value, a);
1339 }
1340 #endif
1341 
1342 template <typename T, typename T2>
1343 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1344 SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
1345  return pointer.Set(root, value, a);
1346 }
1347 
1348 template <typename T, typename CharType, size_t N>
1349 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1350  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1351 }
1352 
1353 template <typename T, typename CharType, size_t N>
1354 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
1355  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1356 }
1357 
1358 template <typename T, typename CharType, size_t N>
1359 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
1360  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1361 }
1362 
1363 #if RAPIDJSON_HAS_STDSTRING
1364 template <typename T, typename CharType, size_t N>
1365 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1366  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1367 }
1368 #endif
1369 
1370 template <typename T, typename CharType, size_t N, typename T2>
1371 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1372 SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
1373  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1374 }
1375 
1376 // No allocator parameter
1377 
1378 template <typename DocumentType>
1379 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1380  return pointer.Set(document, value);
1381 }
1382 
1383 template <typename DocumentType>
1384 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
1385  return pointer.Set(document, value);
1386 }
1387 
1388 template <typename DocumentType>
1389 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
1390  return pointer.Set(document, value);
1391 }
1392 
1393 #if RAPIDJSON_HAS_STDSTRING
1394 template <typename DocumentType>
1395 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
1396  return pointer.Set(document, value);
1397 }
1398 #endif
1399 
1400 template <typename DocumentType, typename T2>
1401 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1402 SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
1403  return pointer.Set(document, value);
1404 }
1405 
1406 template <typename DocumentType, typename CharType, size_t N>
1407 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1408  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1409 }
1410 
1411 template <typename DocumentType, typename CharType, size_t N>
1412 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
1413  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1414 }
1415 
1416 template <typename DocumentType, typename CharType, size_t N>
1417 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
1418  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1419 }
1420 
1421 #if RAPIDJSON_HAS_STDSTRING
1422 template <typename DocumentType, typename CharType, size_t N>
1423 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
1424  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1425 }
1426 #endif
1427 
1428 template <typename DocumentType, typename CharType, size_t N, typename T2>
1429 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1430 SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
1431  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1432 }
1433 
1435 
1436 template <typename T>
1437 typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1438  return pointer.Swap(root, value, a);
1439 }
1440 
1441 template <typename T, typename CharType, size_t N>
1442 typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1443  return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
1444 }
1445 
1446 template <typename DocumentType>
1447 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1448  return pointer.Swap(document, value);
1449 }
1450 
1451 template <typename DocumentType, typename CharType, size_t N>
1452 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1453  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
1454 }
1455 
1457 
1458 template <typename T>
1459 bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
1460  return pointer.Erase(root);
1461 }
1462 
1463 template <typename T, typename CharType, size_t N>
1464 bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
1465  return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
1466 }
1467 
1469 
1471 
1472 #if defined(__clang__) || defined(_MSC_VER)
1473 RAPIDJSON_DIAG_POP
1474 #endif
1475 
1476 #endif // RAPIDJSON_POINTER_H_
GenericPointer(const Token *tokens, size_t tokenCount)
Constructor with user-supplied tokens.
Definition: pointer.h:154
Invalid escape.
Definition: error.h:261
Encoding conversion.
Definition: encodings.h:658
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:415
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:437
object
Definition: rapidjson.h:733
Read-only string stream.
Definition: fwd.h:47
Ch * nameBuffer_
A buffer containing all names in tokens.
Definition: pointer.h:1163
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:124
array
Definition: rapidjson.h:734
ValueType::EncodingType EncodingType
Encoding type from Value.
Definition: pointer.h:70
Invalid percent encoding in URI fragment.
Definition: error.h:262
GenericPointer Append(const Token &token, Allocator *allocator=0) const
Append a token and return a new Pointer.
Definition: pointer.h:235
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:128
PointerParseErrorCode parseErrorCode_
Parsing error code.
Definition: pointer.h:1167
Represents a JSON value. Use Value for UTF8 encoding and default allocator.
Definition: document.h:66
GenericPointer(const GenericPointer &rhs)
Copy constructor.
Definition: pointer.h:157
Token * tokens_
A list of tokens.
Definition: pointer.h:1164
Definition: uri.h:33
SizeType index
A valid array index, if it is not equal to kPointerInvalidIndex.
Definition: pointer.h:91
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:121
A token is the basic units of internal representation.
Definition: pointer.h:88
A document for parsing JSON text as DOM.
Definition: document.h:69
A token must begin with a &#39;/&#39;.
Definition: error.h:260
A read-write string stream.
Definition: fwd.h:52
SizeType length
Length of the name.
Definition: pointer.h:90
GenericPointer(const Ch *source, Allocator *allocator=0)
Constructor that parses a string or URI fragment representation.
Definition: pointer.h:105
size_t parseErrorOffset_
Offset in code unit when parsing fail.
Definition: pointer.h:1166
UTF-8 encoding.
Definition: encodings.h:96
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition: rapidjson.h:712
friend void swap(GenericPointer &a, GenericPointer &b) RAPIDJSON_NOEXCEPT
free-standing swap function helper
Definition: pointer.h:222
Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
Definition: fwd.h:126
GenericPointer & operator=(const GenericPointer &rhs)
Assignment operator.
Definition: pointer.h:174
A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
Definition: pointer.h:1147
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:253
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.
Allocator & GetAllocator()
Get the allocator of this document.
Definition: document.h:2795
size_t tokenCount_
Number of tokens in tokens_.
Definition: pointer.h:1165
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:716
GenericPointer(const GenericPointer &rhs, Allocator *allocator)
Copy constructor.
Definition: pointer.h:162
ValueType::Ch Ch
Character type from Value.
Definition: pointer.h:71
const Ch * name
Name of the token. It has null character at the end but it can contain null character.
Definition: pointer.h:89
PointerParseErrorCode
Error code of JSON pointer parsing.
Definition: error.h:257
GenericPointer & Swap(GenericPointer &other) RAPIDJSON_NOEXCEPT
Swap the content of this pointer with an other.
Definition: pointer.h:199
Reference to a constant string (not taking a copy)
Definition: document.h:346
Definition: document.h:509
The parse is successful.
Definition: error.h:258
Allocator * allocator_
The current allocator. It is either user-supplied or equal to ownAllocator_.
Definition: pointer.h:1161
Type
Type of JSON value.
Definition: rapidjson.h:729
A character must percent encoded in URI fragment.
Definition: error.h:263
Allocator * ownAllocator_
Allocator owned by this Pointer.
Definition: pointer.h:1162
GenericPointer(Allocator *allocator=0)
Default constructor.
Definition: pointer.h:98
~GenericPointer()
Destructor.
Definition: pointer.h:167