Allow use of custom alloc/free functions within Subschema class, specifically for allocating memory for Constraints

This commit is contained in:
Tristan Penman 2015-12-24 08:03:02 +11:00
parent 99455298d8
commit 49fa41ba23
4 changed files with 56 additions and 28 deletions

View File

@ -159,14 +159,14 @@ void addRequiredConstraint(Schema &schema)
requiredProperties.insert("category");
requiredProperties.insert("price");
requiredProperties.insert("title");
schema.addConstraint(new RequiredConstraint(requiredProperties));
schema.addConstraint(RequiredConstraint(requiredProperties));
}
void addTypeConstraint(Schema &schema)
{
// Add a TypeConstraint to the schema, specifying that the root of the
// document must be an object.
schema.addConstraint(new TypeConstraint(TypeConstraint::kObject));
schema.addConstraint(TypeConstraint(TypeConstraint::kObject));
}
int main(int argc, char *argv[])

View File

@ -25,9 +25,21 @@ struct BasicConstraint: Constraint
return visitor.visit(*static_cast<const ConstraintType*>(this));
}
virtual Constraint * clone() const
virtual Constraint * clone(CustomAlloc allocFn, CustomFree freeFn) const
{
return new ConstraintType(*static_cast<const ConstraintType*>(this));
void *ptr = allocFn(sizeof(ConstraintType));
if (!ptr) {
throw std::runtime_error(
"Failed to allocate memory for cloned constraint");
}
try {
return new (ptr) ConstraintType(
*static_cast<const ConstraintType*>(this));
} catch (...) {
freeFn(ptr);
throw;
}
}
};

View File

@ -12,7 +12,13 @@ class ConstraintVisitor;
*
* @todo Consider using something like the boost::cloneable concept here.
*/
struct Constraint {
struct Constraint
{
/// Typedef for custom new-/malloc-like function
typedef void * (*CustomAlloc)(size_t size);
/// Typedef for custom free-like function
typedef void (*CustomFree)(void *);
/**
* @brief Virtual destructor.
@ -38,15 +44,10 @@ struct Constraint {
*
* @returns an owning-pointer to the new constraint.
*/
virtual Constraint * clone() const = 0;
virtual Constraint * clone(CustomAlloc, CustomFree) const = 0;
};
inline Constraint * new_clone(const Constraint &constraint)
{
return constraint.clone();
}
} // namespace constraints
} // namespace valijson

View File

@ -25,6 +25,12 @@ namespace valijson {
class Subschema
{
public:
/// Typedef for custom new-/malloc-like function
typedef void * (*CustomAlloc)(size_t size);
/// Typedef for custom free-like function
typedef void (*CustomFree)(void *);
/// Typedef the Constraint class into the local namespace for convenience
typedef constraints::Constraint Constraint;
@ -33,9 +39,24 @@ public:
typedef boost::function<bool (const Constraint &)> ApplyFunction;
/**
* @brief Construct a new Subschema object with no constraints
* @brief Construct a new Subschema object
*/
Subschema() { }
Subschema()
: allocFn(::operator new)
, freeFn(::operator delete) { }
/**
* @brief Construct a new Subschema using custom memory management
* functions
*
* @parma allocFn malloc- or new-like function to allocate memory
* within Schema, such as for Subschema instances
* @param freeFn free-like function to free memory allocated with
* the `customAlloc` function
*/
Subschema(CustomAlloc allocFn, CustomFree freeFn)
: allocFn(allocFn)
, freeFn(freeFn) { }
/**
* @brief Clean up and free all memory managed by the Subschema
@ -46,7 +67,8 @@ public:
for (std::vector<const Constraint *>::iterator itr =
constraints.begin(); itr != constraints.end(); ++itr) {
const Constraint *constraint = *itr;
delete constraint;
constraint->~Constraint();
freeFn((void*)(constraint));
}
constraints.clear();
} catch (const std::exception &e) {
@ -68,20 +90,7 @@ public:
*/
void addConstraint(const Constraint &constraint)
{
constraints.push_back(constraint.clone());
}
/**
* @brief Add a constraint to this sub-schema
*
* This Subschema instance will take ownership of Constraint that is
* pointed to, and will free it when it is no longer needed.
*
* @param constraint Pointer to the Constraint to take ownership of
*/
void addConstraint(Constraint *constraint)
{
constraints.push_back(constraint);
constraints.push_back(constraint.clone(allocFn, freeFn));
}
/**
@ -239,6 +248,12 @@ public:
this->title = title;
}
protected:
CustomAlloc allocFn;
CustomFree freeFn;
private:
// Disable copy construction