Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
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__
22RAPIDJSON_DIAG_PUSH
23RAPIDJSON_DIAG_OFF(switch-enum)
24#elif defined(_MSC_VER)
25RAPIDJSON_DIAG_PUSH
26RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
27#endif
28
30
31static const SizeType kPointerInvalidIndex = ~SizeType(0);
32
34
45
47// GenericPointer
48
50
78template <typename ValueType, typename Allocator = CrtAllocator>
80public:
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
108
110
117
118#if RAPIDJSON_HAS_STDSTRING
120
126 Parse(source.c_str(), source.size());
127 }
128#endif
129
131
140
142
163 GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
164
169
174
177 if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
178 Allocator::Free(tokens_);
180 }
181
184 if (this != &rhs) {
185 // Do not delete ownAllcator
186 if (nameBuffer_)
187 Allocator::Free(tokens_);
188
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
208 GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT {
209 internal::Swap(allocator_, other.allocator_);
210 internal::Swap(ownAllocator_, other.ownAllocator_);
211 internal::Swap(nameBuffer_, other.nameBuffer_);
212 internal::Swap(tokens_, other.tokens_);
213 internal::Swap(tokenCount_, other.tokenCount_);
214 internal::Swap(parseErrorOffset_, other.parseErrorOffset_);
215 internal::Swap(parseErrorCode_, other.parseErrorCode_);
216 return *this;
217 }
218
220
231 friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
232
234
236
237
239
244 GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
246 r.allocator_ = allocator;
247 Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
248 std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
249 r.tokens_[tokenCount_].name = p;
250 r.tokens_[tokenCount_].length = token.length;
251 r.tokens_[tokenCount_].index = token.index;
252 return r;
253 }
254
256
263 Token token = { name, length, kPointerInvalidIndex };
264 return Append(token, allocator);
265 }
266
268
273 template <typename T>
274 RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
277 }
278
279#if RAPIDJSON_HAS_STDSTRING
281
286 GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
287 return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
288 }
289#endif
290
292
298 char buffer[21];
299 char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
300 SizeType length = static_cast<SizeType>(end - buffer);
301 buffer[length] = '\0';
302
303 if (sizeof(Ch) == 1) {
304 Token token = { reinterpret_cast<Ch*>(buffer), length, index };
305 return Append(token, allocator);
306 }
307 else {
308 Ch name[21];
309 for (size_t i = 0; i <= length; i++)
310 name[i] = static_cast<Ch>(buffer[i]);
311 Token token = { name, length, index };
312 return Append(token, allocator);
313 }
314 }
315
317
322 GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
323 if (token.IsString())
324 return Append(token.GetString(), token.GetStringLength(), allocator);
325 else {
326 RAPIDJSON_ASSERT(token.IsUint64());
327 RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
328 return Append(static_cast<SizeType>(token.GetUint64()), allocator);
329 }
330 }
331
333
334
336 bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
337
339 size_t GetParseErrorOffset() const { return parseErrorOffset_; }
340
342 PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
343
345
347 Allocator& GetAllocator() { return *allocator_; }
348
350
351
353 const Token* GetTokens() const { return tokens_; }
354
356 size_t GetTokenCount() const { return tokenCount_; }
357
359
361
362
364
367 bool operator==(const GenericPointer& rhs) const {
368 if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
369 return false;
370
371 for (size_t i = 0; i < tokenCount_; i++) {
372 if (tokens_[i].index != rhs.tokens_[i].index ||
373 tokens_[i].length != rhs.tokens_[i].length ||
374 (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
375 {
376 return false;
377 }
378 }
379
380 return true;
381 }
382
384
387 bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
388
390
393 bool operator<(const GenericPointer& rhs) const {
394 if (!IsValid())
395 return false;
396 if (!rhs.IsValid())
397 return true;
398
399 if (tokenCount_ != rhs.tokenCount_)
400 return tokenCount_ < rhs.tokenCount_;
401
402 for (size_t i = 0; i < tokenCount_; i++) {
403 if (tokens_[i].index != rhs.tokens_[i].index)
404 return tokens_[i].index < rhs.tokens_[i].index;
405
406 if (tokens_[i].length != rhs.tokens_[i].length)
407 return tokens_[i].length < rhs.tokens_[i].length;
408
409 if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length))
410 return cmp < 0;
411 }
412
413 return false;
414 }
415
417
419
420
422
426 template<typename OutputStream>
427 bool Stringify(OutputStream& os) const {
428 return Stringify<false, OutputStream>(os);
429 }
430
432
436 template<typename OutputStream>
437 bool StringifyUriFragment(OutputStream& os) const {
438 return Stringify<true, OutputStream>(os);
439 }
440
442
444
445
447
461 ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
462 RAPIDJSON_ASSERT(IsValid());
463 ValueType* v = &root;
464 bool exist = true;
465 for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
466 if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
467 v->PushBack(ValueType().Move(), allocator);
468 v = &((*v)[v->Size() - 1]);
469 exist = false;
470 }
471 else {
472 if (t->index == kPointerInvalidIndex) { // must be object name
473 if (!v->IsObject())
474 v->SetObject(); // Change to Object
475 }
476 else { // object name or array index
477 if (!v->IsArray() && !v->IsObject())
478 v->SetArray(); // Change to Array
479 }
480
481 if (v->IsArray()) {
482 if (t->index >= v->Size()) {
483 v->Reserve(t->index + 1, allocator);
484 while (t->index >= v->Size())
485 v->PushBack(ValueType().Move(), allocator);
486 exist = false;
487 }
488 v = &((*v)[t->index]);
489 }
490 else {
491 typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
492 if (m == v->MemberEnd()) {
493 v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
494 v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
495 exist = false;
496 }
497 else
498 v = &m->value;
499 }
500 }
501 }
502
503 if (alreadyExist)
504 *alreadyExist = exist;
505
506 return *v;
507 }
508
510
515 template <typename stackAllocator>
517 return Create(document, document.GetAllocator(), alreadyExist);
518 }
519
521
523
524
526
539 ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
540 RAPIDJSON_ASSERT(IsValid());
541 ValueType* v = &root;
542 for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
543 switch (v->GetType()) {
544 case kObjectType:
545 {
546 typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
547 if (m == v->MemberEnd())
548 break;
549 v = &m->value;
550 }
551 continue;
552 case kArrayType:
553 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
554 break;
555 v = &((*v)[t->index]);
556 continue;
557 default:
558 break;
559 }
560
561 // Error: unresolved token
562 if (unresolvedTokenIndex)
563 *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
564 return 0;
565 }
566 return v;
567 }
568
570
574 const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
575 return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
576 }
577
579
581
582
584
593 ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
594 bool alreadyExist;
595 ValueType& v = Create(root, allocator, &alreadyExist);
596 return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
597 }
598
600 ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
601 bool alreadyExist;
602 ValueType& v = Create(root, allocator, &alreadyExist);
603 return alreadyExist ? v : v.SetString(defaultValue, allocator);
604 }
605
606#if RAPIDJSON_HAS_STDSTRING
608 ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
609 bool alreadyExist;
610 ValueType& v = Create(root, allocator, &alreadyExist);
611 return alreadyExist ? v : v.SetString(defaultValue, allocator);
612 }
613#endif
614
616
619 template <typename T>
620 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
621 GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
622 return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
623 }
624
626 template <typename stackAllocator>
628 return GetWithDefault(document, defaultValue, document.GetAllocator());
629 }
630
632 template <typename stackAllocator>
634 return GetWithDefault(document, defaultValue, document.GetAllocator());
635 }
636
637#if RAPIDJSON_HAS_STDSTRING
639 template <typename stackAllocator>
640 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
641 return GetWithDefault(document, defaultValue, document.GetAllocator());
642 }
643#endif
644
646
649 template <typename T, typename stackAllocator>
650 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
652 return GetWithDefault(document, defaultValue, document.GetAllocator());
653 }
654
656
658
659
661
670 ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
671 return Create(root, allocator) = value;
672 }
673
675 ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
676 return Create(root, allocator).CopyFrom(value, allocator);
677 }
678
680 ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
681 return Create(root, allocator) = ValueType(value, allocator).Move();
682 }
683
684#if RAPIDJSON_HAS_STDSTRING
686 ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
687 return Create(root, allocator) = ValueType(value, allocator).Move();
688 }
689#endif
690
692
695 template <typename T>
696 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
697 Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
698 return Create(root, allocator) = ValueType(value).Move();
699 }
700
702 template <typename stackAllocator>
704 return Create(document) = value;
705 }
706
708 template <typename stackAllocator>
710 return Create(document).CopyFrom(value, document.GetAllocator());
711 }
712
714 template <typename stackAllocator>
716 return Create(document) = ValueType(value, document.GetAllocator()).Move();
717 }
718
719#if RAPIDJSON_HAS_STDSTRING
721 template <typename stackAllocator>
723 return Create(document) = ValueType(value, document.GetAllocator()).Move();
724 }
725#endif
726
728
731 template <typename T, typename stackAllocator>
732 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
734 return Create(document) = value;
735 }
736
738
740
741
743
752 ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
753 return Create(root, allocator).Swap(value);
754 }
755
757 template <typename stackAllocator>
759 return Create(document).Swap(value);
760 }
761
763
765
771 bool Erase(ValueType& root) const {
772 RAPIDJSON_ASSERT(IsValid());
773 if (tokenCount_ == 0) // Cannot erase the root
774 return false;
775
776 ValueType* v = &root;
777 const Token* last = tokens_ + (tokenCount_ - 1);
778 for (const Token *t = tokens_; t != last; ++t) {
779 switch (v->GetType()) {
780 case kObjectType:
781 {
782 typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
783 if (m == v->MemberEnd())
784 return false;
785 v = &m->value;
786 }
787 break;
788 case kArrayType:
789 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
790 return false;
791 v = &((*v)[t->index]);
792 break;
793 default:
794 return false;
795 }
796 }
797
798 switch (v->GetType()) {
799 case kObjectType:
800 return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
801 case kArrayType:
802 if (last->index == kPointerInvalidIndex || last->index >= v->Size())
803 return false;
804 v->Erase(v->Begin() + last->index);
805 return true;
806 default:
807 return false;
808 }
809 }
810
811private:
813
819 Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
820 if (!allocator_) // allocator is independently owned.
822
823 size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
824 for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
825 nameBufferSize += t->length;
826
827 tokenCount_ = rhs.tokenCount_ + extraToken;
828 tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
829 nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
830 if (rhs.tokenCount_ > 0) {
831 std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
832 }
833 if (nameBufferSize > 0) {
834 std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
835 }
836
837 // Adjust pointers to name buffer
838 std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
839 for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
840 t->name += diff;
841
842 return nameBuffer_ + nameBufferSize;
843 }
844
846
850 bool NeedPercentEncode(Ch c) const {
851 return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
852 }
853
855#ifndef __clang__ // -Wdocumentation
861#endif
862 void Parse(const Ch* source, size_t length) {
863 RAPIDJSON_ASSERT(source != NULL);
866
867 // Create own allocator if user did not supply.
868 if (!allocator_)
870
871 // Count number of '/' as tokenCount
872 tokenCount_ = 0;
873 for (const Ch* s = source; s != source + length; s++)
874 if (*s == '/')
875 tokenCount_++;
876
877 Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
878 Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
879 size_t i = 0;
880
881 // Detect if it is a URI fragment
882 bool uriFragment = false;
883 if (source[i] == '#') {
884 uriFragment = true;
885 i++;
886 }
887
888 if (i != length && source[i] != '/') {
890 goto error;
891 }
892
893 while (i < length) {
894 RAPIDJSON_ASSERT(source[i] == '/');
895 i++; // consumes '/'
896
897 token->name = name;
898 bool isNumber = true;
899
900 while (i < length && source[i] != '/') {
901 Ch c = source[i];
902 if (uriFragment) {
903 // Decoding percent-encoding for URI fragment
904 if (c == '%') {
905 PercentDecodeStream is(&source[i], source + length);
907 Ch* begin = os.PutBegin();
908 if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
910 goto error;
911 }
912 size_t len = os.PutEnd(begin);
913 i += is.Tell() - 1;
914 if (len == 1)
915 c = *name;
916 else {
917 name += len;
918 isNumber = false;
919 i++;
920 continue;
921 }
922 }
923 else if (NeedPercentEncode(c)) {
925 goto error;
926 }
927 }
928
929 i++;
930
931 // Escaping "~0" -> '~', "~1" -> '/'
932 if (c == '~') {
933 if (i < length) {
934 c = source[i];
935 if (c == '0') c = '~';
936 else if (c == '1') c = '/';
937 else {
939 goto error;
940 }
941 i++;
942 }
943 else {
945 goto error;
946 }
947 }
948
949 // First check for index: all of characters are digit
950 if (c < '0' || c > '9')
951 isNumber = false;
952
953 *name++ = c;
954 }
955 token->length = static_cast<SizeType>(name - token->name);
956 if (token->length == 0)
957 isNumber = false;
958 *name++ = '\0'; // Null terminator
959
960 // Second check for index: more than one digit cannot have leading zero
961 if (isNumber && token->length > 1 && token->name[0] == '0')
962 isNumber = false;
963
964 // String to SizeType conversion
965 SizeType n = 0;
966 if (isNumber) {
967 for (size_t j = 0; j < token->length; j++) {
968 SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
969 if (m < n) { // overflow detection
970 isNumber = false;
971 break;
972 }
973 n = m;
974 }
975 }
976
977 token->index = isNumber ? n : kPointerInvalidIndex;
978 token++;
979 }
980
981 RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
983 return;
984
985 error:
986 Allocator::Free(tokens_);
987 nameBuffer_ = 0;
988 tokens_ = 0;
989 tokenCount_ = 0;
991 return;
992 }
993
995
1000 template<bool uriFragment, typename OutputStream>
1001 bool Stringify(OutputStream& os) const {
1002 RAPIDJSON_ASSERT(IsValid());
1003
1004 if (uriFragment)
1005 os.Put('#');
1006
1007 for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
1008 os.Put('/');
1009 for (size_t j = 0; j < t->length; j++) {
1010 Ch c = t->name[j];
1011 if (c == '~') {
1012 os.Put('~');
1013 os.Put('0');
1014 }
1015 else if (c == '/') {
1016 os.Put('~');
1017 os.Put('1');
1018 }
1019 else if (uriFragment && NeedPercentEncode(c)) {
1020 // Transcode to UTF8 sequence
1022 PercentEncodeStream<OutputStream> target(os);
1023 if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
1024 return false;
1025 j += source.Tell() - 1;
1026 }
1027 else
1028 os.Put(c);
1029 }
1030 }
1031 return true;
1032 }
1033
1035
1040 class PercentDecodeStream {
1041 public:
1042 typedef typename ValueType::Ch Ch;
1043
1045
1049 PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
1050
1051 Ch Take() {
1052 if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
1053 valid_ = false;
1054 return 0;
1055 }
1056 src_++;
1057 Ch c = 0;
1058 for (int j = 0; j < 2; j++) {
1059 c = static_cast<Ch>(c << 4);
1060 Ch h = *src_;
1061 if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
1062 else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
1063 else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
1064 else {
1065 valid_ = false;
1066 return 0;
1067 }
1068 src_++;
1069 }
1070 return c;
1071 }
1072
1073 size_t Tell() const { return static_cast<size_t>(src_ - head_); }
1074 bool IsValid() const { return valid_; }
1075
1076 private:
1077 const Ch* src_;
1078 const Ch* head_;
1079 const Ch* end_;
1080 bool valid_;
1081 };
1082
1084 template <typename OutputStream>
1086 public:
1087 PercentEncodeStream(OutputStream& os) : os_(os) {}
1088 void Put(char c) { // UTF-8 must be byte
1089 unsigned char u = static_cast<unsigned char>(c);
1090 static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1091 os_.Put('%');
1092 os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
1093 os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
1094 }
1095 private:
1096 OutputStream& os_;
1097 };
1098
1106};
1107
1110
1112
1113
1115
1116template <typename T>
1117typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
1118 return pointer.Create(root, a);
1119}
1120
1121template <typename T, typename CharType, size_t N>
1122typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
1123 return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
1124}
1125
1126// No allocator parameter
1127
1128template <typename DocumentType>
1129typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
1130 return pointer.Create(document);
1131}
1132
1133template <typename DocumentType, typename CharType, size_t N>
1134typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
1135 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
1136}
1137
1139
1140template <typename T>
1141typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1142 return pointer.Get(root, unresolvedTokenIndex);
1143}
1144
1145template <typename T>
1146const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1147 return pointer.Get(root, unresolvedTokenIndex);
1148}
1149
1150template <typename T, typename CharType, size_t N>
1151typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
1152 return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1153}
1154
1155template <typename T, typename CharType, size_t N>
1156const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
1157 return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1158}
1159
1161
1162template <typename T>
1163typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1164 return pointer.GetWithDefault(root, defaultValue, a);
1165}
1166
1167template <typename T>
1168typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1169 return pointer.GetWithDefault(root, defaultValue, a);
1170}
1171
1172#if RAPIDJSON_HAS_STDSTRING
1173template <typename T>
1174typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1175 return pointer.GetWithDefault(root, defaultValue, a);
1176}
1177#endif
1178
1179template <typename T, typename T2>
1180RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1181GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
1182 return pointer.GetWithDefault(root, defaultValue, a);
1183}
1184
1185template <typename T, typename CharType, size_t N>
1186typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1187 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1188}
1189
1190template <typename T, typename CharType, size_t N>
1191typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1192 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1193}
1194
1195#if RAPIDJSON_HAS_STDSTRING
1196template <typename T, typename CharType, size_t N>
1197typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1198 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1199}
1200#endif
1201
1202template <typename T, typename CharType, size_t N, typename T2>
1203RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1204GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
1205 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1206}
1207
1208// No allocator parameter
1209
1210template <typename DocumentType>
1211typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
1212 return pointer.GetWithDefault(document, defaultValue);
1213}
1214
1215template <typename DocumentType>
1216typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
1217 return pointer.GetWithDefault(document, defaultValue);
1218}
1219
1220#if RAPIDJSON_HAS_STDSTRING
1221template <typename DocumentType>
1222typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1223 return pointer.GetWithDefault(document, defaultValue);
1224}
1225#endif
1226
1227template <typename DocumentType, typename T2>
1228RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1230 return pointer.GetWithDefault(document, defaultValue);
1231}
1232
1233template <typename DocumentType, typename CharType, size_t N>
1234typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
1235 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1236}
1237
1238template <typename DocumentType, typename CharType, size_t N>
1239typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
1240 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1241}
1242
1243#if RAPIDJSON_HAS_STDSTRING
1244template <typename DocumentType, typename CharType, size_t N>
1245typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1246 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1247}
1248#endif
1249
1250template <typename DocumentType, typename CharType, size_t N, typename T2>
1251RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1252GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
1253 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1254}
1255
1257
1258template <typename T>
1259typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1260 return pointer.Set(root, value, a);
1261}
1262
1263template <typename T>
1264typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
1265 return pointer.Set(root, value, a);
1266}
1267
1268template <typename T>
1269typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
1270 return pointer.Set(root, value, a);
1271}
1272
1273#if RAPIDJSON_HAS_STDSTRING
1274template <typename T>
1275typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1276 return pointer.Set(root, value, a);
1277}
1278#endif
1279
1280template <typename T, typename T2>
1281RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1282SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
1283 return pointer.Set(root, value, a);
1284}
1285
1286template <typename T, typename CharType, size_t N>
1287typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1288 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1289}
1290
1291template <typename T, typename CharType, size_t N>
1292typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
1293 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1294}
1295
1296template <typename T, typename CharType, size_t N>
1297typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
1298 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1299}
1300
1301#if RAPIDJSON_HAS_STDSTRING
1302template <typename T, typename CharType, size_t N>
1303typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1304 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1305}
1306#endif
1307
1308template <typename T, typename CharType, size_t N, typename T2>
1309RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1310SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
1311 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1312}
1313
1314// No allocator parameter
1315
1316template <typename DocumentType>
1317typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1318 return pointer.Set(document, value);
1319}
1320
1321template <typename DocumentType>
1322typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
1323 return pointer.Set(document, value);
1324}
1325
1326template <typename DocumentType>
1327typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
1328 return pointer.Set(document, value);
1329}
1330
1331#if RAPIDJSON_HAS_STDSTRING
1332template <typename DocumentType>
1333typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
1334 return pointer.Set(document, value);
1335}
1336#endif
1337
1338template <typename DocumentType, typename T2>
1339RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1341 return pointer.Set(document, value);
1342}
1343
1344template <typename DocumentType, typename CharType, size_t N>
1345typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1347}
1348
1349template <typename DocumentType, typename CharType, size_t N>
1350typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
1352}
1353
1354template <typename DocumentType, typename CharType, size_t N>
1355typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
1357}
1358
1359#if RAPIDJSON_HAS_STDSTRING
1360template <typename DocumentType, typename CharType, size_t N>
1361typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
1363}
1364#endif
1365
1366template <typename DocumentType, typename CharType, size_t N, typename T2>
1367RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1368SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
1370}
1371
1373
1374template <typename T>
1375typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1376 return pointer.Swap(root, value, a);
1377}
1378
1379template <typename T, typename CharType, size_t N>
1380typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1382}
1383
1384template <typename DocumentType>
1385typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1386 return pointer.Swap(document, value);
1387}
1388
1389template <typename DocumentType, typename CharType, size_t N>
1390typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1392}
1393
1395
1396template <typename T>
1398 return pointer.Erase(root);
1399}
1400
1401template <typename T, typename CharType, size_t N>
1402bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
1403 return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
1404}
1405
1407
1409
1410#if defined(__clang__) || defined(_MSC_VER)
1411RAPIDJSON_DIAG_POP
1412#endif
1413
1414#endif // RAPIDJSON_POINTER_H_
bool operator<(const CBigNum &a, const CBigNum &b)
Definition base58.cpp:498
const mie::Vuint & p
Definition bn.cpp:27
const mie::Vuint & r
Definition bn.cpp:28
std::string name
A document for parsing JSON text as DOM.
Definition document.h:2124
Allocator & GetAllocator()
Get the allocator of this document.
Definition document.h:2412
A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
Definition pointer.h:1085
PercentEncodeStream(OutputStream &os)
Definition pointer.h:1087
Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
Definition pointer.h:79
ValueType::EncodingType EncodingType
Encoding type from Value.
Definition pointer.h:81
friend void swap(GenericPointer &a, GenericPointer &b) RAPIDJSON_NOEXCEPT
free-standing swap function helper
Definition pointer.h:231
Ch * nameBuffer_
A buffer containing all names in tokens.
Definition pointer.h:1101
Allocator * allocator_
The current allocator. It is either user-supplied or equal to ownAllocator_.
Definition pointer.h:1099
GenericPointer(const GenericPointer &rhs, Allocator *allocator)
Copy constructor.
Definition pointer.h:171
GenericPointer(const Ch *source, Allocator *allocator=0)
Constructor that parses a string or URI fragment representation.
Definition pointer.h:114
GenericPointer(const Token *tokens, size_t tokenCount)
Constructor with user-supplied tokens.
Definition pointer.h:163
GenericPointer(Allocator *allocator=0)
Default constructor.
Definition pointer.h:107
size_t tokenCount_
Number of tokens in tokens_.
Definition pointer.h:1103
ValueType::Ch Ch
Character type from Value.
Definition pointer.h:82
GenericPointer(const GenericPointer &rhs)
Copy constructor.
Definition pointer.h:166
PointerParseErrorCode parseErrorCode_
Parsing error code.
Definition pointer.h:1105
Token * tokens_
A list of tokens.
Definition pointer.h:1102
Allocator * ownAllocator_
Allocator owned by this Pointer.
Definition pointer.h:1100
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
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:262
GenericPointer Append(const Token &token, Allocator *allocator=0) const
Append a token and return a new Pointer.
Definition pointer.h:244
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.
~GenericPointer()
Destructor.
Definition pointer.h:176
size_t parseErrorOffset_
Offset in code unit when parsing fail.
Definition pointer.h:1104
GenericPointer & operator=(const GenericPointer &rhs)
Assignment operator.
Definition pointer.h:183
Allocator * allocator
Definition pointer.h:275
GenericPointer & Swap(GenericPointer &other) RAPIDJSON_NOEXCEPT
Swap the content of this pointer with an other.
Definition pointer.h:208
Concept for allocating, resizing and freeing memory block.
bool operator!=(const environment &other)
os_t os
bool operator==(const environment &other)
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition rapidjson.h:406
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition rapidjson.h:121
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition rapidjson.h:124
PointerParseErrorCode
Error code of parsing.
Definition pointer.h:37
@ kPointerParseErrorInvalidEscape
Invalid escape.
Definition pointer.h:41
@ kPointerParseErrorTokenMustBeginWithSolidus
A token must begin with a '/'.
Definition pointer.h:40
@ kPointerParseErrorNone
The parse is successful.
Definition pointer.h:38
@ kPointerParseErrorCharacterMustPercentEncode
A character must percent encoded in URI fragment.
Definition pointer.h:43
@ kPointerParseErrorInvalidPercentEncoding
Invalid percent encoding in URI fragment.
Definition pointer.h:42
#define Ch(x, y, z)
Definition hash_impl.h:17
void diff(const std::string &a, const std::string &b)
Definition jmp.cpp:18
ValueType
Definition Types.h:14
char * u64toa(uint64_t value, char *buffer)
Definition itoa.h:126
void Swap(T &a, T &b) RAPIDJSON_NOEXCEPT
Custom swap() to avoid dependency on C++ <algorithm> header.
Definition swap.h:33
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
Definition strfunc.h:31
char * u32toa(uint32_t value, char *buffer)
Definition itoa.h:39
const GenericPointer< typename T::ValueType > T2 value
Definition pointer.h:1282
const GenericPointer< typename T::ValueType > T2 defaultValue
Definition pointer.h:1181
T::ValueType & SwapValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::ValueType &value, typename T::AllocatorType &a)
Definition pointer.h:1375
T::ValueType & SetValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::ValueType &value, typename T::AllocatorType &a)
Definition pointer.h:1259
T::ValueType * GetValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, size_t *unresolvedTokenIndex=0)
Definition pointer.h:1141
bool EraseValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer)
Definition pointer.h:1397
T::ValueType & CreateValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::AllocatorType &a)
Definition pointer.h:1117
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr< internal::IsPointer< T2 >, internal::IsGenericValue< T2 > >),(typename T::ValueType &)) GetValueByPointerWithDefault(T &root
GenericPointer< Value > Pointer
GenericPointer for Value (UTF-8, default allocator).
Definition pointer.h:1109
const GenericPointer< typename T::ValueType > & pointer
Definition pointer.h:1181
T::ValueType & GetValueByPointerWithDefault(T &root, const GenericPointer< typename T::ValueType > &pointer, const typename T::ValueType &defaultValue, typename T::AllocatorType &a)
Definition pointer.h:1163
const CharType(& source)[N]
Definition pointer.h:1204
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
#define T(meth, val, expected)
const int N
Definition quantize.cpp:54
@ kObjectType
object
Definition rapidjson.h:648
@ kArrayType
array
Definition rapidjson.h:649
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition rapidjson.h:631
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition rapidjson.h:384
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition rapidjson.h:627
A read-write string stream.
Definition stream.h:188
A token is the basic units of internal representation.
Definition pointer.h:97
SizeType index
A valid array index, if it is not equal to kPointerInvalidIndex.
Definition pointer.h:100
SizeType length
Length of the name.
Definition pointer.h:99
const Ch * name
Name of the token. It has null character at the end but it can contain null character.
Definition pointer.h:98
Reference to a constant string (not taking a copy)
Definition document.h:256
Read-only string stream.
Definition stream.h:154
Encoding conversion.
Definition encodings.h:658
UTF-8 encoding.
Definition encodings.h:96
void cmp(const Operand &op, uint32 imm)
char * s
uint16_t j
size_t len