|
|
@@ -18,19 +18,19 @@
|
|
|
#include <jvalidate/forward.h>
|
|
|
#include <jvalidate/uri.h>
|
|
|
|
|
|
-namespace jvalidate {
|
|
|
+namespace jvalidate::detail {
|
|
|
template <Adapter A> class ReferenceManager {
|
|
|
public:
|
|
|
using Keywords = std::unordered_map<std::string_view, std::set<schema::Wraps>>;
|
|
|
|
|
|
private:
|
|
|
DocumentCache<A> & external_;
|
|
|
- detail::ReferenceCache references_;
|
|
|
+ ReferenceCache references_;
|
|
|
|
|
|
- std::map<detail::RootReference, A> roots_;
|
|
|
+ std::map<RootReference, A> roots_;
|
|
|
|
|
|
- detail::ContextStack<URI, detail::Anchor, detail::Reference> active_dynamic_anchors_;
|
|
|
- std::map<URI, std::map<detail::Anchor, detail::Reference>> dynamic_anchors_;
|
|
|
+ ContextStack<URI, Anchor, Reference> active_dynamic_anchors_;
|
|
|
+ std::map<URI, std::map<Anchor, Reference>> dynamic_anchors_;
|
|
|
|
|
|
public:
|
|
|
ReferenceManager(DocumentCache<A> & external, A const & root, schema::Version version,
|
|
|
@@ -39,13 +39,13 @@ public:
|
|
|
prime(root, {}, version, keywords);
|
|
|
}
|
|
|
|
|
|
- auto dynamic_scope(detail::Reference const & ref) {
|
|
|
+ auto dynamic_scope(Reference const & ref) {
|
|
|
URI const uri =
|
|
|
ref.pointer().empty() ? ref.uri() : references_.relative_to_nearest_anchor(ref).uri();
|
|
|
return active_dynamic_anchors_.scope(uri, dynamic_anchors_[uri]);
|
|
|
}
|
|
|
|
|
|
- std::optional<A> load(detail::Reference const & ref, detail::ParserContext<A> const & context) {
|
|
|
+ std::optional<A> load(Reference const & ref, ParserContext<A> const & context) {
|
|
|
if (auto it = roots_.find(ref.root()); it != roots_.end()) {
|
|
|
return ref.pointer().walk(it->second);
|
|
|
}
|
|
|
@@ -68,8 +68,8 @@ public:
|
|
|
return ref.pointer().walk(*external);
|
|
|
}
|
|
|
|
|
|
- detail::Reference canonicalize(detail::Reference const & ref, detail::Reference const & parent,
|
|
|
- detail::inout<bool> dynamic_reference) {
|
|
|
+ Reference canonicalize(Reference const & ref, Reference const & parent,
|
|
|
+ inout<bool> dynamic_reference) {
|
|
|
URI const uri = [this, &ref, &parent]() {
|
|
|
if (ref.uri().empty() && parent.uri().empty()) {
|
|
|
return references_.actual_parent_uri(parent);
|
|
|
@@ -96,10 +96,10 @@ public:
|
|
|
// TODO(samjaffe): Clean up this block too...
|
|
|
URI const dyn_uri = ref.uri().empty() ? ref.uri() : uri;
|
|
|
|
|
|
- detail::OnBlockExit scope;
|
|
|
+ OnBlockExit scope;
|
|
|
if (not ref.uri().empty() && dynamic_reference &&
|
|
|
active_dynamic_anchors_.contains(ref.anchor())) {
|
|
|
- scope = dynamic_scope(detail::Reference(dyn_uri));
|
|
|
+ scope = dynamic_scope(Reference(dyn_uri));
|
|
|
}
|
|
|
|
|
|
if (std::optional dynamic = active_dynamic_anchors_.lookup(dyn_uri, ref.anchor())) {
|
|
|
@@ -115,15 +115,14 @@ public:
|
|
|
|
|
|
// Relative URI, not in the HEREDOC (or we set an $id)
|
|
|
if (ref.uri().empty() and ref.anchor().empty()) {
|
|
|
- return detail::Reference(references_.relative_to_nearest_anchor(parent).root(),
|
|
|
- ref.pointer());
|
|
|
+ return Reference(references_.relative_to_nearest_anchor(parent).root(), ref.pointer());
|
|
|
}
|
|
|
|
|
|
- return detail::Reference(uri, ref.anchor(), ref.pointer());
|
|
|
+ return Reference(uri, ref.anchor(), ref.pointer());
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
- void prime(Adapter auto const & json, detail::Reference where, schema::Version version,
|
|
|
+ void prime(Adapter auto const & json, Reference where, schema::Version version,
|
|
|
Keywords const & keywords) {
|
|
|
if (json.type() != adapter::Type::Object) {
|
|
|
return;
|
|
|
@@ -154,21 +153,21 @@ private:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- void canonicalize(detail::Reference & where, schema::Version version, A const & json) {
|
|
|
+ void canonicalize(Reference & where, schema::Version version, A const & json) {
|
|
|
std::string const id = version <= schema::Version::Draft04 ? "id" : "$id";
|
|
|
auto const schema = json.as_object();
|
|
|
|
|
|
- detail::RootReference root = where.root();
|
|
|
+ RootReference root = where.root();
|
|
|
if (schema.contains(id)) {
|
|
|
- root = detail::RootReference(schema[id].as_string());
|
|
|
+ root = RootReference(schema[id].as_string());
|
|
|
if (root.uri().empty()) {
|
|
|
- root = detail::RootReference(where.uri(), root.anchor());
|
|
|
+ root = RootReference(where.uri(), root.anchor());
|
|
|
} else if (not root.uri().is_rootless() || where.uri().empty()) {
|
|
|
// By definition - rootless URIs cannot be relative
|
|
|
} else if (root.uri().is_relative()) {
|
|
|
- root = detail::RootReference(where.uri().parent() / root.uri(), root.anchor());
|
|
|
+ root = RootReference(where.uri().parent() / root.uri(), root.anchor());
|
|
|
} else {
|
|
|
- root = detail::RootReference(where.uri().root() / root.uri(), root.anchor());
|
|
|
+ root = RootReference(where.uri().root() / root.uri(), root.anchor());
|
|
|
}
|
|
|
|
|
|
roots_.emplace(root, json);
|
|
|
@@ -181,34 +180,34 @@ private:
|
|
|
}
|
|
|
|
|
|
if (schema.contains("$anchor")) {
|
|
|
- root = detail::RootReference(root.uri(), detail::Anchor(schema["$anchor"].as_string()));
|
|
|
+ root = RootReference(root.uri(), Anchor(schema["$anchor"].as_string()));
|
|
|
roots_.emplace(root, json);
|
|
|
where = references_.emplace(where, root);
|
|
|
}
|
|
|
|
|
|
if (version == schema::Version::Draft2019_09 && schema.contains("$recursiveAnchor") &&
|
|
|
schema["$recursiveAnchor"].as_boolean()) {
|
|
|
- detail::Anchor anchor;
|
|
|
- root = detail::RootReference(root.uri(), anchor);
|
|
|
+ Anchor anchor;
|
|
|
+ root = RootReference(root.uri(), anchor);
|
|
|
|
|
|
roots_.emplace(root, json);
|
|
|
where = references_.emplace(where, root);
|
|
|
|
|
|
- if (detail::Reference & dynamic = dynamic_anchors_[root.uri()][anchor];
|
|
|
- dynamic == detail::Reference() || where < dynamic) {
|
|
|
+ if (Reference & dynamic = dynamic_anchors_[root.uri()][anchor];
|
|
|
+ dynamic == Reference() || where < dynamic) {
|
|
|
dynamic = where;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (schema.contains("$dynamicAnchor") && version > schema::Version::Draft2019_09) {
|
|
|
- detail::Anchor anchor(schema["$dynamicAnchor"].as_string());
|
|
|
- root = detail::RootReference(root.uri(), anchor);
|
|
|
+ Anchor anchor(schema["$dynamicAnchor"].as_string());
|
|
|
+ root = RootReference(root.uri(), anchor);
|
|
|
|
|
|
roots_.emplace(root, json);
|
|
|
where = references_.emplace(where, root);
|
|
|
|
|
|
- if (detail::Reference & dynamic = dynamic_anchors_[root.uri()][anchor];
|
|
|
- dynamic == detail::Reference() || where < dynamic) {
|
|
|
+ if (Reference & dynamic = dynamic_anchors_[root.uri()][anchor];
|
|
|
+ dynamic == Reference() || where < dynamic) {
|
|
|
dynamic = where;
|
|
|
}
|
|
|
}
|