From 14e31be16d967eec1fa1a1db6029736246737ddb Mon Sep 17 00:00:00 2001 From: Tristan Penman Date: Mon, 11 Jan 2016 21:37:12 +1100 Subject: [PATCH] Improve encapsulation in MinLengthConstraint and MaxLengthConstraint classes --- examples/custom_schema.cpp | 8 ++- .../constraints/concrete_constraints.hpp | 57 +++++++++++++++---- .../constraints/constraint_visitor.hpp | 4 +- include/valijson/schema_parser.hpp | 14 +++-- include/valijson/validation_visitor.hpp | 36 ++++++------ 5 files changed, 83 insertions(+), 36 deletions(-) diff --git a/examples/custom_schema.cpp b/examples/custom_schema.cpp index 8df3ee1..da8a1f3 100644 --- a/examples/custom_schema.cpp +++ b/examples/custom_schema.cpp @@ -141,8 +141,12 @@ void addPropertiesConstraint(Schema &schema) // Create a child schema for the 'title' property that requires a string // that is between 1 and 200 characters in length. const Subschema *subschema = schema.createSubschema(); - schema.addConstraintToSubschema(MaxLengthConstraint(200), subschema); - schema.addConstraintToSubschema(MinLengthConstraint(1), subschema); + MaxLengthConstraint maxLengthConstraint; + maxLengthConstraint.setMaxLength(200); + schema.addConstraintToSubschema(maxLengthConstraint, subschema); + MinLengthConstraint minLengthConstraint; + minLengthConstraint.setMinLength(0); + schema.addConstraintToSubschema(minLengthConstraint, subschema); TypeConstraint typeConstraint; typeConstraint.addNamedType(TypeConstraint::kString); schema.addConstraintToSubschema(typeConstraint, subschema); diff --git a/include/valijson/constraints/concrete_constraints.hpp b/include/valijson/constraints/concrete_constraints.hpp index 323a13b..262fccf 100644 --- a/include/valijson/constraints/concrete_constraints.hpp +++ b/include/valijson/constraints/concrete_constraints.hpp @@ -445,14 +445,30 @@ private: }; /** - * @brief Represents a 'maxLength' constraint. + * @brief Represents a 'maxLength' constraint */ -struct MaxLengthConstraint: BasicConstraint +class MaxLengthConstraint: public BasicConstraint { - MaxLengthConstraint(int64_t maxLength) - : maxLength(maxLength) { } +public: + MaxLengthConstraint() + : maxLength(std::numeric_limits::max()) { } - const int64_t maxLength; + MaxLengthConstraint(CustomAlloc allocFn, CustomFree freeFn) + : BasicConstraint(allocFn, freeFn), + maxLength(std::numeric_limits::max()) { } + + int64_t getMaxLength() const + { + return maxLength; + } + + void setMaxLength(int64_t newMaxLength) + { + maxLength = newMaxLength; + } + +private: + int64_t maxLength; }; /** @@ -539,14 +555,35 @@ private: }; /** - * @brief Represents a 'minLength' constraint. + * @brief Represents a 'minLength' constraint */ -struct MinLengthConstraint: BasicConstraint +class MinLengthConstraint: public BasicConstraint { - MinLengthConstraint(int64_t minLength) - : minLength(minLength) { } +public: + MinLengthConstraint() + : minLength(0) { } - const int64_t minLength; + MinLengthConstraint(CustomAlloc allocFn, CustomFree freeFn) + : BasicConstraint(allocFn, freeFn), + minLength(0) { } + + int64_t getMinLength() const + { + return minLength; + } + + void setMinLength(int64_t newMinLength) + { + if (newMinLength < 0) { + throw std::runtime_error( + "Minimum number of items must be a non-negative integer"); + } + + minLength = newMinLength; + } + +private: + int64_t minLength; }; /** diff --git a/include/valijson/constraints/constraint_visitor.hpp b/include/valijson/constraints/constraint_visitor.hpp index 503eee1..42a98a1 100644 --- a/include/valijson/constraints/constraint_visitor.hpp +++ b/include/valijson/constraints/constraint_visitor.hpp @@ -6,9 +6,7 @@ namespace valijson { namespace constraints { struct FormatConstraint; -struct MaxLengthConstraint; struct MaxPropertiesConstraint; -struct MinLengthConstraint; struct MinPropertiesConstraint; struct MultipleOfConstraint; @@ -19,8 +17,10 @@ class EnumConstraint; class LinearItemsConstraint; class MaxItemsConstraint; class MaximumConstraint; +class MaxLengthConstraint; class MinItemsConstraint; class MinimumConstraint; +class MinLengthConstraint; class NotConstraint; class OneOfConstraint; class PatternConstraint; diff --git a/include/valijson/schema_parser.hpp b/include/valijson/schema_parser.hpp index cbc2992..8d99962 100644 --- a/include/valijson/schema_parser.hpp +++ b/include/valijson/schema_parser.hpp @@ -959,9 +959,11 @@ private: const AdapterType &node) { if (node.maybeInteger()) { - int64_t value = node.asInteger(); + const int64_t value = node.asInteger(); if (value >= 0) { - return constraints::MaxLengthConstraint(value); + constraints::MaxLengthConstraint constraint; + constraint.setMaxLength(value); + return constraint; } } @@ -1070,14 +1072,16 @@ private: const AdapterType &node) { if (node.maybeInteger()) { - int64_t value = node.asInteger(); + const int64_t value = node.asInteger(); if (value >= 0) { - return constraints::MinLengthConstraint(value); + constraints::MinLengthConstraint constraint; + constraint.setMinLength(value); + return constraint; } } throw std::runtime_error( - "Expected a positive integer value for 'minLength' " + "Expected a non-negative integer value for 'minLength' " "constraint."); } diff --git a/include/valijson/validation_visitor.hpp b/include/valijson/validation_visitor.hpp index 5b52074..ecfa7b6 100644 --- a/include/valijson/validation_visitor.hpp +++ b/include/valijson/validation_visitor.hpp @@ -410,12 +410,11 @@ public: } /** - * @brief Validate against the maxLength constraint represented by a - * MaxLengthConstraint object. + * @brief Validate a value against a MaxLengthConstraint * - * @param constraint Constraint that the target must validate against. + * @param constraint Constraint that the target must validate against * - * @return true if constraint is satisfied, false otherwise. + * @return \c true if constraint is satisfied; \c false otherwise */ virtual bool visit(const MaxLengthConstraint &constraint) { @@ -424,15 +423,17 @@ public: } const std::string s = target.asString(); - const int len = utils::u8_strlen(s.c_str()); - if (len <= constraint.maxLength) { + const int64_t len = utils::u8_strlen(s.c_str()); + const int64_t maxLength = constraint.getMaxLength(); + if (len <= maxLength) { return true; } if (results) { - results->pushError(context, "String should be no more than " + - boost::lexical_cast(constraint.maxLength) + - " characters in length."); + results->pushError(context, + "String should be no more than " + + boost::lexical_cast(maxLength) + + " characters in length."); } return false; @@ -531,12 +532,11 @@ public: } /** - * @brief Validate against the minLength constraint represented by a - * MinLengthConstraint object. + * @brief Validate a value against a MinLengthConstraint * - * @param constraint Constraint that the target must validate against. + * @param constraint Constraint that the target must validate against * - * @return true if the constraint is satisfied, false otherwise. + * @return \c true if the constraint is satisfied; \c false otherwise */ virtual bool visit(const MinLengthConstraint &constraint) { @@ -546,14 +546,16 @@ public: const std::string s = target.asString(); const int len = utils::u8_strlen(s.c_str()); - if (len >= constraint.minLength) { + const int64_t minLength = constraint.getMinLength(); + if (len >= minLength) { return true; } if (results) { - results->pushError(context, "String should be no fewer than " + - boost::lexical_cast(constraint.minLength) + - " characters in length."); + results->pushError(context, + "String should be no fewer than " + + boost::lexical_cast(minLength) + + " characters in length."); } return false;