|
@@ -6,6 +6,7 @@
|
|
|
#include <unordered_map>
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
#include <jvalidate/detail/anchor.h>
|
|
#include <jvalidate/detail/anchor.h>
|
|
|
|
|
+#include <jvalidate/detail/context_stack.h>
|
|
|
#include <jvalidate/detail/on_block_exit.h>
|
|
#include <jvalidate/detail/on_block_exit.h>
|
|
|
#include <jvalidate/detail/out.h>
|
|
#include <jvalidate/detail/out.h>
|
|
|
#include <jvalidate/detail/parser_context.h>
|
|
#include <jvalidate/detail/parser_context.h>
|
|
@@ -28,7 +29,7 @@ private:
|
|
|
|
|
|
|
|
std::map<detail::RootReference, A> roots_;
|
|
std::map<detail::RootReference, A> roots_;
|
|
|
|
|
|
|
|
- std::map<detail::Anchor, detail::Reference> active_dynamic_anchors_;
|
|
|
|
|
|
|
+ detail::ContextStack<detail::Anchor, detail::Reference> active_dynamic_anchors_;
|
|
|
std::map<URI, std::map<detail::Anchor, detail::Reference>> dynamic_anchors_;
|
|
std::map<URI, std::map<detail::Anchor, detail::Reference>> dynamic_anchors_;
|
|
|
|
|
|
|
|
public:
|
|
public:
|
|
@@ -38,36 +39,20 @@ public:
|
|
|
prime(root, {}, version, keywords);
|
|
prime(root, {}, version, keywords);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- detail::OnBlockExit suppress(detail::Anchor const & anchor) {
|
|
|
|
|
- if (auto it = active_dynamic_anchors_.find(anchor); it != active_dynamic_anchors_.end()) {
|
|
|
|
|
- detail::Reference where = it->second;
|
|
|
|
|
- active_dynamic_anchors_.erase(it);
|
|
|
|
|
- return [this, anchor, where]() { active_dynamic_anchors_[anchor] = where; };
|
|
|
|
|
- }
|
|
|
|
|
- return nullptr;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- auto scoped_activate(detail::Reference ref) {
|
|
|
|
|
- URI const uri = references_.relative_to_nearest_anchor(ref).uri();
|
|
|
|
|
- activate_dynamic(uri);
|
|
|
|
|
- return [this, uri]() { deactivate_dynamic(uri); };
|
|
|
|
|
|
|
+ auto dynamic_scope(detail::Reference const & ref) {
|
|
|
|
|
+ URI const uri =
|
|
|
|
|
+ ref.pointer().empty() ? ref.uri() : references_.relative_to_nearest_anchor(ref).uri();
|
|
|
|
|
+ return active_dynamic_anchors_.scope(dynamic_anchors_[uri]);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- auto load(detail::Reference const & ref, detail::ParserContext<A> const & context)
|
|
|
|
|
- -> std::pair<std::optional<A>, detail::OnBlockExit> {
|
|
|
|
|
- auto scoped_schema = [this, &ref](A const & schema) {
|
|
|
|
|
- activate_dynamic(ref.uri());
|
|
|
|
|
- return std::make_pair(ref.pointer().walk(schema),
|
|
|
|
|
- [this, uri = ref.uri()] { deactivate_dynamic(uri); });
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
|
|
+ std::optional<A> load(detail::Reference const & ref, detail::ParserContext<A> const & context) {
|
|
|
if (auto it = roots_.find(ref.root()); it != roots_.end()) {
|
|
if (auto it = roots_.find(ref.root()); it != roots_.end()) {
|
|
|
- return scoped_schema(it->second);
|
|
|
|
|
|
|
+ return ref.pointer().walk(it->second);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
std::optional<A> external = external_.try_load(ref.uri());
|
|
std::optional<A> external = external_.try_load(ref.uri());
|
|
|
if (not external) {
|
|
if (not external) {
|
|
|
- return std::make_pair(std::nullopt, nullptr);
|
|
|
|
|
|
|
+ return std::nullopt;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// TODO(samjaffe): Change Versions if needed...
|
|
// TODO(samjaffe): Change Versions if needed...
|
|
@@ -76,18 +61,18 @@ public:
|
|
|
|
|
|
|
|
// May have a sub-id that we map to
|
|
// May have a sub-id that we map to
|
|
|
if (auto it = roots_.find(ref.root()); it != roots_.end()) {
|
|
if (auto it = roots_.find(ref.root()); it != roots_.end()) {
|
|
|
- return scoped_schema(it->second);
|
|
|
|
|
|
|
+ return ref.pointer().walk(it->second);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Will get called if the external schema does not declare a root document id?
|
|
// Will get called if the external schema does not declare a root document id?
|
|
|
- return scoped_schema(*external);
|
|
|
|
|
|
|
+ return ref.pointer().walk(*external);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
detail::Reference canonicalize(detail::Reference const & ref, detail::Reference const & parent,
|
|
detail::Reference canonicalize(detail::Reference const & ref, detail::Reference const & parent,
|
|
|
detail::inout<bool> dynamic_reference) const {
|
|
detail::inout<bool> dynamic_reference) const {
|
|
|
- if (auto it = active_dynamic_anchors_.find(ref.anchor()); it != active_dynamic_anchors_.end()) {
|
|
|
|
|
|
|
+ if (std::optional dynamic = active_dynamic_anchors_.lookup(ref.anchor())) {
|
|
|
if (dynamic_reference) {
|
|
if (dynamic_reference) {
|
|
|
- return it->second;
|
|
|
|
|
|
|
+ return *dynamic;
|
|
|
}
|
|
}
|
|
|
dynamic_reference = ref.uri().empty() && ref.pointer().empty();
|
|
dynamic_reference = ref.uri().empty() && ref.pointer().empty();
|
|
|
}
|
|
}
|
|
@@ -133,21 +118,6 @@ public:
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
private:
|
|
|
- void activate_dynamic(URI const & uri) {
|
|
|
|
|
- active_dynamic_anchors_.insert(dynamic_anchors_[uri].begin(), dynamic_anchors_[uri].end());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void deactivate_dynamic(URI const & uri) {
|
|
|
|
|
- std::map<detail::Anchor, detail::Reference> const & candidates = dynamic_anchors_[uri];
|
|
|
|
|
- for (auto it = active_dynamic_anchors_.begin(); it != active_dynamic_anchors_.end();) {
|
|
|
|
|
- if (auto cit = candidates.find(it->first); it->second == cit->second) {
|
|
|
|
|
- it = active_dynamic_anchors_.erase(it);
|
|
|
|
|
- } else {
|
|
|
|
|
- ++it;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
void prime(Adapter auto const & json, detail::Reference where, schema::Version version,
|
|
void prime(Adapter auto const & json, detail::Reference where, schema::Version version,
|
|
|
Keywords const & keywords) {
|
|
Keywords const & keywords) {
|
|
|
if (json.type() != adapter::Type::Object) {
|
|
if (json.type() != adapter::Type::Object) {
|