|
16 | 16 | #define RAPIDJSON_POINTER_H_
|
17 | 17 |
|
18 | 18 | #include "document.h"
|
| 19 | +#include "uri.h" |
19 | 20 | #include "internal/itoa.h"
|
20 | 21 |
|
21 | 22 | #ifdef __clang__
|
@@ -80,6 +81,8 @@ class GenericPointer {
|
80 | 81 | public:
|
81 | 82 | typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
|
82 | 83 | typedef typename ValueType::Ch Ch; //!< Character type from Value
|
| 84 | + typedef GenericUri<ValueType, Allocator> UriType; |
| 85 | + |
83 | 86 |
|
84 | 87 | //! A token is the basic units of internal representation.
|
85 | 88 | /*!
|
@@ -163,7 +166,7 @@ class GenericPointer {
|
163 | 166 | GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
|
164 | 167 |
|
165 | 168 | //! Copy constructor.
|
166 |
| - GenericPointer(const GenericPointer& rhs) : allocator_(rhs.allocator_), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { |
| 169 | + GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { |
167 | 170 | *this = rhs;
|
168 | 171 | }
|
169 | 172 |
|
@@ -520,6 +523,70 @@ class GenericPointer {
|
520 | 523 |
|
521 | 524 | //@}
|
522 | 525 |
|
| 526 | + //!@name Compute URI |
| 527 | + //@{ |
| 528 | + |
| 529 | + //! Compute the in-scope URI for a subtree. |
| 530 | + // For use with JSON pointers into JSON schema documents. |
| 531 | + /*! |
| 532 | + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. |
| 533 | + \param rootUri Root URI |
| 534 | + \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. |
| 535 | + \param allocator Allocator for Uris |
| 536 | + \return Uri if it can be resolved. Otherwise null. |
| 537 | +
|
| 538 | + \note |
| 539 | + There are only 3 situations when a URI cannot be resolved: |
| 540 | + 1. A value in the path is not an array nor object. |
| 541 | + 2. An object value does not contain the token. |
| 542 | + 3. A token is out of range of an array value. |
| 543 | +
|
| 544 | + Use unresolvedTokenIndex to retrieve the token index. |
| 545 | + */ |
| 546 | + UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const { |
| 547 | + static const Ch kIdString[] = { 'i', 'd', '\0' }; |
| 548 | + static const ValueType kIdValue(kIdString, 2); |
| 549 | + UriType base = UriType(rootUri, allocator); |
| 550 | + RAPIDJSON_ASSERT(IsValid()); |
| 551 | + ValueType* v = &root; |
| 552 | + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { |
| 553 | + switch (v->GetType()) { |
| 554 | + case kObjectType: |
| 555 | + { |
| 556 | + // See if we have an id, and if so resolve with the current base |
| 557 | + typename ValueType::MemberIterator m = v->FindMember(kIdValue); |
| 558 | + if (m != v->MemberEnd() && (m->value).IsString()) { |
| 559 | + UriType here = UriType(m->value, allocator).Resolve(base, allocator); |
| 560 | + base = here; |
| 561 | + } |
| 562 | + m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length))); |
| 563 | + if (m == v->MemberEnd()) |
| 564 | + break; |
| 565 | + v = &m->value; |
| 566 | + } |
| 567 | + continue; |
| 568 | + case kArrayType: |
| 569 | + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) |
| 570 | + break; |
| 571 | + v = &((*v)[t->index]); |
| 572 | + continue; |
| 573 | + default: |
| 574 | + break; |
| 575 | + } |
| 576 | + |
| 577 | + // Error: unresolved token |
| 578 | + if (unresolvedTokenIndex) |
| 579 | + *unresolvedTokenIndex = static_cast<size_t>(t - tokens_); |
| 580 | + return UriType(allocator); |
| 581 | + } |
| 582 | + return base; |
| 583 | + } |
| 584 | + |
| 585 | + UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const { |
| 586 | + return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex, allocator); |
| 587 | + } |
| 588 | + |
| 589 | + |
523 | 590 | //!@name Query value
|
524 | 591 | //@{
|
525 | 592 |
|
|
0 commit comments