mirror of
https://github.com/tristanpenman/valijson.git
synced 2025-09-27 16:29:33 +02:00
Update EnumConstraint to use custom allocator for collection (but not frozen values)
This commit is contained in:
parent
99a5c2f604
commit
f779b0780c
@ -95,16 +95,15 @@ void addPropertiesConstraint(Schema &schema)
|
||||
{
|
||||
// Prepare an enum constraint requires a document to be equal to at
|
||||
// least one of a set of possible values
|
||||
EnumConstraint::Values enumConstraintValues;
|
||||
enumConstraintValues.push_back(new RapidJsonFrozenValue("album"));
|
||||
enumConstraintValues.push_back(new RapidJsonFrozenValue("book"));
|
||||
enumConstraintValues.push_back(new RapidJsonFrozenValue("other"));
|
||||
enumConstraintValues.push_back(new RapidJsonFrozenValue("video"));
|
||||
EnumConstraint constraint;
|
||||
constraint.addValue(RapidJsonFrozenValue("album"));
|
||||
constraint.addValue(RapidJsonFrozenValue("book"));
|
||||
constraint.addValue(RapidJsonFrozenValue("other"));
|
||||
constraint.addValue(RapidJsonFrozenValue("video"));
|
||||
|
||||
// Create a subschema, owned by the root schema, with a constraint
|
||||
const Subschema *subschema = schema.createSubschema();
|
||||
schema.addConstraintToSubschema(EnumConstraint(enumConstraintValues),
|
||||
subschema);
|
||||
schema.addConstraintToSubschema(constraint, subschema);
|
||||
|
||||
// Include subschema in properties constraint
|
||||
propertySchemaMap["category"] = subschema;
|
||||
|
@ -50,19 +50,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implementation of new_clone for the FrozenValue interface, as
|
||||
* required for the boost pointer containers.
|
||||
*
|
||||
* @param frozenValue reference to FrozenValue to clone
|
||||
*
|
||||
* @returns a pointer to a new FrozenValue, belonging to the caller
|
||||
*/
|
||||
inline FrozenValue * new_clone(const FrozenValue &frozenValue)
|
||||
{
|
||||
return frozenValue.clone();
|
||||
}
|
||||
|
||||
} // namespace adapters
|
||||
} // namespace valijson
|
||||
|
||||
|
@ -231,20 +231,51 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents an 'enum' constraint.
|
||||
* @brief Represents an 'enum' constraint
|
||||
*
|
||||
* An enum constraint provides a set of permissible values for a JSON node. The
|
||||
* node will only validate against this constraint if it matches one of the
|
||||
* values in the set.
|
||||
* An enum constraint provides a collection of permissible values for a JSON
|
||||
* node. The node will only validate against this constraint if it matches one
|
||||
* or more of the values in the collection.
|
||||
*/
|
||||
struct EnumConstraint: BasicConstraint<EnumConstraint>
|
||||
class EnumConstraint: public BasicConstraint<EnumConstraint>
|
||||
{
|
||||
typedef boost::ptr_vector<adapters::FrozenValue> Values;
|
||||
public:
|
||||
EnumConstraint()
|
||||
: enumValues(Allocator::rebind<const EnumValue *>::other(allocator)) { }
|
||||
|
||||
EnumConstraint(const Values &values) // Copy each of the frozen values
|
||||
: values(values) { }
|
||||
EnumConstraint(CustomAlloc allocFn, CustomFree freeFn)
|
||||
: BasicConstraint(allocFn, freeFn),
|
||||
enumValues(Allocator::rebind<const EnumValue *>::other(allocator)) { }
|
||||
|
||||
const Values values;
|
||||
void addValue(const adapters::Adapter &value)
|
||||
{
|
||||
// TODO: Freeze value using custom alloc/free functions
|
||||
enumValues.push_back(value.freeze());
|
||||
}
|
||||
|
||||
void addValue(const adapters::FrozenValue &value)
|
||||
{
|
||||
// TODO: Clone using custom alloc/free functions
|
||||
enumValues.push_back(value.clone());
|
||||
}
|
||||
|
||||
template<typename FunctorType>
|
||||
void applyToValues(const FunctorType &fn) const
|
||||
{
|
||||
BOOST_FOREACH( const EnumValue *value, enumValues ) {
|
||||
if (!fn(*value)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef adapters::FrozenValue EnumValue;
|
||||
|
||||
typedef std::vector<const EnumValue *,
|
||||
internal::CustomAllocator<const EnumValue *> > EnumValues;
|
||||
|
||||
EnumValues enumValues;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,7 @@
|
||||
namespace valijson {
|
||||
namespace constraints {
|
||||
|
||||
struct EnumConstraint;
|
||||
|
||||
struct FormatConstraint;
|
||||
struct MaximumConstraint;
|
||||
struct MaxItemsConstraint;
|
||||
@ -22,6 +22,7 @@ struct PropertiesConstraint;
|
||||
class AllOfConstraint;
|
||||
class AnyOfConstraint;
|
||||
class DependenciesConstraint;
|
||||
class EnumConstraint;
|
||||
class LinearItemsConstraint;
|
||||
class NotConstraint;
|
||||
class OneOfConstraint;
|
||||
|
@ -697,16 +697,16 @@ private:
|
||||
const AdapterType &node)
|
||||
{
|
||||
// Make a copy of each value in the enum array
|
||||
constraints::EnumConstraint::Values values;
|
||||
constraints::EnumConstraint constraint;
|
||||
BOOST_FOREACH( const AdapterType value, node.getArray() ) {
|
||||
values.push_back(value.freeze());
|
||||
constraint.addValue(value);
|
||||
}
|
||||
|
||||
/// @todo This will make another copy of the values while constructing
|
||||
/// the EnumConstraint. Move semantics in C++11 should make it possible
|
||||
/// to avoid these copies without complicating the implementation of the
|
||||
/// EnumConstraint class.
|
||||
return constraints::EnumConstraint(values);
|
||||
return constraint;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -205,30 +205,31 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Validate against the enum constraint represented by an
|
||||
* EnumConstraint object.
|
||||
* @brief Validate current node against an EnumConstraint
|
||||
*
|
||||
* Validation succeeds if the target is equal to one of the values provided
|
||||
* by the enum constraint.
|
||||
* by the EnumConstraint.
|
||||
*
|
||||
* @param constraint Constraint that the target must validate against.
|
||||
* @param constraint Constraint that the target must validate against
|
||||
*
|
||||
* @return true if validation succeeds, false otherwise.
|
||||
* @return \c true if validation succeeds; \c false otherwise
|
||||
*/
|
||||
virtual bool visit(const EnumConstraint &constraint)
|
||||
{
|
||||
// Compare the target with each 'frozen' value in the enum constraint.
|
||||
BOOST_FOREACH( const adapters::FrozenValue &value, constraint.values ) {
|
||||
if (value.equalTo(target, true)) {
|
||||
return true;
|
||||
unsigned int numValidated = 0;
|
||||
constraint.applyToValues(ValidateEquality(target, context, false, true,
|
||||
strictTypes, NULL, &numValidated));
|
||||
|
||||
if (numValidated == 0) {
|
||||
if (results) {
|
||||
results->pushError(context,
|
||||
"Failed to match against any enum values.");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (results) {
|
||||
results->pushError(context, "Failed to match against any enum values.");
|
||||
}
|
||||
|
||||
return false;
|
||||
return numValidated > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1057,6 +1058,56 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Functor to compare a node with a collection of values
|
||||
*/
|
||||
struct ValidateEquality
|
||||
{
|
||||
ValidateEquality(
|
||||
const AdapterType &target,
|
||||
const std::vector<std::string> &context,
|
||||
bool continueOnSuccess,
|
||||
bool continueOnFailure,
|
||||
bool strictTypes,
|
||||
ValidationResults *results,
|
||||
unsigned int *numValidated)
|
||||
: target(target),
|
||||
context(context),
|
||||
continueOnSuccess(continueOnSuccess),
|
||||
continueOnFailure(continueOnFailure),
|
||||
strictTypes(strictTypes),
|
||||
results(results),
|
||||
numValidated(numValidated) { }
|
||||
|
||||
template<typename OtherValue>
|
||||
bool operator()(const OtherValue &value) const
|
||||
{
|
||||
if (value.equalTo(target, strictTypes)) {
|
||||
if (numValidated) {
|
||||
(*numValidated)++;
|
||||
}
|
||||
|
||||
return continueOnSuccess;
|
||||
}
|
||||
|
||||
if (results) {
|
||||
results->pushError(context,
|
||||
"Target value and comparison value are not equal");
|
||||
}
|
||||
|
||||
return continueOnFailure;
|
||||
}
|
||||
|
||||
private:
|
||||
const AdapterType ⌖
|
||||
const std::vector<std::string> &context;
|
||||
bool continueOnSuccess;
|
||||
bool continueOnFailure;
|
||||
bool strictTypes;
|
||||
ValidationResults * const results;
|
||||
unsigned int * const numValidated;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Functor to validate the presence of a set of properties
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user