diff --git a/include/valijson/adapters/property_tree_adapter.hpp b/include/valijson/adapters/property_tree_adapter.hpp index 6121914..2957d1c 100644 --- a/include/valijson/adapters/property_tree_adapter.hpp +++ b/include/valijson/adapters/property_tree_adapter.hpp @@ -360,17 +360,17 @@ public: return false; } - bool getBool(bool &result) const + bool getBool(bool &) const { return false; } - bool getDouble(double &result) const + bool getDouble(double &) const { return false; } - bool getInteger(int64_t &result) const + bool getInteger(int64_t &) const { return false; } diff --git a/include/valijson/constraint_builder.hpp b/include/valijson/constraint_builder.hpp new file mode 100644 index 0000000..7b1ab79 --- /dev/null +++ b/include/valijson/constraint_builder.hpp @@ -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 diff --git a/include/valijson/constraints/concrete_constraints.hpp b/include/valijson/constraints/concrete_constraints.hpp index 142aaa1..e5dbe64 100644 --- a/include/valijson/constraints/concrete_constraints.hpp +++ b/include/valijson/constraints/concrete_constraints.hpp @@ -812,7 +812,7 @@ public: const std::vector& context, valijson::ValidationResults *results) const = 0; -protected: +private: virtual Constraint * cloneInto(void *) const = 0; virtual size_t sizeOf() const = 0; diff --git a/include/valijson/schema_parser.hpp b/include/valijson/schema_parser.hpp index a3d70c8..8970d12 100644 --- a/include/valijson/schema_parser.hpp +++ b/include/valijson/schema_parser.hpp @@ -4,6 +4,8 @@ #include #include +#include +#include #include #include @@ -15,6 +17,7 @@ #include #include #include +#include #include #ifdef __clang__ @@ -36,7 +39,6 @@ namespace valijson { class SchemaParser { public: - /// Supported versions of JSON Schema enum Version { kDraft3, ///< @deprecated JSON Schema v3 has been superseded by v4 @@ -54,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 */ @@ -70,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 * @@ -110,6 +147,11 @@ public: private: + typedef std::vector > + ConstraintBuilders; + + ConstraintBuilders constraintBuilders; + template struct DocumentCache { @@ -841,6 +883,23 @@ private: rootSchema.addConstraintToSubschema(*constraint, &subschema); } } + + for (ConstraintBuilders::const_iterator + builderItr = constraintBuilders.begin(); + builderItr != constraintBuilders.end(); ++builderItr) { + if ((itr = object.find(builderItr->first)) != object.end()) { + constraints::Constraint *constraint = NULL; + try { + constraint = builderItr->second->make(itr->second); + rootSchema.addConstraintToSubschema(*constraint, + &subschema); + delete constraint; + } catch (...) { + delete constraint; + throw; + } + } + } } /** diff --git a/include/valijson/subschema.hpp b/include/valijson/subschema.hpp index 8ac4a0c..7d88f03 100644 --- a/include/valijson/subschema.hpp +++ b/include/valijson/subschema.hpp @@ -91,41 +91,15 @@ public: */ void addConstraint(const Constraint &constraint) { - constraints.push_back(constraint.clone(allocFn, freeFn)); - } - - /** - * @brief move a constraint to this sub-schema - * - * The constraint will be added to the list of constraints for this - * Subschema. - * - * @param constraint pointer to the constraint to be added. Ownership - * assumed. - */ - void addConstraint(const Constraint *constraint) - { - constraints.push_back(constraint); - } - - //#if _cplusplus >=201103L - #if 0 - /** - * @brief Add a constraint to this sub-schema - * - * The constraint will be copied before being added to the list of - * constraints for this Subschema. Note that constraints will be copied - * only as deep as references to other Subschemas - e.g. copies of - * constraints that refer to sub-schemas, will continue to refer to the - * same Subschema instances. - * - * @param constraint Reference to the constraint to copy - */ - void addConstraint(std::unique_ptrconstraint) - { - constraints.push_back(constraint.release()); + Constraint *newConstraint = constraint.clone(allocFn, freeFn); + try { + constraints.push_back(newConstraint); + } catch (...) { + newConstraint->~Constraint(); + freeFn(newConstraint); + throw; } - #endif + } /** * @brief Invoke a function on each child Constraint diff --git a/include/valijson/validation_results.hpp b/include/valijson/validation_results.hpp index f36acde..e6e8d57 100644 --- a/include/valijson/validation_results.hpp +++ b/include/valijson/validation_results.hpp @@ -19,6 +19,7 @@ class ValidationResults { public: + virtual ~ValidationResults() {} /** * @brief Describes a validation error. * diff --git a/xcode/valijson.xcodeproj/project.pbxproj b/xcode/valijson.xcodeproj/project.pbxproj index 3483469..6409d99 100644 --- a/xcode/valijson.xcodeproj/project.pbxproj +++ b/xcode/valijson.xcodeproj/project.pbxproj @@ -171,6 +171,7 @@ 6A869A2517CD8641006864FA /* type.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = type.json; sourceTree = ""; }; 6A869A2617CD8641006864FA /* uniqueItems.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = uniqueItems.json; sourceTree = ""; }; 6A869A3017CD8A92006864FA /* rapidjson_utils.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = rapidjson_utils.hpp; sourceTree = ""; }; + 6A8BA11C1CB71163001CA087 /* constraint_builder.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = constraint_builder.hpp; sourceTree = ""; }; 6A9297071C4B1A3500737891 /* allocators.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = allocators.h; sourceTree = ""; }; 6A9297081C4B1A3500737891 /* document.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = document.h; sourceTree = ""; }; 6A9297091C4B1A3500737891 /* encodedstream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = encodedstream.h; sourceTree = ""; }; @@ -858,6 +859,7 @@ 6AC78BE317C5FC6A00674114 /* constraints */, 6A506D1D1AF88D5E00C2C818 /* internal */, 6A869A2F17CD8A81006864FA /* utils */, + 6A8BA11C1CB71163001CA087 /* constraint_builder.hpp */, 6AC78BE917C5FC6A00674114 /* schema.hpp */, 6AC78BEA17C5FC6A00674114 /* schema_parser.hpp */, 6A309D2D1C28C1FD00EF761C /* subschema.hpp */, @@ -1078,7 +1080,7 @@ 6AC78AC517C5FBBC00674114 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0730; ORGANIZATIONNAME = "Tristan Penman"; TargetAttributes = { 6A5C5D461C5B151F004F40ED = { @@ -1185,19 +1187,9 @@ 6A5C5D491C5B151F004F40ED /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = "-"; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - EXECUTABLE_PREFIX = lib; - GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -1208,19 +1200,9 @@ 6A5C5D4A1C5B151F004F40ED /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = "-"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - EXECUTABLE_PREFIX = lib; - GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -1423,17 +1405,13 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; EXECUTABLE_PREFIX = lib; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "../thirdparty/jsoncpp-0.9.4/include", ); MTL_ENABLE_DEBUG_INFO = YES; @@ -1446,17 +1424,13 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; EXECUTABLE_PREFIX = lib; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "../thirdparty/jsoncpp-0.9.4/include", ); MTL_ENABLE_DEBUG_INFO = NO;