Electroneum
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 #elif defined(_MSC_VER)
25 RAPIDJSON_DIAG_PUSH
26 RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
27 #endif
28 
30 
31 static const SizeType kPointerInvalidIndex = ~SizeType(0);
32 
34 
39 
44 };
45 
47 // GenericPointer
48 
50 
78 template <typename ValueType, typename Allocator = CrtAllocator>
79 class GenericPointer {
80 public:
81  typedef typename ValueType::EncodingType EncodingType;
82  typedef typename ValueType::Ch Ch;
83 
85 
97  struct Token {
98  const Ch* name;
101  };
102 
104 
105 
107  GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
108 
110 
114  explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
115  Parse(source, internal::StrLen(source));
116  }
117 
118 #if RAPIDJSON_HAS_STDSTRING
119 
125  explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
126  Parse(source.c_str(), source.size());
127  }
128 #endif
129 
131 
137  GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
138  Parse(source, length);
139  }
140 
142 
163  GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
164 
166  GenericPointer(const GenericPointer& rhs) : allocator_(rhs.allocator_), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
167  *this = rhs;
168  }
169 
171  GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
172  *this = rhs;
173  }
174 
177  if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
178  Allocator::Free(tokens_);
179  RAPIDJSON_DELETE(ownAllocator_);
180  }
181 
184  if (this != &rhs) {
185  // Do not delete ownAllcator
186  if (nameBuffer_)
187  Allocator::Free(tokens_);
188 
189  tokenCount_ = rhs.tokenCount_;
190  parseErrorOffset_ = rhs.parseErrorOffset_;
191  parseErrorCode_ = rhs.parseErrorCode_;
192 
193  if (rhs.nameBuffer_)
194  CopyFromRaw(rhs); // Normally parsed tokens.
195  else {
196  tokens_ = rhs.tokens_; // User supplied const tokens.
197  nameBuffer_ = 0;
198  }
199  }
200  return *this;
201  }
202 
204 
206 
207 
209 
214  GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
215  GenericPointer r;
216  r.allocator_ = allocator;
217  Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
218  std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
219  r.tokens_[tokenCount_].name = p;
220  r.tokens_[tokenCount_].length = token.length;
221  r.tokens_[tokenCount_].index = token.index;
222  return r;
223  }
224 
226 
232  GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
233  Token token = { name, length, kPointerInvalidIndex };
234  return Append(token, allocator);
235  }
236 
238 
243  template <typename T>
244  RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
245  Append(T* name, Allocator* allocator = 0) const {
247  }
248 
249 #if RAPIDJSON_HAS_STDSTRING
250 
256  GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
257  return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
258  }
259 #endif
260 
262 
267  GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
268  char buffer[21];
269  char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
270  SizeType length = static_cast<SizeType>(end - buffer);
271  buffer[length] = '\0';
272 
273  if (sizeof(Ch) == 1) {
274  Token token = { reinterpret_cast<Ch*>(buffer), length, index };
275  return Append(token, allocator);
276  }
277  else {
278  Ch name[21];
279  for (size_t i = 0; i <= length; i++)
280  name[i] = static_cast<Ch>(buffer[i]);
281  Token token = { name, length, index };
282  return Append(token, allocator);
283  }
284  }
285 
287 
292  GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
293  if (token.IsString())
294  return Append(token.GetString(), token.GetStringLength(), allocator);
295  else {
296  RAPIDJSON_ASSERT(token.IsUint64());
297  RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
298  return Append(static_cast<SizeType>(token.GetUint64()), allocator);
299  }
300  }
301 
303 
304 
306  bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
307 
309  size_t GetParseErrorOffset() const { return parseErrorOffset_; }
310 
312  PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
313 
315 
317  Allocator& GetAllocator() { return *allocator_; }
318 
320 
321 
323  const Token* GetTokens() const { return tokens_; }
324 
326  size_t GetTokenCount() const { return tokenCount_; }
327 
329 
331 
332 
334 
337  bool operator==(const GenericPointer& rhs) const {
338  if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
339  return false;
340 
341  for (size_t i = 0; i < tokenCount_; i++) {
342  if (tokens_[i].index != rhs.tokens_[i].index ||
343  tokens_[i].length != rhs.tokens_[i].length ||
344  (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
345  {
346  return false;
347  }
348  }
349 
350  return true;
351  }
352 
354 
357  bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
358 
360 
362 
363 
365 
369  template<typename OutputStream>
370  bool Stringify(OutputStream& os) const {
371  return Stringify<false, OutputStream>(os);
372  }
373 
375 
379  template<typename OutputStream>
380  bool StringifyUriFragment(OutputStream& os) const {
381  return Stringify<true, OutputStream>(os);
382  }
383 
385 
387 
388 
390 
404  ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
405  RAPIDJSON_ASSERT(IsValid());
406  ValueType* v = &root;
407  bool exist = true;
408  for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
409  if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
410  v->PushBack(ValueType().Move(), allocator);
411  v = &((*v)[v->Size() - 1]);
412  exist = false;
413  }
414  else {
415  if (t->index == kPointerInvalidIndex) { // must be object name
416  if (!v->IsObject())
417  v->SetObject(); // Change to Object
418  }
419  else { // object name or array index
420  if (!v->IsArray() && !v->IsObject())
421  v->SetArray(); // Change to Array
422  }
423 
424  if (v->IsArray()) {
425  if (t->index >= v->Size()) {
426  v->Reserve(t->index + 1, allocator);
427  while (t->index >= v->Size())
428  v->PushBack(ValueType().Move(), allocator);
429  exist = false;
430  }
431  v = &((*v)[t->index]);
432  }
433  else {
434  typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
435  if (m == v->MemberEnd()) {
436  v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
437  v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
438  exist = false;
439  }
440  else
441  v = &m->value;
442  }
443  }
444  }
445 
446  if (alreadyExist)
447  *alreadyExist = exist;
448 
449  return *v;
450  }
451 
453 
458  template <typename stackAllocator>
459  ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
460  return Create(document, document.GetAllocator(), alreadyExist);
461  }
462 
464 
466 
467 
469 
482  ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
483  RAPIDJSON_ASSERT(IsValid());
484  ValueType* v = &root;
485  for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
486  switch (v->GetType()) {
487  case kObjectType:
488  {
489  typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
490  if (m == v->MemberEnd())
491  break;
492  v = &m->value;
493  }
494  continue;
495  case kArrayType:
496  if (t->index == kPointerInvalidIndex || t->index >= v->Size())
497  break;
498  v = &((*v)[t->index]);
499  continue;
500  default:
501  break;
502  }
503 
504  // Error: unresolved token
505  if (unresolvedTokenIndex)
506  *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
507  return 0;
508  }
509  return v;
510  }
511 
513 
517  const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
518  return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
519  }
520 
522 
524 
525 
527 
536  ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
537  bool alreadyExist;
538  ValueType& v = Create(root, allocator, &alreadyExist);
539  return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
540  }
541 
543  ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
544  bool alreadyExist;
545  ValueType& v = Create(root, allocator, &alreadyExist);
546  return alreadyExist ? v : v.SetString(defaultValue, allocator);
547  }
548 
549 #if RAPIDJSON_HAS_STDSTRING
550  ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
552  bool alreadyExist;
553  ValueType& v = Create(root, allocator, &alreadyExist);
554  return alreadyExist ? v : v.SetString(defaultValue, allocator);
555  }
556 #endif
557 
559 
562  template <typename T>
563  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
564  GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
565  return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
566  }
567 
569  template <typename stackAllocator>
571  return GetWithDefault(document, defaultValue, document.GetAllocator());
572  }
573 
575  template <typename stackAllocator>
577  return GetWithDefault(document, defaultValue, document.GetAllocator());
578  }
579 
580 #if RAPIDJSON_HAS_STDSTRING
581  template <typename stackAllocator>
583  ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
584  return GetWithDefault(document, defaultValue, document.GetAllocator());
585  }
586 #endif
587 
589 
592  template <typename T, typename stackAllocator>
593  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
594  GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
595  return GetWithDefault(document, defaultValue, document.GetAllocator());
596  }
597 
599 
601 
602 
604 
613  ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
614  return Create(root, allocator) = value;
615  }
616 
618  ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
619  return Create(root, allocator).CopyFrom(value, allocator);
620  }
621 
623  ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
624  return Create(root, allocator) = ValueType(value, allocator).Move();
625  }
626 
627 #if RAPIDJSON_HAS_STDSTRING
628  ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
630  return Create(root, allocator) = ValueType(value, allocator).Move();
631  }
632 #endif
633 
635 
638  template <typename T>
639  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
640  Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
641  return Create(root, allocator) = ValueType(value).Move();
642  }
643 
645  template <typename stackAllocator>
647  return Create(document) = value;
648  }
649 
651  template <typename stackAllocator>
653  return Create(document).CopyFrom(value, document.GetAllocator());
654  }
655 
657  template <typename stackAllocator>
659  return Create(document) = ValueType(value, document.GetAllocator()).Move();
660  }
661 
662 #if RAPIDJSON_HAS_STDSTRING
663  template <typename stackAllocator>
666  return Create(document) = ValueType(value, document.GetAllocator()).Move();
667  }
668 #endif
669 
671 
674  template <typename T, typename stackAllocator>
675  RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
676  Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
677  return Create(document) = value;
678  }
679 
681 
683 
684 
686 
695  ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
696  return Create(root, allocator).Swap(value);
697  }
698 
700  template <typename stackAllocator>
702  return Create(document).Swap(value);
703  }
704 
706 
708 
714  bool Erase(ValueType& root) const {
715  RAPIDJSON_ASSERT(IsValid());
716  if (tokenCount_ == 0) // Cannot erase the root
717  return false;
718 
719  ValueType* v = &root;
720  const Token* last = tokens_ + (tokenCount_ - 1);
721  for (const Token *t = tokens_; t != last; ++t) {
722  switch (v->GetType()) {
723  case kObjectType:
724  {
725  typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
726  if (m == v->MemberEnd())
727  return false;
728  v = &m->value;
729  }
730  break;
731  case kArrayType:
732  if (t->index == kPointerInvalidIndex || t->index >= v->Size())
733  return false;
734  v = &((*v)[t->index]);
735  break;
736  default:
737  return false;
738  }
739  }
740 
741  switch (v->GetType()) {
742  case kObjectType:
743  return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
744  case kArrayType:
745  if (last->index == kPointerInvalidIndex || last->index >= v->Size())
746  return false;
747  v->Erase(v->Begin() + last->index);
748  return true;
749  default:
750  return false;
751  }
752  }
753 
754 private:
756 
762  Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
763  if (!allocator_) // allocator is independently owned.
764  ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
765 
766  size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
767  for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
768  nameBufferSize += t->length;
769 
770  tokenCount_ = rhs.tokenCount_ + extraToken;
771  tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
772  nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
773  if (rhs.tokenCount_ > 0) {
774  std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
775  }
776  if (nameBufferSize > 0) {
777  std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
778  }
779 
780  // Adjust pointers to name buffer
781  std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
782  for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
783  t->name += diff;
784 
785  return nameBuffer_ + nameBufferSize;
786  }
787 
789 
793  bool NeedPercentEncode(Ch c) const {
794  return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
795  }
796 
798 #ifndef __clang__ // -Wdocumentation
799 
804 #endif
805  void Parse(const Ch* source, size_t length) {
806  RAPIDJSON_ASSERT(source != NULL);
807  RAPIDJSON_ASSERT(nameBuffer_ == 0);
808  RAPIDJSON_ASSERT(tokens_ == 0);
809 
810  // Create own allocator if user did not supply.
811  if (!allocator_)
812  ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
813 
814  // Count number of '/' as tokenCount
815  tokenCount_ = 0;
816  for (const Ch* s = source; s != source + length; s++)
817  if (*s == '/')
818  tokenCount_++;
819 
820  Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
821  Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
822  size_t i = 0;
823 
824  // Detect if it is a URI fragment
825  bool uriFragment = false;
826  if (source[i] == '#') {
827  uriFragment = true;
828  i++;
829  }
830 
831  if (i != length && source[i] != '/') {
833  goto error;
834  }
835 
836  while (i < length) {
837  RAPIDJSON_ASSERT(source[i] == '/');
838  i++; // consumes '/'
839 
840  token->name = name;
841  bool isNumber = true;
842 
843  while (i < length && source[i] != '/') {
844  Ch c = source[i];
845  if (uriFragment) {
846  // Decoding percent-encoding for URI fragment
847  if (c == '%') {
848  PercentDecodeStream is(&source[i], source + length);
850  Ch* begin = os.PutBegin();
851  if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
853  goto error;
854  }
855  size_t len = os.PutEnd(begin);
856  i += is.Tell() - 1;
857  if (len == 1)
858  c = *name;
859  else {
860  name += len;
861  isNumber = false;
862  i++;
863  continue;
864  }
865  }
866  else if (NeedPercentEncode(c)) {
868  goto error;
869  }
870  }
871 
872  i++;
873 
874  // Escaping "~0" -> '~', "~1" -> '/'
875  if (c == '~') {
876  if (i < length) {
877  c = source[i];
878  if (c == '0') c = '~';
879  else if (c == '1') c = '/';
880  else {
881  parseErrorCode_ = kPointerParseErrorInvalidEscape;
882  goto error;
883  }
884  i++;
885  }
886  else {
887  parseErrorCode_ = kPointerParseErrorInvalidEscape;
888  goto error;
889  }
890  }
891 
892  // First check for index: all of characters are digit
893  if (c < '0' || c > '9')
894  isNumber = false;
895 
896  *name++ = c;
897  }
898  token->length = static_cast<SizeType>(name - token->name);
899  if (token->length == 0)
900  isNumber = false;
901  *name++ = '\0'; // Null terminator
902 
903  // Second check for index: more than one digit cannot have leading zero
904  if (isNumber && token->length > 1 && token->name[0] == '0')
905  isNumber = false;
906 
907  // String to SizeType conversion
908  SizeType n = 0;
909  if (isNumber) {
910  for (size_t j = 0; j < token->length; j++) {
911  SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
912  if (m < n) { // overflow detection
913  isNumber = false;
914  break;
915  }
916  n = m;
917  }
918  }
919 
920  token->index = isNumber ? n : kPointerInvalidIndex;
921  token++;
922  }
923 
924  RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
925  parseErrorCode_ = kPointerParseErrorNone;
926  return;
927 
928  error:
929  Allocator::Free(tokens_);
930  nameBuffer_ = 0;
931  tokens_ = 0;
932  tokenCount_ = 0;
933  parseErrorOffset_ = i;
934  return;
935  }
936 
938 
943  template<bool uriFragment, typename OutputStream>
944  bool Stringify(OutputStream& os) const {
945  RAPIDJSON_ASSERT(IsValid());
946 
947  if (uriFragment)
948  os.Put('#');
949 
950  for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
951  os.Put('/');
952  for (size_t j = 0; j < t->length; j++) {
953  Ch c = t->name[j];
954  if (c == '~') {
955  os.Put('~');
956  os.Put('0');
957  }
958  else if (c == '/') {
959  os.Put('~');
960  os.Put('1');
961  }
962  else if (uriFragment && NeedPercentEncode(c)) {
963  // Transcode to UTF8 sequence
965  PercentEncodeStream<OutputStream> target(os);
966  if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
967  return false;
968  j += source.Tell() - 1;
969  }
970  else
971  os.Put(c);
972  }
973  }
974  return true;
975  }
976 
978 
983  class PercentDecodeStream {
984  public:
985  typedef typename ValueType::Ch Ch;
986 
988 
992  PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
993 
994  Ch Take() {
995  if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
996  valid_ = false;
997  return 0;
998  }
999  src_++;
1000  Ch c = 0;
1001  for (int j = 0; j < 2; j++) {
1002  c = static_cast<Ch>(c << 4);
1003  Ch h = *src_;
1004  if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
1005  else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
1006  else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
1007  else {
1008  valid_ = false;
1009  return 0;
1010  }
1011  src_++;
1012  }
1013  return c;
1014  }
1015 
1016  size_t Tell() const { return static_cast<size_t>(src_ - head_); }
1017  bool IsValid() const { return valid_; }
1018 
1019  private:
1020  const Ch* src_;
1021  const Ch* head_;
1022  const Ch* end_;
1023  bool valid_;
1024  };
1025 
1027  template <typename OutputStream>
1028  class PercentEncodeStream {
1029  public:
1030  PercentEncodeStream(OutputStream& os) : os_(os) {}
1031  void Put(char c) { // UTF-8 must be byte
1032  unsigned char u = static_cast<unsigned char>(c);
1033  static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1034  os_.Put('%');
1035  os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
1036  os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
1037  }
1038  private:
1039  OutputStream& os_;
1040  };
1041 
1042  Allocator* allocator_;
1043  Allocator* ownAllocator_;
1044  Ch* nameBuffer_;
1045  Token* tokens_;
1046  size_t tokenCount_;
1047  size_t parseErrorOffset_;
1048  PointerParseErrorCode parseErrorCode_;
1049 };
1050 
1053 
1055 
1056 
1058 
1059 template <typename T>
1060 typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
1061  return pointer.Create(root, a);
1062 }
1063 
1064 template <typename T, typename CharType, size_t N>
1065 typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
1066  return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
1067 }
1068 
1069 // No allocator parameter
1070 
1071 template <typename DocumentType>
1072 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
1073  return pointer.Create(document);
1074 }
1075 
1076 template <typename DocumentType, typename CharType, size_t N>
1077 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
1078  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
1079 }
1080 
1082 
1083 template <typename T>
1084 typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1085  return pointer.Get(root, unresolvedTokenIndex);
1086 }
1087 
1088 template <typename T>
1089 const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1090  return pointer.Get(root, unresolvedTokenIndex);
1091 }
1092 
1093 template <typename T, typename CharType, size_t N>
1094 typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
1095  return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1096 }
1097 
1098 template <typename T, typename CharType, size_t N>
1099 const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
1100  return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1101 }
1102 
1104 
1105 template <typename T>
1106 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1107  return pointer.GetWithDefault(root, defaultValue, a);
1108 }
1109 
1110 template <typename T>
1111 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1112  return pointer.GetWithDefault(root, defaultValue, a);
1113 }
1114 
1115 #if RAPIDJSON_HAS_STDSTRING
1116 template <typename T>
1117 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1118  return pointer.GetWithDefault(root, defaultValue, a);
1119 }
1120 #endif
1121 
1122 template <typename T, typename T2>
1123 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1124 GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
1125  return pointer.GetWithDefault(root, defaultValue, a);
1126 }
1127 
1128 template <typename T, typename CharType, size_t N>
1129 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1130  return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1131 }
1132 
1133 template <typename T, typename CharType, size_t N>
1134 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1135  return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1136 }
1137 
1138 #if RAPIDJSON_HAS_STDSTRING
1139 template <typename T, typename CharType, size_t N>
1140 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1141  return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1142 }
1143 #endif
1144 
1145 template <typename T, typename CharType, size_t N, typename T2>
1146 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1147 GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
1148  return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1149 }
1150 
1151 // No allocator parameter
1152 
1153 template <typename DocumentType>
1154 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
1155  return pointer.GetWithDefault(document, defaultValue);
1156 }
1157 
1158 template <typename DocumentType>
1159 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
1160  return pointer.GetWithDefault(document, defaultValue);
1161 }
1162 
1163 #if RAPIDJSON_HAS_STDSTRING
1164 template <typename DocumentType>
1165 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1166  return pointer.GetWithDefault(document, defaultValue);
1167 }
1168 #endif
1169 
1170 template <typename DocumentType, typename T2>
1171 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1173  return pointer.GetWithDefault(document, defaultValue);
1174 }
1175 
1176 template <typename DocumentType, typename CharType, size_t N>
1177 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
1178  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1179 }
1180 
1181 template <typename DocumentType, typename CharType, size_t N>
1182 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
1183  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1184 }
1185 
1186 #if RAPIDJSON_HAS_STDSTRING
1187 template <typename DocumentType, typename CharType, size_t N>
1188 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1189  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1190 }
1191 #endif
1192 
1193 template <typename DocumentType, typename CharType, size_t N, typename T2>
1194 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1195 GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
1196  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1197 }
1198 
1200 
1201 template <typename T>
1202 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1203  return pointer.Set(root, value, a);
1204 }
1205 
1206 template <typename T>
1207 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
1208  return pointer.Set(root, value, a);
1209 }
1210 
1211 template <typename T>
1212 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
1213  return pointer.Set(root, value, a);
1214 }
1215 
1216 #if RAPIDJSON_HAS_STDSTRING
1217 template <typename T>
1218 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1219  return pointer.Set(root, value, a);
1220 }
1221 #endif
1222 
1223 template <typename T, typename T2>
1224 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1225 SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
1226  return pointer.Set(root, value, a);
1227 }
1228 
1229 template <typename T, typename CharType, size_t N>
1230 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1231  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1232 }
1233 
1234 template <typename T, typename CharType, size_t N>
1235 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
1236  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1237 }
1238 
1239 template <typename T, typename CharType, size_t N>
1240 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
1241  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1242 }
1243 
1244 #if RAPIDJSON_HAS_STDSTRING
1245 template <typename T, typename CharType, size_t N>
1246 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1247  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1248 }
1249 #endif
1250 
1251 template <typename T, typename CharType, size_t N, typename T2>
1252 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1253 SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
1254  return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1255 }
1256 
1257 // No allocator parameter
1258 
1259 template <typename DocumentType>
1260 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1261  return pointer.Set(document, value);
1262 }
1263 
1264 template <typename DocumentType>
1265 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
1266  return pointer.Set(document, value);
1267 }
1268 
1269 template <typename DocumentType>
1270 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
1271  return pointer.Set(document, value);
1272 }
1273 
1274 #if RAPIDJSON_HAS_STDSTRING
1275 template <typename DocumentType>
1276 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
1277  return pointer.Set(document, value);
1278 }
1279 #endif
1280 
1281 template <typename DocumentType, typename T2>
1282 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1284  return pointer.Set(document, value);
1285 }
1286 
1287 template <typename DocumentType, typename CharType, size_t N>
1288 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1289  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1290 }
1291 
1292 template <typename DocumentType, typename CharType, size_t N>
1293 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
1294  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1295 }
1296 
1297 template <typename DocumentType, typename CharType, size_t N>
1298 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
1299  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1300 }
1301 
1302 #if RAPIDJSON_HAS_STDSTRING
1303 template <typename DocumentType, typename CharType, size_t N>
1304 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
1305  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1306 }
1307 #endif
1308 
1309 template <typename DocumentType, typename CharType, size_t N, typename T2>
1310 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1311 SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
1312  return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1313 }
1314 
1316 
1317 template <typename T>
1318 typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1319  return pointer.Swap(root, value, a);
1320 }
1321 
1322 template <typename T, typename CharType, size_t N>
1323 typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1324  return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
1325 }
1326 
1327 template <typename DocumentType>
1328 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1329  return pointer.Swap(document, value);
1330 }
1331 
1332 template <typename DocumentType, typename CharType, size_t N>
1333 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1335 }
1336 
1338 
1339 template <typename T>
1341  return pointer.Erase(root);
1342 }
1343 
1344 template <typename T, typename CharType, size_t N>
1345 bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
1346  return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
1347 }
1348 
1350 
1352 
1353 #if defined(__clang__) || defined(_MSC_VER)
1354 RAPIDJSON_DIAG_POP
1355 #endif
1356 
1357 #endif // RAPIDJSON_POINTER_H_
T::ValueType & GetValueByPointerWithDefault(T &root, const GenericPointer< typename T::ValueType > &pointer, const typename T::ValueType &defaultValue, typename T::AllocatorType &a)
Definition: pointer.h:1106
ValueType & Set(ValueType &root, ValueType &value, typename ValueType::AllocatorType &allocator) const
Set a value in a subtree, with move semantics.
Definition: pointer.h:613
char * u64toa(uint64_t value, char *buffer)
Definition: itoa.h:126
PointerParseErrorCode
Error code of parsing.
Definition: pointer.h:37
const uint32_t T[512]
const CharType(& source)[N]
Definition: pointer.h:1147
GenericPointer(const Ch *source, Allocator *allocator=0)
Constructor that parses a string or URI fragment representation.
Definition: pointer.h:114
SizeType length
Length of the name.
Definition: pointer.h:99
A token is the basic units of internal representation.
Definition: pointer.h:97
GenericPointer(const Ch *source, size_t length, Allocator *allocator=0)
Constructor that parses a string or URI fragment representation, with length of the source string...
Definition: pointer.h:137
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:389
object
Definition: rapidjson.h:624
Invalid percent encoding in URI fragment.
Definition: pointer.h:42
~GenericPointer()
Destructor.
Definition: pointer.h:176
array
Definition: rapidjson.h:625
GenericPointer(const GenericPointer &rhs, Allocator *allocator)
Copy constructor.
Definition: pointer.h:171
GenericPointer(const Token *tokens, size_t tokenCount)
Constructor with user-supplied tokens.
Definition: pointer.h:163
bool operator==(const some_test_data &a, const some_test_data &b)
ValueType & Set(ValueType &root, const Ch *value, typename ValueType::AllocatorType &allocator) const
Set a null-terminated string in a subtree.
Definition: pointer.h:623
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:121
bool operator!=(const some_test_subdata &a, const some_test_subdata &b)
ValueType::EncodingType EncodingType
Encoding type from Value.
Definition: pointer.h:81
Allocator * allocator
Definition: pointer.h:245
const char * name
bool Erase(ValueType &root) const
Erase a value in a subtree.
Definition: pointer.h:714
The parse is successful.
Definition: pointer.h:38
T::ValueType & SwapValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::ValueType &value, typename T::AllocatorType &a)
Definition: pointer.h:1318
Encoding conversion.
Definition: encodings.h:658
ValueType::Ch Ch
Character type from Value.
Definition: pointer.h:82
return true
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition: rapidjson.h:603
Reference to a constant string (not taking a copy)
Definition: document.h:253
SizeType index
A valid array index, if it is not equal to kPointerInvalidIndex.
Definition: pointer.h:100
Read-only string stream.
Definition: fwd.h:47
GenericPointer< Value > Pointer
GenericPointer for Value (UTF-8, default allocator).
Definition: pointer.h:1052
Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
Definition: fwd.h:126
ValueType & Set(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, const Ch *value) const
Set a null-terminated string in a document.
Definition: pointer.h:658
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:124
void Swap(T &a, T &b) RAPIDJSON_NOEXCEPT
Custom swap() to avoid dependency on C++ <algorithm> header.
Definition: swap.h:33
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:607
char * u32toa(uint32_t value, char *buffer)
Definition: itoa.h:39
T::ValueType & CreateValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::AllocatorType &a)
Definition: pointer.h:1060
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:232
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
ValueType & Swap(ValueType &root, ValueType &value, typename ValueType::AllocatorType &allocator) const
Swap a value with a value in a subtree.
Definition: pointer.h:695
A character must percent encoded in URI fragment.
Definition: pointer.h:43
ValueType & Set(ValueType &root, const ValueType &value, typename ValueType::AllocatorType &allocator) const
Set a value in a subtree, with copy semantics.
Definition: pointer.h:618
GenericPointer(const GenericPointer &rhs)
Copy constructor.
Definition: pointer.h:166
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
void * memcpy(void *a, const void *b, size_t c)
#define Ch(x, y, z)
Definition: hash_impl.h:17
GenericPointer Append(const Token &token, Allocator *allocator=0) const
Append a token and return a new Pointer.
Definition: pointer.h:214
A token must begin with a &#39;/&#39;.
Definition: pointer.h:40
ValueType & Swap(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, ValueType &value) const
Swap a value with a value in a document.
Definition: pointer.h:701
bool EraseValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer)
Definition: pointer.h:1340
GenericPointer(Allocator *allocator=0)
Default constructor.
Definition: pointer.h:107
const GenericPointer< typename T::ValueType > T2 defaultValue
Definition: pointer.h:1124
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
Definition: strfunc.h:31
ValueType & Set(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, ValueType &value) const
Set a value in a document, with move semantics.
Definition: pointer.h:646
const GenericPointer< typename T::ValueType > & pointer
Definition: pointer.h:1124
A read-write string stream.
Definition: fwd.h:52
Type
Type of JSON value.
Definition: rapidjson.h:620
Allocator stackAllocator stackAllocator & document
Definition: pointer.h:594
error
Tracks LMDB error codes.
Definition: error.h:44
T::ValueType & SetValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::ValueType &value, typename T::AllocatorType &a)
Definition: pointer.h:1202
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr< internal::IsPointer< T2 >, internal::IsGenericValue< T2 > >),(typename T::ValueType &)) GetValueByPointerWithDefault(T &root
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:411
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.
const Ch * name
Name of the token. It has null character at the end but it can contain null character.
Definition: pointer.h:98
A document for parsing JSON text as DOM.
Definition: document.h:60
GenericPointer & operator=(const GenericPointer &rhs)
Assignment operator.
Definition: pointer.h:183
T::ValueType * GetValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, size_t *unresolvedTokenIndex=0)
Definition: pointer.h:1084
UTF-8 encoding.
Definition: encodings.h:96
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:652