Update AllOfConstraint and AnyOfConstraint classes to use custom allocator

This commit is contained in:
Tristan Penman 2015-12-27 19:32:30 +11:00
parent c54bf3ba87
commit d534c49393
3 changed files with 164 additions and 65 deletions

View File

@ -31,9 +31,6 @@
#include <valijson/schema.hpp>
namespace valijson {
class Schema;
namespace constraints {
/**
@ -43,15 +40,40 @@ namespace constraints {
* validate against. If a value fails to validate against any of these sub-
* schemas, then validation fails.
*/
struct AllOfConstraint: BasicConstraint<AllOfConstraint>
class AllOfConstraint: public BasicConstraint<AllOfConstraint>
{
typedef std::vector<const Subschema *> Schemas;
public:
AllOfConstraint()
: subschemas(Allocator::rebind<const Subschema *>::other(allocator)) { }
AllOfConstraint(const Schemas &schemas)
: schemas(schemas) { }
AllOfConstraint(CustomAlloc allocFn, CustomFree freeFn)
: BasicConstraint(allocFn, freeFn),
subschemas(Allocator::rebind<const Subschema *>::other(allocator)) { }
/// Collection of schemas that must all be satisfied
const Schemas schemas;
void addSubschema(const Subschema *subschema)
{
subschemas.push_back(subschema);
}
template<typename FunctorType>
void applyToSubschemas(const FunctorType &fn) const
{
unsigned int index = 0;
BOOST_FOREACH( const Subschema *subschema, subschemas ) {
if (!fn(index, subschema)) {
return;
}
index++;
}
}
private:
typedef std::vector<const Subschema *,
internal::CustomAllocator<const Subschema *> > Subschemas;
/// Collection of sub-schemas, all of which must be satisfied
Subschemas subschemas;
};
/**
@ -61,15 +83,40 @@ struct AllOfConstraint: BasicConstraint<AllOfConstraint>
* validate against. If a value validates against one of these sub-schemas,
* then the validation passes.
*/
struct AnyOfConstraint: BasicConstraint<AnyOfConstraint>
class AnyOfConstraint: public BasicConstraint<AnyOfConstraint>
{
typedef std::vector<const Subschema *> Schemas;
public:
AnyOfConstraint()
: subschemas(Allocator::rebind<const Subschema *>::other(allocator)) { }
AnyOfConstraint(const Schemas &schemas)
: schemas(schemas) { }
AnyOfConstraint(CustomAlloc allocFn, CustomFree freeFn)
: BasicConstraint(allocFn, freeFn),
subschemas(Allocator::rebind<const Subschema *>::other(allocator)) { }
/// Collection of schemas of which one must be satisfied
const Schemas schemas;
void addSubschema(const Subschema *subschema)
{
subschemas.push_back(subschema);
}
template<typename FunctorType>
void applyToSubschemas(const FunctorType &fn) const
{
unsigned int index = 0;
BOOST_FOREACH( const Subschema *subschema, subschemas ) {
if (!fn(index, subschema)) {
return;
}
index++;
}
}
private:
typedef std::vector<const Subschema *,
internal::CustomAllocator<const Subschema *> > Subschemas;
/// Collection of sub-schemas, at least one of which must be satisfied
Subschemas subschemas;
};
/**
@ -146,29 +193,25 @@ public:
}
template<typename FunctorType>
bool applyToPropertyDependencies(const FunctorType &fn) const
void applyToPropertyDependencies(const FunctorType &fn) const
{
BOOST_FOREACH( const PropertyDependencies::value_type &v,
propertyDependencies ) {
if (!fn(v.first, v.second)) {
return false;
return;
}
}
return true;
}
template<typename FunctorType>
bool applyToSchemaDependencies(const FunctorType &fn) const
void applyToSchemaDependencies(const FunctorType &fn) const
{
BOOST_FOREACH( const SchemaDependencies::value_type &v,
schemaDependencies ) {
if (!fn(v.first, v.second)) {
return false;
return;
}
}
return true;
}
private:

View File

@ -496,16 +496,17 @@ private:
"Expected array value for 'allOf' constraint.");
}
constraints::AllOfConstraint::Schemas childSchemas;
constraints::AllOfConstraint constraint;
int index = 0;
BOOST_FOREACH ( const AdapterType schemaNode, node.asArray() ) {
if (schemaNode.maybeObject()) {
const std::string childPath = nodePath + "/" +
boost::lexical_cast<std::string>(index);
childSchemas.push_back(rootSchema.createSubschema());
const Subschema *subschema = rootSchema.createSubschema();
constraint.addSubschema(subschema);
populateSchema<AdapterType>(rootSchema, rootNode, schemaNode,
*childSchemas.back(), currentScope, childPath,
fetchDoc);
*subschema, currentScope, childPath, fetchDoc);
index++;
} else {
throw std::runtime_error(
@ -514,7 +515,7 @@ private:
}
}
return constraints::AllOfConstraint(childSchemas);
return constraint;
}
/**
@ -548,16 +549,17 @@ private:
"Expected array value for 'anyOf' constraint.");
}
constraints::AnyOfConstraint::Schemas childSchemas;
constraints::AnyOfConstraint constraint;
int index = 0;
BOOST_FOREACH ( const AdapterType schemaNode, node.asArray() ) {
if (schemaNode.maybeObject()) {
const std::string childPath = nodePath + "/" +
boost::lexical_cast<std::string>(index);
childSchemas.push_back(rootSchema.createSubschema());
const Subschema *subschema = rootSchema.createSubschema();
constraint.addSubschema(subschema);
populateSchema<AdapterType>(rootSchema, rootNode, schemaNode,
*childSchemas.back(), currentScope, childPath,
fetchDoc);
*subschema, currentScope, childPath, fetchDoc);
index++;
} else {
throw std::runtime_error(
@ -566,7 +568,7 @@ private:
}
}
return constraints::AnyOfConstraint(childSchemas);
return constraint;
}
/**

View File

@ -112,27 +112,10 @@ public:
*/
virtual bool visit(const AllOfConstraint &constraint)
{
// Flag used to track validation status if errors are non-fatal
bool validated = true;
// Validate against each child schema
unsigned int index = 0;
BOOST_FOREACH( const Subschema *subschema, constraint.schemas ) {
// Ensure that the target validates against child schema
if (!validateSchema(*subschema)) {
if (results) {
validated = false;
results->pushError(context,
std::string("Failed to validate against child schema #") +
boost::lexical_cast<std::string>(index) + " of allOf constraint.");
} else {
return false;
}
}
index++;
}
constraint.applyToSubschemas(ValidateAllSubschemas(target, context,
*this, results, &validated));
return validated;
}
@ -157,22 +140,17 @@ public:
*/
virtual bool visit(const AnyOfConstraint &constraint)
{
// Wrap the validationCallback() function below so that it will be
// passed a reference to a constraint (_1), and a reference to the
// visitor (*this).
Schema::ApplyFunction fn(boost::bind(validationCallback, _1, *this));
bool validated = false;
BOOST_FOREACH( const Subschema *subschema, constraint.schemas ) {
if (subschema->apply(fn)) {
return true;
}
constraint.applyToSubschemas(ValidateAtLeastOneSubschema(target,
context, *this, results, &validated));
if (!validated && results) {
results->pushError(context, "Failed to validate against any child "
"schemas allowed by anyOf constraint.");
}
if (results) {
results->pushError(context, "Failed to validate against any child schemas allowed by anyOf constraint.");
}
return false;
return validated;
}
/**
@ -1066,6 +1044,82 @@ public:
private:
struct ValidateAllSubschemas
{
ValidateAllSubschemas(
const AdapterType &adapter,
const std::vector<std::string> &context,
ValidationVisitor &validationVisitor,
ValidationResults *results,
bool *validated)
: adapter(adapter),
context(context),
validationVisitor(validationVisitor),
results(results),
validated(validated) { }
bool operator()(unsigned int index, const Subschema *subschema) const
{
if (!validationVisitor.validateSchema(*subschema)) {
if (validated) {
*validated = false;
}
if (results) {
results->pushError(context,
"Failed to validate against child schema #" +
boost::lexical_cast<std::string>(index) +
" of allOf constraint.");
}
return false;
}
return true;
}
private:
const AdapterType &adapter;
const std::vector<std::string> &context;
ValidationVisitor &validationVisitor;
ValidationResults * const results;
bool * const validated;
};
struct ValidateAtLeastOneSubschema
{
ValidateAtLeastOneSubschema(
const AdapterType &adapter,
const std::vector<std::string> &context,
ValidationVisitor &validationVisitor,
ValidationResults *results,
bool *validated)
: adapter(adapter),
context(context),
validationVisitor(validationVisitor),
results(results),
validated(validated) { }
bool operator()(unsigned int index, const Subschema *subschema) const
{
if (validationVisitor.validateSchema(*subschema)) {
if (validated) {
*validated = true;
}
return false;
}
return true;
}
private:
const AdapterType &adapter;
const std::vector<std::string> &context;
ValidationVisitor &validationVisitor;
ValidationResults * const results;
bool * const validated;
};
struct ValidatePropertyDependencies
{
ValidatePropertyDependencies(