|
@@ -70,7 +70,7 @@ public:
|
|
|
return Status::Accept;
|
|
return Status::Accept;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- add_error("type ", type, " is not one of {", cons.types, '}');
|
|
|
|
|
|
|
+ add_error("type ", type, " is not one of {", cons.types, "}");
|
|
|
return Status::Reject;
|
|
return Status::Reject;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -94,13 +94,20 @@ public:
|
|
|
Status visit(constraint::AllOfConstraint const & cons) const {
|
|
Status visit(constraint::AllOfConstraint const & cons) const {
|
|
|
Status rval = Status::Accept;
|
|
Status rval = Status::Accept;
|
|
|
|
|
|
|
|
|
|
+ std::set<size_t> unmatched;
|
|
|
size_t i = 0;
|
|
size_t i = 0;
|
|
|
for (schema::Node const * subschema : cons.children) {
|
|
for (schema::Node const * subschema : cons.children) {
|
|
|
- rval &= validate_subschema(subschema, i);
|
|
|
|
|
|
|
+ if (auto stat = validate_subschema(subschema, i); stat == Status::Reject) {
|
|
|
|
|
+ rval = Status::Reject;
|
|
|
|
|
+ unmatched.insert(i);
|
|
|
|
|
+ }
|
|
|
++i;
|
|
++i;
|
|
|
BREAK_EARLY_IF_NO_RESULT_TREE();
|
|
BREAK_EARLY_IF_NO_RESULT_TREE();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (rval == Status::Reject) {
|
|
|
|
|
+ add_error("does not validate subschemas ", unmatched);
|
|
|
|
|
+ }
|
|
|
return rval;
|
|
return rval;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -118,35 +125,51 @@ public:
|
|
|
++i;
|
|
++i;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (rval == Status::Reject) {
|
|
|
|
|
+ add_error("validates none of the subschemas");
|
|
|
|
|
+ }
|
|
|
return rval;
|
|
return rval;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Status visit(constraint::OneOfConstraint const & cons) const {
|
|
Status visit(constraint::OneOfConstraint const & cons) const {
|
|
|
- size_t matches = 0;
|
|
|
|
|
|
|
+ std::set<size_t> matches;
|
|
|
size_t i = 0;
|
|
size_t i = 0;
|
|
|
for (schema::Node const * subschema : cons.children) {
|
|
for (schema::Node const * subschema : cons.children) {
|
|
|
if (validate_subschema(subschema, i)) {
|
|
if (validate_subschema(subschema, i)) {
|
|
|
- ++matches;
|
|
|
|
|
|
|
+ matches.insert(i);
|
|
|
}
|
|
}
|
|
|
++i;
|
|
++i;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return matches == 1 ? Status::Accept : Status::Reject;
|
|
|
|
|
|
|
+ if (matches.size() == 1) {
|
|
|
|
|
+ return Status::Accept;
|
|
|
|
|
+ }
|
|
|
|
|
+ add_error("validates subschemas ", matches);
|
|
|
|
|
+ return Status::Reject;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Status visit(constraint::NotConstraint const & cons) const {
|
|
Status visit(constraint::NotConstraint const & cons) const {
|
|
|
VisitedAnnotation * suppress = nullptr;
|
|
VisitedAnnotation * suppress = nullptr;
|
|
|
std::swap(suppress, visited_);
|
|
std::swap(suppress, visited_);
|
|
|
- auto rval = validate_subschema(cons.child, detail::Pointer()) == Status::Reject;
|
|
|
|
|
|
|
+ bool const rval = validate_subschema(cons.child) == Status::Reject;
|
|
|
std::swap(suppress, visited_);
|
|
std::swap(suppress, visited_);
|
|
|
|
|
+
|
|
|
|
|
+ if (not rval) {
|
|
|
|
|
+ add_error("actually validates subschema");
|
|
|
|
|
+ }
|
|
|
return rval;
|
|
return rval;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Status visit(constraint::ConditionalConstraint const & cons) const {
|
|
Status visit(constraint::ConditionalConstraint const & cons) const {
|
|
|
- if (validate_subschema(cons.if_constraint, detail::Pointer())) {
|
|
|
|
|
- return validate_subschema(cons.then_constraint, "then");
|
|
|
|
|
|
|
+ VisitedAnnotation * suppress = nullptr;
|
|
|
|
|
+ std::swap(suppress, visited_);
|
|
|
|
|
+ bool const if_result = validate_subschema(cons.if_constraint);
|
|
|
|
|
+ std::swap(suppress, visited_);
|
|
|
|
|
+
|
|
|
|
|
+ if (if_result) {
|
|
|
|
|
+ return validate_subschema(cons.then_constraint, detail::parent, "then");
|
|
|
}
|
|
}
|
|
|
- return validate_subschema(cons.else_constraint, "else");
|
|
|
|
|
|
|
+ return validate_subschema(cons.else_constraint, detail::parent, "else");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Status visit(constraint::MaximumConstraint const & cons) const {
|
|
Status visit(constraint::MaximumConstraint const & cons) const {
|
|
@@ -239,8 +262,7 @@ public:
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- std::cerr << "Unimplemented constraint format(" << cons.format << ")"
|
|
|
|
|
- << "\n";
|
|
|
|
|
|
|
+ add_error("unimplemented format assertion: '", cons.format, "'");
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -570,12 +592,12 @@ private:
|
|
|
to.insert(from.begin(), from.end());
|
|
to.insert(from.begin(), from.end());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- template <typename K>
|
|
|
|
|
- Status validate_subschema(schema::Node const * subschema, K const & key) const {
|
|
|
|
|
|
|
+ template <typename... K>
|
|
|
|
|
+ Status validate_subschema(schema::Node const * subschema, K const &... keys) const {
|
|
|
VisitedAnnotation annotate;
|
|
VisitedAnnotation annotate;
|
|
|
|
|
|
|
|
ValidationVisitor next = *this;
|
|
ValidationVisitor next = *this;
|
|
|
- next.schema_path_ /= key;
|
|
|
|
|
|
|
+ ((next.schema_path_ /= keys), ...);
|
|
|
std::tie(next.schema_, next.visited_) =
|
|
std::tie(next.schema_, next.visited_) =
|
|
|
std::forward_as_tuple(subschema, visited_ ? &annotate : nullptr);
|
|
std::forward_as_tuple(subschema, visited_ ? &annotate : nullptr);
|
|
|
|
|
|