Move ConstraintBuilder to its own header file and update SchemaParser to explicitly take ownership of a ConstraintBuilder by pointer

This commit is contained in:
Tristan Penman 2016-04-08 08:24:05 +10:00
parent 9ad441dfbe
commit 078ee62301
3 changed files with 83 additions and 21 deletions

View File

@ -0,0 +1,25 @@
#pragma once
#ifndef __VALIJSON_CONSTRAINT_BUILDER_HPP
#define __VALIJSON_CONSTRAINT_BUILDER_HPP
namespace valijson {
namespace adapters {
class Adapter;
}
namespace constraints {
struct Constraint;
}
class ConstraintBuilder
{
public:
virtual ~ConstraintBuilder() {}
virtual constraints::Constraint * make(const adapters::Adapter &) const = 0;
};
} // namespace valijson
#endif

View File

@ -17,6 +17,7 @@
#include <valijson/internal/json_pointer.hpp>
#include <valijson/internal/json_reference.hpp>
#include <valijson/internal/uri.hpp>
#include <valijson/constraint_builder.hpp>
#include <valijson/schema.hpp>
#ifdef __clang__
@ -26,12 +27,6 @@
namespace valijson {
class ConstraintBuilder {
public:
virtual ~ConstraintBuilder() {}
virtual std::unique_ptr<constraints::Constraint> make(adapters::Adapter &node) = 0;
};
/**
* @brief Parser for populating a Schema based on a JSON Schema document.
*
@ -44,11 +39,6 @@ class ConstraintBuilder {
class SchemaParser
{
public:
void addConstraintBuilder(const std::string &key, ConstraintBuilder &builder) {
regConstraints.emplace_back(key, &builder);
}
/// Supported versions of JSON Schema
enum Version {
kDraft3, ///< @deprecated JSON Schema v3 has been superseded by v4
@ -66,6 +56,17 @@ public:
SchemaParser(const Version version = kDraft4)
: version(version) { }
/**
* @brief Release memory associated with custom ConstraintBuilders
*/
~SchemaParser()
{
for (ConstraintBuilders::iterator itr = constraintBuilders.begin();
itr != constraintBuilders.end(); ++itr) {
delete (*itr).second;
}
}
/**
* @brief Struct to contain templated function type for fetching documents
*/
@ -82,6 +83,30 @@ public:
typedef void (*FreeDoc)(const DocumentType *);
};
/**
* @brief Add a custom contraint to this SchemaParser
* @param key name that will be used to identify relevant constraints
* while parsing a schema document
* @param builder pointer to a subclass of ConstraintBuilder that can
* parse custom constraints found in a schema document,
* and return an appropriate instance of Constraint; this
* class guarantees that it will take ownership of this
* pointer - unless this function throws an exception
*
* @todo consider accepting a list of custom ConstraintBuilders in
* constructor, so that this class remains immutable after
* construction
*
* @todo Add additional checks for key conflicts, empty keys, and
* potential restrictions relating to case sensitivity
*/
void addConstraintBuilder(const std::string &key,
const ConstraintBuilder *builder)
{
constraintBuilders.push_back(std::make_pair(key, builder));
}
/**
* @brief Populate a Schema object from JSON Schema document
*
@ -122,6 +147,11 @@ public:
private:
typedef std::vector<std::pair<std::string, const ConstraintBuilder *>>
ConstraintBuilders;
ConstraintBuilders constraintBuilders;
template<typename AdapterType>
struct DocumentCache
{
@ -521,9 +551,6 @@ private:
schemaCache, schemaCacheKeysToCreate);
}
std::vector<std::pair<std::string, ConstraintBuilder *>> regConstraints;
/**
* @brief Populate a Schema object from JSON Schema document
*
@ -785,13 +812,6 @@ private:
makePatternConstraint(itr->second), &subschema);
}
for (auto &builder : regConstraints) {
if ((itr = object.find(builder.first)) != object.end()) {
auto pcons = builder.second->make(itr->second);
rootSchema.addConstraintToSubschema(*pcons, &subschema);
}
}
{
// Check for schema keywords that require the creation of a
// PropertiesConstraint instance.
@ -863,6 +883,21 @@ private:
rootSchema.addConstraintToSubschema(*constraint, &subschema);
}
}
for (auto &builder : constraintBuilders) {
if ((itr = object.find(builder.first)) != object.end()) {
constraints::Constraint *constraint = NULL;
try {
constraint = builder.second->make(itr->second);
rootSchema.addConstraintToSubschema(*constraint,
&subschema);
delete constraint;
} catch (...) {
delete constraint;
throw;
}
}
}
}
/**

View File

@ -171,6 +171,7 @@
6A869A2517CD8641006864FA /* type.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = type.json; sourceTree = "<group>"; };
6A869A2617CD8641006864FA /* uniqueItems.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = uniqueItems.json; sourceTree = "<group>"; };
6A869A3017CD8A92006864FA /* rapidjson_utils.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = rapidjson_utils.hpp; sourceTree = "<group>"; };
6A8BA11C1CB71163001CA087 /* constraint_builder.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = constraint_builder.hpp; sourceTree = "<group>"; };
6A9297071C4B1A3500737891 /* allocators.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = allocators.h; sourceTree = "<group>"; };
6A9297081C4B1A3500737891 /* document.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = document.h; sourceTree = "<group>"; };
6A9297091C4B1A3500737891 /* encodedstream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = encodedstream.h; sourceTree = "<group>"; };
@ -858,6 +859,7 @@
6AC78BE317C5FC6A00674114 /* constraints */,
6A506D1D1AF88D5E00C2C818 /* internal */,
6A869A2F17CD8A81006864FA /* utils */,
6A8BA11C1CB71163001CA087 /* constraint_builder.hpp */,
6AC78BE917C5FC6A00674114 /* schema.hpp */,
6AC78BEA17C5FC6A00674114 /* schema_parser.hpp */,
6A309D2D1C28C1FD00EF761C /* subschema.hpp */,