|
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 | /*!
|
@@ -520,6 +523,69 @@ 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 unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. |
| 534 | + \return Uri if it can be resolved. Otherwise null. |
| 535 | +
|
| 536 | + \note |
| 537 | + There are only 3 situations when a URI cannot be resolved: |
| 538 | + 1. A value in the path is not an array nor object. |
| 539 | + 2. An object value does not contain the token. |
| 540 | + 3. A token is out of range of an array value. |
| 541 | +
|
| 542 | + Use unresolvedTokenIndex to retrieve the token index. |
| 543 | + */ |
| 544 | + UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0) const { |
| 545 | + static const Ch kIdString[] = { 'i', 'd', '\0' }; |
| 546 | + static const ValueType kIdValue(kIdString, 2); |
| 547 | + UriType base = rootUri; |
| 548 | + RAPIDJSON_ASSERT(IsValid()); |
| 549 | + ValueType* v = &root; |
| 550 | + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { |
| 551 | + switch (v->GetType()) { |
| 552 | + case kObjectType: |
| 553 | + { |
| 554 | + // See if we have an id, and if so resolve with the current base |
| 555 | + typename ValueType::MemberIterator m = v->FindMember(kIdValue); |
| 556 | + if (m != v->MemberEnd() && (m->value).IsString()) { |
| 557 | + UriType here = UriType(m->value); |
| 558 | + here.Resolve(base); |
| 559 | + base = here; |
| 560 | + } |
| 561 | + m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length))); |
| 562 | + if (m == v->MemberEnd()) |
| 563 | + break; |
| 564 | + v = &m->value; |
| 565 | + } |
| 566 | + continue; |
| 567 | + case kArrayType: |
| 568 | + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) |
| 569 | + break; |
| 570 | + v = &((*v)[t->index]); |
| 571 | + continue; |
| 572 | + default: |
| 573 | + break; |
| 574 | + } |
| 575 | + |
| 576 | + // Error: unresolved token |
| 577 | + if (unresolvedTokenIndex) |
| 578 | + *unresolvedTokenIndex = static_cast<size_t>(t - tokens_); |
| 579 | + return UriType(); |
| 580 | + } |
| 581 | + return base; |
| 582 | + } |
| 583 | + |
| 584 | + UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0) const { |
| 585 | + return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex); |
| 586 | + } |
| 587 | + |
| 588 | + |
523 | 589 | //!@name Query value
|
524 | 590 | //@{
|
525 | 591 |
|
|
0 commit comments