File indexing completed on 2025-02-21 10:13:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef RAPIDJSON_POINTER_H_
0016 #define RAPIDJSON_POINTER_H_
0017
0018 #include "document.h"
0019 #include "uri.h"
0020 #include "internal/itoa.h"
0021 #include "error/error.h" // PointerParseErrorCode
0022
0023 #ifdef __clang__
0024 RAPIDJSON_DIAG_PUSH
0025 RAPIDJSON_DIAG_OFF(switch-enum)
0026 #elif defined(_MSC_VER)
0027 RAPIDJSON_DIAG_PUSH
0028 RAPIDJSON_DIAG_OFF(4512)
0029 #endif
0030
0031 RAPIDJSON_NAMESPACE_BEGIN
0032
0033 static const SizeType kPointerInvalidIndex = ~SizeType(0);
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 template <typename ValueType, typename Allocator = CrtAllocator>
0068 class GenericPointer {
0069 public:
0070 typedef typename ValueType::EncodingType EncodingType;
0071 typedef typename ValueType::Ch Ch;
0072 typedef GenericUri<ValueType, Allocator> UriType;
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088 struct Token {
0089 const Ch* name;
0090 SizeType length;
0091 SizeType index;
0092 };
0093
0094
0095
0096
0097
0098 GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
0099
0100
0101
0102
0103
0104
0105 explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
0106 Parse(source, internal::StrLen(source));
0107 }
0108
0109 #if RAPIDJSON_HAS_STDSTRING
0110
0111
0112
0113
0114
0115
0116 explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
0117 Parse(source.c_str(), source.size());
0118 }
0119 #endif
0120
0121
0122
0123
0124
0125
0126
0127
0128 GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
0129 Parse(source, length);
0130 }
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
0155
0156
0157 GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
0158 *this = rhs;
0159 }
0160
0161
0162 GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
0163 *this = rhs;
0164 }
0165
0166
0167 ~GenericPointer() {
0168 if (nameBuffer_)
0169 Allocator::Free(tokens_);
0170 RAPIDJSON_DELETE(ownAllocator_);
0171 }
0172
0173
0174 GenericPointer& operator=(const GenericPointer& rhs) {
0175 if (this != &rhs) {
0176
0177 if (nameBuffer_)
0178 Allocator::Free(tokens_);
0179
0180 tokenCount_ = rhs.tokenCount_;
0181 parseErrorOffset_ = rhs.parseErrorOffset_;
0182 parseErrorCode_ = rhs.parseErrorCode_;
0183
0184 if (rhs.nameBuffer_)
0185 CopyFromRaw(rhs);
0186 else {
0187 tokens_ = rhs.tokens_;
0188 nameBuffer_ = 0;
0189 }
0190 }
0191 return *this;
0192 }
0193
0194
0195
0196
0197
0198
0199 GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT {
0200 internal::Swap(allocator_, other.allocator_);
0201 internal::Swap(ownAllocator_, other.ownAllocator_);
0202 internal::Swap(nameBuffer_, other.nameBuffer_);
0203 internal::Swap(tokens_, other.tokens_);
0204 internal::Swap(tokenCount_, other.tokenCount_);
0205 internal::Swap(parseErrorOffset_, other.parseErrorOffset_);
0206 internal::Swap(parseErrorCode_, other.parseErrorCode_);
0207 return *this;
0208 }
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222 friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235 GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
0236 GenericPointer r;
0237 r.allocator_ = allocator;
0238 Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
0239 std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
0240 r.tokens_[tokenCount_].name = p;
0241 r.tokens_[tokenCount_].length = token.length;
0242 r.tokens_[tokenCount_].index = token.index;
0243 return r;
0244 }
0245
0246
0247
0248
0249
0250
0251
0252
0253 GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
0254 Token token = { name, length, kPointerInvalidIndex };
0255 return Append(token, allocator);
0256 }
0257
0258
0259
0260
0261
0262
0263
0264 template <typename T>
0265 RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
0266 Append(T* name, Allocator* allocator = 0) const {
0267 return Append(name, internal::StrLen(name), allocator);
0268 }
0269
0270 #if RAPIDJSON_HAS_STDSTRING
0271
0272
0273
0274
0275
0276
0277 GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
0278 return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
0279 }
0280 #endif
0281
0282
0283
0284
0285
0286
0287
0288 GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
0289 char buffer[21];
0290 char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
0291 SizeType length = static_cast<SizeType>(end - buffer);
0292 buffer[length] = '\0';
0293
0294 if (sizeof(Ch) == 1) {
0295 Token token = { reinterpret_cast<Ch*>(buffer), length, index };
0296 return Append(token, allocator);
0297 }
0298 else {
0299 Ch name[21];
0300 for (size_t i = 0; i <= length; i++)
0301 name[i] = static_cast<Ch>(buffer[i]);
0302 Token token = { name, length, index };
0303 return Append(token, allocator);
0304 }
0305 }
0306
0307
0308
0309
0310
0311
0312
0313 GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
0314 if (token.IsString())
0315 return Append(token.GetString(), token.GetStringLength(), allocator);
0316 else {
0317 RAPIDJSON_ASSERT(token.IsUint64());
0318 RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
0319 return Append(static_cast<SizeType>(token.GetUint64()), allocator);
0320 }
0321 }
0322
0323
0324
0325
0326
0327 bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
0328
0329
0330 size_t GetParseErrorOffset() const { return parseErrorOffset_; }
0331
0332
0333 PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
0334
0335
0336
0337
0338 Allocator& GetAllocator() { return *allocator_; }
0339
0340
0341
0342
0343
0344 const Token* GetTokens() const { return tokens_; }
0345
0346
0347 size_t GetTokenCount() const { return tokenCount_; }
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358 bool operator==(const GenericPointer& rhs) const {
0359 if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
0360 return false;
0361
0362 for (size_t i = 0; i < tokenCount_; i++) {
0363 if (tokens_[i].index != rhs.tokens_[i].index ||
0364 tokens_[i].length != rhs.tokens_[i].length ||
0365 (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
0366 {
0367 return false;
0368 }
0369 }
0370
0371 return true;
0372 }
0373
0374
0375
0376
0377
0378 bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
0379
0380
0381
0382
0383
0384 bool operator<(const GenericPointer& rhs) const {
0385 if (!IsValid())
0386 return false;
0387 if (!rhs.IsValid())
0388 return true;
0389
0390 if (tokenCount_ != rhs.tokenCount_)
0391 return tokenCount_ < rhs.tokenCount_;
0392
0393 for (size_t i = 0; i < tokenCount_; i++) {
0394 if (tokens_[i].index != rhs.tokens_[i].index)
0395 return tokens_[i].index < rhs.tokens_[i].index;
0396
0397 if (tokens_[i].length != rhs.tokens_[i].length)
0398 return tokens_[i].length < rhs.tokens_[i].length;
0399
0400 if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length))
0401 return cmp < 0;
0402 }
0403
0404 return false;
0405 }
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417 template<typename OutputStream>
0418 bool Stringify(OutputStream& os) const {
0419 return Stringify<false, OutputStream>(os);
0420 }
0421
0422
0423
0424
0425
0426
0427 template<typename OutputStream>
0428 bool StringifyUriFragment(OutputStream& os) const {
0429 return Stringify<true, OutputStream>(os);
0430 }
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452 ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
0453 RAPIDJSON_ASSERT(IsValid());
0454 ValueType* v = &root;
0455 bool exist = true;
0456 for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
0457 if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
0458 v->PushBack(ValueType().Move(), allocator);
0459 v = &((*v)[v->Size() - 1]);
0460 exist = false;
0461 }
0462 else {
0463 if (t->index == kPointerInvalidIndex) {
0464 if (!v->IsObject())
0465 v->SetObject();
0466 }
0467 else {
0468 if (!v->IsArray() && !v->IsObject())
0469 v->SetArray();
0470 }
0471
0472 if (v->IsArray()) {
0473 if (t->index >= v->Size()) {
0474 v->Reserve(t->index + 1, allocator);
0475 while (t->index >= v->Size())
0476 v->PushBack(ValueType().Move(), allocator);
0477 exist = false;
0478 }
0479 v = &((*v)[t->index]);
0480 }
0481 else {
0482 typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
0483 if (m == v->MemberEnd()) {
0484 v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
0485 m = v->MemberEnd();
0486 v = &(--m)->value;
0487 exist = false;
0488 }
0489 else
0490 v = &m->value;
0491 }
0492 }
0493 }
0494
0495 if (alreadyExist)
0496 *alreadyExist = exist;
0497
0498 return *v;
0499 }
0500
0501
0502
0503
0504
0505
0506
0507 template <typename stackAllocator>
0508 ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
0509 return Create(document, document.GetAllocator(), alreadyExist);
0510 }
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534 UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
0535 static const Ch kIdString[] = { 'i', 'd', '\0' };
0536 static const ValueType kIdValue(kIdString, 2);
0537 UriType base = UriType(rootUri, allocator);
0538 RAPIDJSON_ASSERT(IsValid());
0539 ValueType* v = &root;
0540 for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
0541 switch (v->GetType()) {
0542 case kObjectType:
0543 {
0544
0545 typename ValueType::MemberIterator m = v->FindMember(kIdValue);
0546 if (m != v->MemberEnd() && (m->value).IsString()) {
0547 UriType here = UriType(m->value, allocator).Resolve(base, allocator);
0548 base = here;
0549 }
0550 m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
0551 if (m == v->MemberEnd())
0552 break;
0553 v = &m->value;
0554 }
0555 continue;
0556 case kArrayType:
0557 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
0558 break;
0559 v = &((*v)[t->index]);
0560 continue;
0561 default:
0562 break;
0563 }
0564
0565
0566 if (unresolvedTokenIndex)
0567 *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
0568 return UriType(allocator);
0569 }
0570 return base;
0571 }
0572
0573 UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
0574 return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex, allocator);
0575 }
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595 ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
0596 RAPIDJSON_ASSERT(IsValid());
0597 ValueType* v = &root;
0598 for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
0599 switch (v->GetType()) {
0600 case kObjectType:
0601 {
0602 typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
0603 if (m == v->MemberEnd())
0604 break;
0605 v = &m->value;
0606 }
0607 continue;
0608 case kArrayType:
0609 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
0610 break;
0611 v = &((*v)[t->index]);
0612 continue;
0613 default:
0614 break;
0615 }
0616
0617
0618 if (unresolvedTokenIndex)
0619 *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
0620 return 0;
0621 }
0622 return v;
0623 }
0624
0625
0626
0627
0628
0629
0630 const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
0631 return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
0632 }
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649 ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
0650 bool alreadyExist;
0651 ValueType& v = Create(root, allocator, &alreadyExist);
0652 return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
0653 }
0654
0655
0656 ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
0657 bool alreadyExist;
0658 ValueType& v = Create(root, allocator, &alreadyExist);
0659 return alreadyExist ? v : v.SetString(defaultValue, allocator);
0660 }
0661
0662 #if RAPIDJSON_HAS_STDSTRING
0663
0664 ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
0665 bool alreadyExist;
0666 ValueType& v = Create(root, allocator, &alreadyExist);
0667 return alreadyExist ? v : v.SetString(defaultValue, allocator);
0668 }
0669 #endif
0670
0671
0672
0673
0674
0675 template <typename T>
0676 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
0677 GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
0678 return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
0679 }
0680
0681
0682 template <typename stackAllocator>
0683 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const {
0684 return GetWithDefault(document, defaultValue, document.GetAllocator());
0685 }
0686
0687
0688 template <typename stackAllocator>
0689 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
0690 return GetWithDefault(document, defaultValue, document.GetAllocator());
0691 }
0692
0693 #if RAPIDJSON_HAS_STDSTRING
0694
0695 template <typename stackAllocator>
0696 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
0697 return GetWithDefault(document, defaultValue, document.GetAllocator());
0698 }
0699 #endif
0700
0701
0702
0703
0704
0705 template <typename T, typename stackAllocator>
0706 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
0707 GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
0708 return GetWithDefault(document, defaultValue, document.GetAllocator());
0709 }
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726 ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
0727 return Create(root, allocator) = value;
0728 }
0729
0730
0731 ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
0732 return Create(root, allocator).CopyFrom(value, allocator);
0733 }
0734
0735
0736 ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
0737 return Create(root, allocator) = ValueType(value, allocator).Move();
0738 }
0739
0740 #if RAPIDJSON_HAS_STDSTRING
0741
0742 ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
0743 return Create(root, allocator) = ValueType(value, allocator).Move();
0744 }
0745 #endif
0746
0747
0748
0749
0750
0751 template <typename T>
0752 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
0753 Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
0754 return Create(root, allocator) = ValueType(value).Move();
0755 }
0756
0757
0758 template <typename stackAllocator>
0759 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
0760 return Create(document) = value;
0761 }
0762
0763
0764 template <typename stackAllocator>
0765 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {
0766 return Create(document).CopyFrom(value, document.GetAllocator());
0767 }
0768
0769
0770 template <typename stackAllocator>
0771 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const {
0772 return Create(document) = ValueType(value, document.GetAllocator()).Move();
0773 }
0774
0775 #if RAPIDJSON_HAS_STDSTRING
0776
0777 template <typename stackAllocator>
0778 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
0779 return Create(document) = ValueType(value, document.GetAllocator()).Move();
0780 }
0781 #endif
0782
0783
0784
0785
0786
0787 template <typename T, typename stackAllocator>
0788 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
0789 Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
0790 return Create(document) = value;
0791 }
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802
0803
0804
0805
0806
0807
0808 ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
0809 return Create(root, allocator).Swap(value);
0810 }
0811
0812
0813 template <typename stackAllocator>
0814 ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
0815 return Create(document).Swap(value);
0816 }
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827 bool Erase(ValueType& root) const {
0828 RAPIDJSON_ASSERT(IsValid());
0829 if (tokenCount_ == 0)
0830 return false;
0831
0832 ValueType* v = &root;
0833 const Token* last = tokens_ + (tokenCount_ - 1);
0834 for (const Token *t = tokens_; t != last; ++t) {
0835 switch (v->GetType()) {
0836 case kObjectType:
0837 {
0838 typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
0839 if (m == v->MemberEnd())
0840 return false;
0841 v = &m->value;
0842 }
0843 break;
0844 case kArrayType:
0845 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
0846 return false;
0847 v = &((*v)[t->index]);
0848 break;
0849 default:
0850 return false;
0851 }
0852 }
0853
0854 switch (v->GetType()) {
0855 case kObjectType:
0856 return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
0857 case kArrayType:
0858 if (last->index == kPointerInvalidIndex || last->index >= v->Size())
0859 return false;
0860 v->Erase(v->Begin() + last->index);
0861 return true;
0862 default:
0863 return false;
0864 }
0865 }
0866
0867 private:
0868
0869
0870
0871
0872
0873
0874
0875 Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
0876 if (!allocator_)
0877 ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
0878
0879 size_t nameBufferSize = rhs.tokenCount_;
0880 for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
0881 nameBufferSize += t->length;
0882
0883 tokenCount_ = rhs.tokenCount_ + extraToken;
0884 tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
0885 nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
0886 if (rhs.tokenCount_ > 0) {
0887 std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
0888 }
0889 if (nameBufferSize > 0) {
0890 std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
0891 }
0892
0893
0894
0895
0896 for (size_t i = 0; i < rhs.tokenCount_; ++i) {
0897
0898
0899
0900 std::ptrdiff_t name_offset = rhs.tokens_[i].name - rhs.nameBuffer_;
0901 tokens_[i].name = nameBuffer_ + name_offset;
0902 }
0903
0904 return nameBuffer_ + nameBufferSize;
0905 }
0906
0907
0908
0909
0910
0911
0912 bool NeedPercentEncode(Ch c) const {
0913 return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
0914 }
0915
0916
0917 #ifndef __clang__
0918
0919
0920
0921
0922
0923 #endif
0924 void Parse(const Ch* source, size_t length) {
0925 RAPIDJSON_ASSERT(source != NULL);
0926 RAPIDJSON_ASSERT(nameBuffer_ == 0);
0927 RAPIDJSON_ASSERT(tokens_ == 0);
0928
0929
0930 if (!allocator_)
0931 ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
0932
0933
0934 tokenCount_ = 0;
0935 for (const Ch* s = source; s != source + length; s++)
0936 if (*s == '/')
0937 tokenCount_++;
0938
0939 Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
0940 Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
0941 size_t i = 0;
0942
0943
0944 bool uriFragment = false;
0945 if (source[i] == '#') {
0946 uriFragment = true;
0947 i++;
0948 }
0949
0950 if (i != length && source[i] != '/') {
0951 parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus;
0952 goto error;
0953 }
0954
0955 while (i < length) {
0956 RAPIDJSON_ASSERT(source[i] == '/');
0957 i++;
0958
0959 token->name = name;
0960 bool isNumber = true;
0961
0962 while (i < length && source[i] != '/') {
0963 Ch c = source[i];
0964 if (uriFragment) {
0965
0966 if (c == '%') {
0967 PercentDecodeStream is(&source[i], source + length);
0968 GenericInsituStringStream<EncodingType> os(name);
0969 Ch* begin = os.PutBegin();
0970 if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
0971 parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding;
0972 goto error;
0973 }
0974 size_t len = os.PutEnd(begin);
0975 i += is.Tell() - 1;
0976 if (len == 1)
0977 c = *name;
0978 else {
0979 name += len;
0980 isNumber = false;
0981 i++;
0982 continue;
0983 }
0984 }
0985 else if (NeedPercentEncode(c)) {
0986 parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode;
0987 goto error;
0988 }
0989 }
0990
0991 i++;
0992
0993
0994 if (c == '~') {
0995 if (i < length) {
0996 c = source[i];
0997 if (c == '0') c = '~';
0998 else if (c == '1') c = '/';
0999 else {
1000 parseErrorCode_ = kPointerParseErrorInvalidEscape;
1001 goto error;
1002 }
1003 i++;
1004 }
1005 else {
1006 parseErrorCode_ = kPointerParseErrorInvalidEscape;
1007 goto error;
1008 }
1009 }
1010
1011
1012 if (c < '0' || c > '9')
1013 isNumber = false;
1014
1015 *name++ = c;
1016 }
1017 token->length = static_cast<SizeType>(name - token->name);
1018 if (token->length == 0)
1019 isNumber = false;
1020 *name++ = '\0';
1021
1022
1023 if (isNumber && token->length > 1 && token->name[0] == '0')
1024 isNumber = false;
1025
1026
1027 SizeType n = 0;
1028 if (isNumber) {
1029 for (size_t j = 0; j < token->length; j++) {
1030 SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
1031 if (m < n) {
1032 isNumber = false;
1033 break;
1034 }
1035 n = m;
1036 }
1037 }
1038
1039 token->index = isNumber ? n : kPointerInvalidIndex;
1040 token++;
1041 }
1042
1043 RAPIDJSON_ASSERT(name <= nameBuffer_ + length);
1044 parseErrorCode_ = kPointerParseErrorNone;
1045 return;
1046
1047 error:
1048 Allocator::Free(tokens_);
1049 nameBuffer_ = 0;
1050 tokens_ = 0;
1051 tokenCount_ = 0;
1052 parseErrorOffset_ = i;
1053 return;
1054 }
1055
1056
1057
1058
1059
1060
1061
1062 template<bool uriFragment, typename OutputStream>
1063 bool Stringify(OutputStream& os) const {
1064 RAPIDJSON_ASSERT(IsValid());
1065
1066 if (uriFragment)
1067 os.Put('#');
1068
1069 for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
1070 os.Put('/');
1071 for (size_t j = 0; j < t->length; j++) {
1072 Ch c = t->name[j];
1073 if (c == '~') {
1074 os.Put('~');
1075 os.Put('0');
1076 }
1077 else if (c == '/') {
1078 os.Put('~');
1079 os.Put('1');
1080 }
1081 else if (uriFragment && NeedPercentEncode(c)) {
1082
1083 GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
1084 PercentEncodeStream<OutputStream> target(os);
1085 if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
1086 return false;
1087 j += source.Tell() - 1;
1088 }
1089 else
1090 os.Put(c);
1091 }
1092 }
1093 return true;
1094 }
1095
1096
1097
1098
1099
1100
1101
1102 class PercentDecodeStream {
1103 public:
1104 typedef typename ValueType::Ch Ch;
1105
1106
1107
1108
1109
1110
1111 PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
1112
1113 Ch Take() {
1114 if (*src_ != '%' || src_ + 3 > end_) {
1115 valid_ = false;
1116 return 0;
1117 }
1118 src_++;
1119 Ch c = 0;
1120 for (int j = 0; j < 2; j++) {
1121 c = static_cast<Ch>(c << 4);
1122 Ch h = *src_;
1123 if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
1124 else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
1125 else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
1126 else {
1127 valid_ = false;
1128 return 0;
1129 }
1130 src_++;
1131 }
1132 return c;
1133 }
1134
1135 size_t Tell() const { return static_cast<size_t>(src_ - head_); }
1136 bool IsValid() const { return valid_; }
1137
1138 private:
1139 const Ch* src_;
1140 const Ch* head_;
1141 const Ch* end_;
1142 bool valid_;
1143 };
1144
1145
1146 template <typename OutputStream>
1147 class PercentEncodeStream {
1148 public:
1149 PercentEncodeStream(OutputStream& os) : os_(os) {}
1150 void Put(char c) {
1151 unsigned char u = static_cast<unsigned char>(c);
1152 static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1153 os_.Put('%');
1154 os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
1155 os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
1156 }
1157 private:
1158 OutputStream& os_;
1159 };
1160
1161 Allocator* allocator_;
1162 Allocator* ownAllocator_;
1163 Ch* nameBuffer_;
1164 Token* tokens_;
1165 size_t tokenCount_;
1166 size_t parseErrorOffset_;
1167 PointerParseErrorCode parseErrorCode_;
1168 };
1169
1170
1171 typedef GenericPointer<Value> Pointer;
1172
1173
1174
1175
1176
1177
1178 template <typename T>
1179 typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
1180 return pointer.Create(root, a);
1181 }
1182
1183 template <typename T, typename CharType, size_t N>
1184 typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
1185 return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
1186 }
1187
1188
1189
1190 template <typename DocumentType>
1191 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
1192 return pointer.Create(document);
1193 }
1194
1195 template <typename DocumentType, typename CharType, size_t N>
1196 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
1197 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
1198 }
1199
1200
1201
1202 template <typename T>
1203 typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1204 return pointer.Get(root, unresolvedTokenIndex);
1205 }
1206
1207 template <typename T>
1208 const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1209 return pointer.Get(root, unresolvedTokenIndex);
1210 }
1211
1212 template <typename T, typename CharType, size_t N>
1213 typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
1214 return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1215 }
1216
1217 template <typename T, typename CharType, size_t N>
1218 const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
1219 return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1220 }
1221
1222
1223
1224 template <typename T>
1225 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1226 return pointer.GetWithDefault(root, defaultValue, a);
1227 }
1228
1229 template <typename T>
1230 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1231 return pointer.GetWithDefault(root, defaultValue, a);
1232 }
1233
1234 #if RAPIDJSON_HAS_STDSTRING
1235 template <typename T>
1236 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1237 return pointer.GetWithDefault(root, defaultValue, a);
1238 }
1239 #endif
1240
1241 template <typename T, typename T2>
1242 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1243 GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
1244 return pointer.GetWithDefault(root, defaultValue, a);
1245 }
1246
1247 template <typename T, typename CharType, size_t N>
1248 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1249 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1250 }
1251
1252 template <typename T, typename CharType, size_t N>
1253 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1254 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1255 }
1256
1257 #if RAPIDJSON_HAS_STDSTRING
1258 template <typename T, typename CharType, size_t N>
1259 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1260 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1261 }
1262 #endif
1263
1264 template <typename T, typename CharType, size_t N, typename T2>
1265 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1266 GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
1267 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1268 }
1269
1270
1271
1272 template <typename DocumentType>
1273 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
1274 return pointer.GetWithDefault(document, defaultValue);
1275 }
1276
1277 template <typename DocumentType>
1278 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
1279 return pointer.GetWithDefault(document, defaultValue);
1280 }
1281
1282 #if RAPIDJSON_HAS_STDSTRING
1283 template <typename DocumentType>
1284 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1285 return pointer.GetWithDefault(document, defaultValue);
1286 }
1287 #endif
1288
1289 template <typename DocumentType, typename T2>
1290 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1291 GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
1292 return pointer.GetWithDefault(document, defaultValue);
1293 }
1294
1295 template <typename DocumentType, typename CharType, size_t N>
1296 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
1297 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1298 }
1299
1300 template <typename DocumentType, typename CharType, size_t N>
1301 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
1302 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1303 }
1304
1305 #if RAPIDJSON_HAS_STDSTRING
1306 template <typename DocumentType, typename CharType, size_t N>
1307 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1308 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1309 }
1310 #endif
1311
1312 template <typename DocumentType, typename CharType, size_t N, typename T2>
1313 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1314 GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
1315 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1316 }
1317
1318
1319
1320 template <typename T>
1321 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1322 return pointer.Set(root, value, a);
1323 }
1324
1325 template <typename T>
1326 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
1327 return pointer.Set(root, value, a);
1328 }
1329
1330 template <typename T>
1331 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
1332 return pointer.Set(root, value, a);
1333 }
1334
1335 #if RAPIDJSON_HAS_STDSTRING
1336 template <typename T>
1337 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1338 return pointer.Set(root, value, a);
1339 }
1340 #endif
1341
1342 template <typename T, typename T2>
1343 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1344 SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
1345 return pointer.Set(root, value, a);
1346 }
1347
1348 template <typename T, typename CharType, size_t N>
1349 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1350 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1351 }
1352
1353 template <typename T, typename CharType, size_t N>
1354 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
1355 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1356 }
1357
1358 template <typename T, typename CharType, size_t N>
1359 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
1360 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1361 }
1362
1363 #if RAPIDJSON_HAS_STDSTRING
1364 template <typename T, typename CharType, size_t N>
1365 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1366 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1367 }
1368 #endif
1369
1370 template <typename T, typename CharType, size_t N, typename T2>
1371 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1372 SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
1373 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1374 }
1375
1376
1377
1378 template <typename DocumentType>
1379 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1380 return pointer.Set(document, value);
1381 }
1382
1383 template <typename DocumentType>
1384 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
1385 return pointer.Set(document, value);
1386 }
1387
1388 template <typename DocumentType>
1389 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
1390 return pointer.Set(document, value);
1391 }
1392
1393 #if RAPIDJSON_HAS_STDSTRING
1394 template <typename DocumentType>
1395 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
1396 return pointer.Set(document, value);
1397 }
1398 #endif
1399
1400 template <typename DocumentType, typename T2>
1401 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1402 SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
1403 return pointer.Set(document, value);
1404 }
1405
1406 template <typename DocumentType, typename CharType, size_t N>
1407 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1408 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1409 }
1410
1411 template <typename DocumentType, typename CharType, size_t N>
1412 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
1413 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1414 }
1415
1416 template <typename DocumentType, typename CharType, size_t N>
1417 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
1418 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1419 }
1420
1421 #if RAPIDJSON_HAS_STDSTRING
1422 template <typename DocumentType, typename CharType, size_t N>
1423 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
1424 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1425 }
1426 #endif
1427
1428 template <typename DocumentType, typename CharType, size_t N, typename T2>
1429 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1430 SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
1431 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1432 }
1433
1434
1435
1436 template <typename T>
1437 typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1438 return pointer.Swap(root, value, a);
1439 }
1440
1441 template <typename T, typename CharType, size_t N>
1442 typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1443 return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
1444 }
1445
1446 template <typename DocumentType>
1447 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1448 return pointer.Swap(document, value);
1449 }
1450
1451 template <typename DocumentType, typename CharType, size_t N>
1452 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1453 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
1454 }
1455
1456
1457
1458 template <typename T>
1459 bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
1460 return pointer.Erase(root);
1461 }
1462
1463 template <typename T, typename CharType, size_t N>
1464 bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
1465 return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
1466 }
1467
1468
1469
1470 RAPIDJSON_NAMESPACE_END
1471
1472 #if defined(__clang__) || defined(_MSC_VER)
1473 RAPIDJSON_DIAG_POP
1474 #endif
1475
1476 #endif