Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
pointer.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2// Tencent is pleased to support the open source community by making RapidJSON available.
3//
4// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
5//
6// Licensed under the MIT License (the "License"); you may not use this file except
7// in compliance with the License. You may obtain a copy of the License at
8//
9// http://opensource.org/licenses/MIT
10//
11// Unless required by applicable law or agreed to in writing, software distributed
12// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
13// CONDITIONS OF ANY KIND, either express or implied. See the License for the
14// specific language governing permissions and limitations under the License.
15
16#ifndef RAPIDJSON_POINTER_H_
17#define RAPIDJSON_POINTER_H_
18
19#include "document.h"
20#include "internal/itoa.h"
21
22#ifdef __clang__
23RAPIDJSON_DIAG_PUSH
24RAPIDJSON_DIAG_OFF(switch-enum)
25#elif defined(_MSC_VER)
26RAPIDJSON_DIAG_PUSH
27RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
28#endif
29
31
32static const SizeType kPointerInvalidIndex = ~SizeType(0);
33
35
46
48// GenericPointer
49
51
79template <typename ValueType, typename Allocator = CrtAllocator>
81public:
82 typedef typename ValueType::EncodingType EncodingType;
83 typedef typename ValueType::Ch Ch;
84
86
103
105
106
109
111
116 Parse(source, internal::StrLen(source));
117 }
118
119#if RAPIDJSON_HAS_STDSTRING
121
126 explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
127 Parse(source.c_str(), source.size());
128 }
129#endif
130
132
139 Parse(source, length);
140 }
141
143
164 GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
165
170
175
178 if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
179 Allocator::Free(tokens_);
181 }
182
185 if (this != &rhs) {
186 // Do not delete ownAllcator
187 if (nameBuffer_)
188 Allocator::Free(tokens_);
189
193
194 if (rhs.nameBuffer_)
195 CopyFromRaw(rhs); // Normally parsed tokens.
196 else {
197 tokens_ = rhs.tokens_; // User supplied const tokens.
198 nameBuffer_ = 0;
199 }
200 }
201 return *this;
202 }
203
205
209 GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT {
210 internal::Swap(allocator_, other.allocator_);
211 internal::Swap(ownAllocator_, other.ownAllocator_);
212 internal::Swap(nameBuffer_, other.nameBuffer_);
213 internal::Swap(tokens_, other.tokens_);
214 internal::Swap(tokenCount_, other.tokenCount_);
215 internal::Swap(parseErrorOffset_, other.parseErrorOffset_);
216 internal::Swap(parseErrorCode_, other.parseErrorCode_);
217 return *this;
218 }
219
221
232 friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
233
235
237
238
240
245 GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
247 r.allocator_ = allocator;
248 Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
249 std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
250 r.tokens_[tokenCount_].name = p;
251 r.tokens_[tokenCount_].length = token.length;
252 r.tokens_[tokenCount_].index = token.index;
253 return r;
254 }
255
257
263 GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
264 Token token = { name, length, kPointerInvalidIndex };
265 return Append(token, allocator);
266 }
267
269
274 template <typename T>
275 RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
276 Append(T* name, Allocator* allocator = 0) const {
277 return Append(name, internal::StrLen(name), allocator);
278 }
279
280#if RAPIDJSON_HAS_STDSTRING
282
287 GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
288 return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
289 }
290#endif
291
293
298 GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
299 char buffer[21];
300 char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
301 SizeType length = static_cast<SizeType>(end - buffer);
302 buffer[length] = '\0';
303
304 if (sizeof(Ch) == 1) {
305 Token token = { reinterpret_cast<Ch*>(buffer), length, index };
306 return Append(token, allocator);
307 }
308 else {
309 Ch name[21];
310 for (size_t i = 0; i <= length; i++)
311 name[i] = static_cast<Ch>(buffer[i]);
312 Token token = { name, length, index };
313 return Append(token, allocator);
314 }
315 }
316
318
323 GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
324 if (token.IsString())
325 return Append(token.GetString(), token.GetStringLength(), allocator);
326 else {
327 RAPIDJSON_ASSERT(token.IsUint64());
328 RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
329 return Append(static_cast<SizeType>(token.GetUint64()), allocator);
330 }
331 }
332
334
335
337 bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
338
340 size_t GetParseErrorOffset() const { return parseErrorOffset_; }
341
343 PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
344
346
348 Allocator& GetAllocator() { return *allocator_; }
349
351
352
354 const Token* GetTokens() const { return tokens_; }
355
357 size_t GetTokenCount() const { return tokenCount_; }
358
360
362
363
365
368 bool operator==(const GenericPointer& rhs) const {
369 if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
370 return false;
371
372 for (size_t i = 0; i < tokenCount_; i++) {
373 if (tokens_[i].index != rhs.tokens_[i].index ||
374 tokens_[i].length != rhs.tokens_[i].length ||
375 (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
376 {
377 return false;
378 }
379 }
380
381 return true;
382 }
383
385
388 bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
389
391
394 bool operator<(const GenericPointer& rhs) const {
395 if (!IsValid())
396 return false;
397 if (!rhs.IsValid())
398 return true;
399
400 if (tokenCount_ != rhs.tokenCount_)
401 return tokenCount_ < rhs.tokenCount_;
402
403 for (size_t i = 0; i < tokenCount_; i++) {
404 if (tokens_[i].index != rhs.tokens_[i].index)
405 return tokens_[i].index < rhs.tokens_[i].index;
406
407 if (tokens_[i].length != rhs.tokens_[i].length)
408 return tokens_[i].length < rhs.tokens_[i].length;
409
410 if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length))
411 return cmp < 0;
412 }
413
414 return false;
415 }
416
418
420
421
423
427 template<typename OutputStream>
428 bool Stringify(OutputStream& os) const {
429 return Stringify<false, OutputStream>(os);
430 }
431
433
437 template<typename OutputStream>
438 bool StringifyUriFragment(OutputStream& os) const {
439 return Stringify<true, OutputStream>(os);
440 }
441
443
445
446
448
462 ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
463 RAPIDJSON_ASSERT(IsValid());
464 ValueType* v = &root;
465 bool exist = true;
466 for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
467 if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
468 v->PushBack(ValueType().Move(), allocator);
469 v = &((*v)[v->Size() - 1]);
470 exist = false;
471 }
472 else {
473 if (t->index == kPointerInvalidIndex) { // must be object name
474 if (!v->IsObject())
475 v->SetObject(); // Change to Object
476 }
477 else { // object name or array index
478 if (!v->IsArray() && !v->IsObject())
479 v->SetArray(); // Change to Array
480 }
481
482 if (v->IsArray()) {
483 if (t->index >= v->Size()) {
484 v->Reserve(t->index + 1, allocator);
485 while (t->index >= v->Size())
486 v->PushBack(ValueType().Move(), allocator);
487 exist = false;
488 }
489 v = &((*v)[t->index]);
490 }
491 else {
492 typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
493 if (m == v->MemberEnd()) {
494 v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
495 m = v->MemberEnd();
496 v = &(--m)->value; // Assumes AddMember() appends at the end
497 exist = false;
498 }
499 else
500 v = &m->value;
501 }
502 }
503 }
504
505 if (alreadyExist)
506 *alreadyExist = exist;
507
508 return *v;
509 }
510
512
517 template <typename stackAllocator>
518 ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
519 return Create(document, document.GetAllocator(), alreadyExist);
520 }
521
523
525
526
528
541 ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
542 RAPIDJSON_ASSERT(IsValid());
543 ValueType* v = &root;
544 for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
545 switch (v->GetType()) {
546 case kObjectType:
547 {
548 typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
549 if (m == v->MemberEnd())
550 break;
551 v = &m->value;
552 }
553 continue;
554 case kArrayType:
555 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
556 break;
557 v = &((*v)[t->index]);
558 continue;
559 default:
560 break;
561 }
562
563 // Error: unresolved token
564 if (unresolvedTokenIndex)
565 *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
566 return 0;
567 }
568 return v;
569 }
570
572
576 const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
577 return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
578 }
579
581
583
584
586
595 ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
596 bool alreadyExist;
597 ValueType& v = Create(root, allocator, &alreadyExist);
598 return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
599 }
600
602 ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
603 bool alreadyExist;
604 ValueType& v = Create(root, allocator, &alreadyExist);
605 return alreadyExist ? v : v.SetString(defaultValue, allocator);
606 }
607
608#if RAPIDJSON_HAS_STDSTRING
610 ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
611 bool alreadyExist;
612 ValueType& v = Create(root, allocator, &alreadyExist);
613 return alreadyExist ? v : v.SetString(defaultValue, allocator);
614 }
615#endif
616
618
621 template <typename T>
622 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
623 GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
624 return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
625 }
626
628 template <typename stackAllocator>
629 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const {
630 return GetWithDefault(document, defaultValue, document.GetAllocator());
631 }
632
634 template <typename stackAllocator>
635 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
636 return GetWithDefault(document, defaultValue, document.GetAllocator());
637 }
638
639#if RAPIDJSON_HAS_STDSTRING
641 template <typename stackAllocator>
642 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
643 return GetWithDefault(document, defaultValue, document.GetAllocator());
644 }
645#endif
646
648
651 template <typename T, typename stackAllocator>
652 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
653 GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
654 return GetWithDefault(document, defaultValue, document.GetAllocator());
655 }
656
658
660
661
663
672 ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
673 return Create(root, allocator) = value;
674 }
675
677 ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
678 return Create(root, allocator).CopyFrom(value, allocator);
679 }
680
682 ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
683 return Create(root, allocator) = ValueType(value, allocator).Move();
684 }
685
686#if RAPIDJSON_HAS_STDSTRING
688 ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
689 return Create(root, allocator) = ValueType(value, allocator).Move();
690 }
691#endif
692
694
697 template <typename T>
698 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
699 Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
700 return Create(root, allocator) = ValueType(value).Move();
701 }
702
704 template <typename stackAllocator>
705 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
706 return Create(document) = value;
707 }
708
710 template <typename stackAllocator>
711 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {
712 return Create(document).CopyFrom(value, document.GetAllocator());
713 }
714
716 template <typename stackAllocator>
718 return Create(document) = ValueType(value, document.GetAllocator()).Move();
719 }
720
721#if RAPIDJSON_HAS_STDSTRING
723 template <typename stackAllocator>
724 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
725 return Create(document) = ValueType(value, document.GetAllocator()).Move();
726 }
727#endif
728
730
733 template <typename T, typename stackAllocator>
734 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
736 return Create(document) = value;
737 }
738
740
742
743
745
754 ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
755 return Create(root, allocator).Swap(value);
756 }
757
759 template <typename stackAllocator>
761 return Create(document).Swap(value);
762 }
763
765
767
773 bool Erase(ValueType& root) const {
774 RAPIDJSON_ASSERT(IsValid());
775 if (tokenCount_ == 0) // Cannot erase the root
776 return false;
777
778 ValueType* v = &root;
779 const Token* last = tokens_ + (tokenCount_ - 1);
780 for (const Token *t = tokens_; t != last; ++t) {
781 switch (v->GetType()) {
782 case kObjectType:
783 {
784 typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
785 if (m == v->MemberEnd())
786 return false;
787 v = &m->value;
788 }
789 break;
790 case kArrayType:
791 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
792 return false;
793 v = &((*v)[t->index]);
794 break;
795 default:
796 return false;
797 }
798 }
799
800 switch (v->GetType()) {
801 case kObjectType:
802 return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
803 case kArrayType:
804 if (last->index == kPointerInvalidIndex || last->index >= v->Size())
805 return false;
806 v->Erase(v->Begin() + last->index);
807 return true;
808 default:
809 return false;
810 }
811 }
812
813private:
815
821 Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
822 if (!allocator_) // allocator is independently owned.
824
825 size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
826 for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
827 nameBufferSize += t->length;
828
829 tokenCount_ = rhs.tokenCount_ + extraToken;
830 tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
831 nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
832 if (rhs.tokenCount_ > 0) {
833 std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
834 }
835 if (nameBufferSize > 0) {
836 std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
837 }
838
839 // Adjust pointers to name buffer
840 std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
841 for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
842 t->name += diff;
843
844 return nameBuffer_ + nameBufferSize;
845 }
846
848
852 bool NeedPercentEncode(Ch c) const {
853 return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
854 }
855
857#ifndef __clang__ // -Wdocumentation
863#endif
864 void Parse(const Ch* source, size_t length) {
865 RAPIDJSON_ASSERT(source != NULL);
868
869 // Create own allocator if user did not supply.
870 if (!allocator_)
872
873 // Count number of '/' as tokenCount
874 tokenCount_ = 0;
875 for (const Ch* s = source; s != source + length; s++)
876 if (*s == '/')
877 tokenCount_++;
878
879 Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
880 Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
881 size_t i = 0;
882
883 // Detect if it is a URI fragment
884 bool uriFragment = false;
885 if (source[i] == '#') {
886 uriFragment = true;
887 i++;
888 }
889
890 if (i != length && source[i] != '/') {
892 goto error;
893 }
894
895 while (i < length) {
896 RAPIDJSON_ASSERT(source[i] == '/');
897 i++; // consumes '/'
898
899 token->name = name;
900 bool isNumber = true;
901
902 while (i < length && source[i] != '/') {
903 Ch c = source[i];
904 if (uriFragment) {
905 // Decoding percent-encoding for URI fragment
906 if (c == '%') {
907 PercentDecodeStream is(&source[i], source + length);
909 Ch* begin = os.PutBegin();
910 if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
912 goto error;
913 }
914 size_t len = os.PutEnd(begin);
915 i += is.Tell() - 1;
916 if (len == 1)
917 c = *name;
918 else {
919 name += len;
920 isNumber = false;
921 i++;
922 continue;
923 }
924 }
925 else if (NeedPercentEncode(c)) {
927 goto error;
928 }
929 }
930
931 i++;
932
933 // Escaping "~0" -> '~', "~1" -> '/'
934 if (c == '~') {
935 if (i < length) {
936 c = source[i];
937 if (c == '0') c = '~';
938 else if (c == '1') c = '/';
939 else {
941 goto error;
942 }
943 i++;
944 }
945 else {
947 goto error;
948 }
949 }
950
951 // First check for index: all of characters are digit
952 if (c < '0' || c > '9')
953 isNumber = false;
954
955 *name++ = c;
956 }
957 token->length = static_cast<SizeType>(name - token->name);
958 if (token->length == 0)
959 isNumber = false;
960 *name++ = '\0'; // Null terminator
961
962 // Second check for index: more than one digit cannot have leading zero
963 if (isNumber && token->length > 1 && token->name[0] == '0')
964 isNumber = false;
965
966 // String to SizeType conversion
967 SizeType n = 0;
968 if (isNumber) {
969 for (size_t j = 0; j < token->length; j++) {
970 SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
971 if (m < n) { // overflow detection
972 isNumber = false;
973 break;
974 }
975 n = m;
976 }
977 }
978
979 token->index = isNumber ? n : kPointerInvalidIndex;
980 token++;
981 }
982
983 RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
985 return;
986
987 error:
988 Allocator::Free(tokens_);
989 nameBuffer_ = 0;
990 tokens_ = 0;
991 tokenCount_ = 0;
993 return;
994 }
995
997
1002 template<bool uriFragment, typename OutputStream>
1003 bool Stringify(OutputStream& os) const {
1004 RAPIDJSON_ASSERT(IsValid());
1005
1006 if (uriFragment)
1007 os.Put('#');
1008
1009 for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
1010 os.Put('/');
1011 for (size_t j = 0; j < t->length; j++) {
1012 Ch c = t->name[j];
1013 if (c == '~') {
1014 os.Put('~');
1015 os.Put('0');
1016 }
1017 else if (c == '/') {
1018 os.Put('~');
1019 os.Put('1');
1020 }
1021 else if (uriFragment && NeedPercentEncode(c)) {
1022 // Transcode to UTF8 sequence
1024 PercentEncodeStream<OutputStream> target(os);
1025 if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
1026 return false;
1027 j += source.Tell() - 1;
1028 }
1029 else
1030 os.Put(c);
1031 }
1032 }
1033 return true;
1034 }
1035
1037
1042 class PercentDecodeStream {
1043 public:
1044 typedef typename ValueType::Ch Ch;
1045
1047
1051 PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
1052
1053 Ch Take() {
1054 if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
1055 valid_ = false;
1056 return 0;
1057 }
1058 src_++;
1059 Ch c = 0;
1060 for (int j = 0; j < 2; j++) {
1061 c = static_cast<Ch>(c << 4);
1062 Ch h = *src_;
1063 if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
1064 else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
1065 else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
1066 else {
1067 valid_ = false;
1068 return 0;
1069 }
1070 src_++;
1071 }
1072 return c;
1073 }
1074
1075 size_t Tell() const { return static_cast<size_t>(src_ - head_); }
1076 bool IsValid() const { return valid_; }
1077
1078 private:
1079 const Ch* src_;
1080 const Ch* head_;
1081 const Ch* end_;
1082 bool valid_;
1083 };
1084
1086 template <typename OutputStream>
1088 public:
1089 PercentEncodeStream(OutputStream& os) : os_(os) {}
1090 void Put(char c) { // UTF-8 must be byte
1091 unsigned char u = static_cast<unsigned char>(c);
1092 static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1093 os_.Put('%');
1094 os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
1095 os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
1096 }
1097 private:
1098 OutputStream& os_;
1099 };
1100
1108};
1109
1112
1114
1115
1117
1118template <typename T>
1119typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
1120 return pointer.Create(root, a);
1121}
1122
1123template <typename T, typename CharType, size_t N>
1124typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
1125 return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
1126}
1127
1128// No allocator parameter
1129
1130template <typename DocumentType>
1131typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
1132 return pointer.Create(document);
1133}
1134
1135template <typename DocumentType, typename CharType, size_t N>
1136typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
1137 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
1138}
1139
1141
1142template <typename T>
1143typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1144 return pointer.Get(root, unresolvedTokenIndex);
1145}
1146
1147template <typename T>
1148const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1149 return pointer.Get(root, unresolvedTokenIndex);
1150}
1151
1152template <typename T, typename CharType, size_t N>
1153typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
1154 return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1155}
1156
1157template <typename T, typename CharType, size_t N>
1158const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
1159 return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1160}
1161
1163
1164template <typename T>
1165typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1166 return pointer.GetWithDefault(root, defaultValue, a);
1167}
1168
1169template <typename T>
1170typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1171 return pointer.GetWithDefault(root, defaultValue, a);
1172}
1173
1174#if RAPIDJSON_HAS_STDSTRING
1175template <typename T>
1176typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1177 return pointer.GetWithDefault(root, defaultValue, a);
1178}
1179#endif
1180
1181template <typename T, typename T2>
1182RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1183GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
1184 return pointer.GetWithDefault(root, defaultValue, a);
1185}
1186
1187template <typename T, typename CharType, size_t N>
1188typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1189 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1190}
1191
1192template <typename T, typename CharType, size_t N>
1193typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1194 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1195}
1196
1197#if RAPIDJSON_HAS_STDSTRING
1198template <typename T, typename CharType, size_t N>
1199typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1200 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1201}
1202#endif
1203
1204template <typename T, typename CharType, size_t N, typename T2>
1205RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1206GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
1207 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1208}
1209
1210// No allocator parameter
1211
1212template <typename DocumentType>
1213typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
1214 return pointer.GetWithDefault(document, defaultValue);
1215}
1216
1217template <typename DocumentType>
1218typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
1219 return pointer.GetWithDefault(document, defaultValue);
1220}
1221
1222#if RAPIDJSON_HAS_STDSTRING
1223template <typename DocumentType>
1224typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1225 return pointer.GetWithDefault(document, defaultValue);
1226}
1227#endif
1228
1229template <typename DocumentType, typename T2>
1230RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1231GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
1232 return pointer.GetWithDefault(document, defaultValue);
1233}
1234
1235template <typename DocumentType, typename CharType, size_t N>
1236typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
1237 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1238}
1239
1240template <typename DocumentType, typename CharType, size_t N>
1241typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
1242 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1243}
1244
1245#if RAPIDJSON_HAS_STDSTRING
1246template <typename DocumentType, typename CharType, size_t N>
1247typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1248 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1249}
1250#endif
1251
1252template <typename DocumentType, typename CharType, size_t N, typename T2>
1253RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1254GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
1255 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1256}
1257
1259
1260template <typename T>
1261typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1262 return pointer.Set(root, value, a);
1263}
1264
1265template <typename T>
1266typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
1267 return pointer.Set(root, value, a);
1268}
1269
1270template <typename T>
1271typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
1272 return pointer.Set(root, value, a);
1273}
1274
1275#if RAPIDJSON_HAS_STDSTRING
1276template <typename T>
1277typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1278 return pointer.Set(root, value, a);
1279}
1280#endif
1281
1282template <typename T, typename T2>
1283RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1284SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
1285 return pointer.Set(root, value, a);
1286}
1287
1288template <typename T, typename CharType, size_t N>
1289typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1290 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1291}
1292
1293template <typename T, typename CharType, size_t N>
1294typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
1295 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1296}
1297
1298template <typename T, typename CharType, size_t N>
1299typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
1300 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1301}
1302
1303#if RAPIDJSON_HAS_STDSTRING
1304template <typename T, typename CharType, size_t N>
1305typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1306 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1307}
1308#endif
1309
1310template <typename T, typename CharType, size_t N, typename T2>
1311RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1312SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
1313 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1314}
1315
1316// No allocator parameter
1317
1318template <typename DocumentType>
1319typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1320 return pointer.Set(document, value);
1321}
1322
1323template <typename DocumentType>
1324typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
1325 return pointer.Set(document, value);
1326}
1327
1328template <typename DocumentType>
1329typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
1330 return pointer.Set(document, value);
1331}
1332
1333#if RAPIDJSON_HAS_STDSTRING
1334template <typename DocumentType>
1335typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
1336 return pointer.Set(document, value);
1337}
1338#endif
1339
1340template <typename DocumentType, typename T2>
1341RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1342SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
1343 return pointer.Set(document, value);
1344}
1345
1346template <typename DocumentType, typename CharType, size_t N>
1347typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1348 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1349}
1350
1351template <typename DocumentType, typename CharType, size_t N>
1352typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
1353 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1354}
1355
1356template <typename DocumentType, typename CharType, size_t N>
1357typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
1358 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1359}
1360
1361#if RAPIDJSON_HAS_STDSTRING
1362template <typename DocumentType, typename CharType, size_t N>
1363typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
1364 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1365}
1366#endif
1367
1368template <typename DocumentType, typename CharType, size_t N, typename T2>
1369RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1370SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
1371 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1372}
1373
1375
1376template <typename T>
1377typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1378 return pointer.Swap(root, value, a);
1379}
1380
1381template <typename T, typename CharType, size_t N>
1382typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1383 return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
1384}
1385
1386template <typename DocumentType>
1387typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1388 return pointer.Swap(document, value);
1389}
1390
1391template <typename DocumentType, typename CharType, size_t N>
1392typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1393 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
1394}
1395
1397
1398template <typename T>
1399bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
1400 return pointer.Erase(root);
1401}
1402
1403template <typename T, typename CharType, size_t N>
1404bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
1405 return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
1406}
1407
1409
1411
1412#if defined(__clang__) || defined(_MSC_VER)
1413RAPIDJSON_DIAG_POP
1414#endif
1415
1416#endif // RAPIDJSON_POINTER_H_
A document for parsing JSON text as DOM.
Definition document.h:2155
Allocator & GetAllocator()
Get the allocator of this document.
Definition document.h:2443
A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
Definition pointer.h:1087
Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
Definition pointer.h:80
friend void swap(GenericPointer &a, GenericPointer &b) RAPIDJSON_NOEXCEPT
free-standing swap function helper
Definition pointer.h:232
Ch * nameBuffer_
A buffer containing all names in tokens.
Definition pointer.h:1103
Allocator * allocator_
The current allocator. It is either user-supplied or equal to ownAllocator_.
Definition pointer.h:1101
GenericPointer(const GenericPointer &rhs, Allocator *allocator)
Copy constructor.
Definition pointer.h:172
GenericPointer(const Ch *source, Allocator *allocator=0)
Constructor that parses a string or URI fragment representation.
Definition pointer.h:115
ValueType::EncodingType EncodingType
Encoding type from Value.
Definition pointer.h:82
GenericPointer(const Token *tokens, size_t tokenCount)
Constructor with user-supplied tokens.
Definition pointer.h:164
GenericPointer(Allocator *allocator=0)
Default constructor.
Definition pointer.h:108
size_t tokenCount_
Number of tokens in tokens_.
Definition pointer.h:1105
GenericPointer(const GenericPointer &rhs)
Copy constructor.
Definition pointer.h:167
PointerParseErrorCode parseErrorCode_
Parsing error code.
Definition pointer.h:1107
Token * tokens_
A list of tokens.
Definition pointer.h:1104
Allocator * ownAllocator_
Allocator owned by this Pointer.
Definition pointer.h:1102
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:138
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:263
GenericPointer Append(const Token &token, Allocator *allocator=0) const
Append a token and return a new Pointer.
Definition pointer.h:245
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.
ValueType::Ch Ch
Character type from Value.
Definition pointer.h:83
~GenericPointer()
Destructor.
Definition pointer.h:177
size_t parseErrorOffset_
Offset in code unit when parsing fail.
Definition pointer.h:1106
GenericPointer & operator=(const GenericPointer &rhs)
Assignment operator.
Definition pointer.h:184
GenericPointer & Swap(GenericPointer &other) RAPIDJSON_NOEXCEPT
Swap the content of this pointer with an other.
Definition pointer.h:209
Represents a JSON value. Use Value for UTF8 encoding and default allocator.
Definition document.h:609
Concept for allocating, resizing and freeing memory block.
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition rapidjson.h:407
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition rapidjson.h:122
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition rapidjson.h:125
PointerParseErrorCode
Error code of parsing.
Definition pointer.h:38
@ kPointerParseErrorInvalidEscape
Invalid escape.
Definition pointer.h:42
@ kPointerParseErrorTokenMustBeginWithSolidus
A token must begin with a '/'.
Definition pointer.h:41
@ kPointerParseErrorNone
The parse is successful.
Definition pointer.h:39
@ kPointerParseErrorCharacterMustPercentEncode
A character must percent encoded in URI fragment.
Definition pointer.h:44
@ kPointerParseErrorInvalidPercentEncoding
Invalid percent encoding in URI fragment.
Definition pointer.h:43
Integer len(const char *s)
Retourne la longueur de la chaîne s.
bool operator<(const Item &item1, const Item &item2)
Compare deux entités.
Definition Item.h:533
@ kObjectType
object
Definition rapidjson.h:669
@ kArrayType
array
Definition rapidjson.h:670
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition rapidjson.h:652
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition rapidjson.h:385
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition rapidjson.h:648
A read-write string stream.
Definition stream.h:189
A token is the basic units of internal representation.
Definition pointer.h:98
SizeType index
A valid array index, if it is not equal to kPointerInvalidIndex.
Definition pointer.h:101
SizeType length
Length of the name.
Definition pointer.h:100
const Ch * name
Name of the token. It has null character at the end but it can contain null character.
Definition pointer.h:99
Reference to a constant string (not taking a copy)
Definition document.h:287
Read-only string stream.
Definition stream.h:155
Encoding conversion.
Definition encodings.h:659
UTF-8 encoding.
Definition encodings.h:97