From b45e305122640e3de8fe2fc63df07b995252827f Mon Sep 17 00:00:00 2001 From: Leonetienne Date: Sun, 5 Sep 2021 12:56:34 +0200 Subject: [PATCH] Added daisychain methods to easily create more complex parameter constraints --- Hazelnupp/ParamConstraint.h | 33 ++++++++++ Hazelnupp/Version.h | 2 +- Test_Hazelnupp/Constraints.cpp | 116 +++++++++++++++++++++++++++++++++ readme.md | 18 ++--- 4 files changed, 159 insertions(+), 10 deletions(-) diff --git a/Hazelnupp/ParamConstraint.h b/Hazelnupp/ParamConstraint.h index d6b9af7..3870555 100644 --- a/Hazelnupp/ParamConstraint.h +++ b/Hazelnupp/ParamConstraint.h @@ -22,6 +22,17 @@ namespace Hazelnp return pc; } + //! Daisychain-method. Will add a the "required-argument" aspect. + //! Think of the default value like of a list ofparameters. Like {"--width", "800"} + ParamConstraint AddRequire(const std::initializer_list& defaultValue = {}, bool required = true) + { + ParamConstraint pc = *this; + pc.defaultValue = defaultValue; + pc.required = required; + + return pc; + } + //! Constructs a type-safety constraint static ParamConstraint TypeSafety(DATA_TYPE requiredType, bool constrainType = true) { @@ -32,6 +43,17 @@ namespace Hazelnp return pc; } + //! Daisychain-method. Will add a the "type-safety" aspect. + //! Constructs a type-safety constraint + ParamConstraint AddTypeSafety(DATA_TYPE requiredType, bool constrainType = true) + { + ParamConstraint pc = *this; + pc.constrainType = constrainType; + pc.requiredType = requiredType; + + return pc; + } + //! Constructs an incompatibility constraint. //! This means, that the following parameters are NOT compatible with this one and will throw an error if passed together static ParamConstraint Incompatibility(const std::initializer_list& incompatibleParameters) @@ -53,6 +75,17 @@ namespace Hazelnp return pc; } + //! Daisychain-method. Will add a the "incompatiblity" aspect. + //! This means, that the following parameters are NOT compatible with this one and will throw an error if passed together. + //! Syntactical-sugar proxy method that will convert the lonely string to an initializer list for you :3 + ParamConstraint AddIncompatibility(const std::string& incompatibleParameters) + { + ParamConstraint pc = *this; + pc.incompatibleParameters = { incompatibleParameters }; + + return pc; + } + //! Whole constructor ParamConstraint(bool constrainType, DATA_TYPE requiredType, const std::initializer_list& defaultValue, bool required, const std::initializer_list& incompatibleParameters) : diff --git a/Hazelnupp/Version.h b/Hazelnupp/Version.h index 4cda2cb..7627cda 100644 --- a/Hazelnupp/Version.h +++ b/Hazelnupp/Version.h @@ -1,2 +1,2 @@ #pragma once -#define HAZELNUPP_VERSION (1.11) +#define HAZELNUPP_VERSION (1.12) diff --git a/Test_Hazelnupp/Constraints.cpp b/Test_Hazelnupp/Constraints.cpp index cb13f07..aa07d93 100644 --- a/Test_Hazelnupp/Constraints.cpp +++ b/Test_Hazelnupp/Constraints.cpp @@ -676,5 +676,121 @@ namespace TestHazelnupp return; } + + // Tests that daisychained construction of constraints works. Tests for the require constraint to work + TEST_METHOD(Daisychained_Construction_Test_Require) + { + // Setup + ArgList args({ + "/my/fake/path/wahoo.out", + }); + + Assert::ExpectException( + [args] + { + CmdArgsInterface cmdArgsI; + cmdArgsI.SetCrashOnFail(false); + + cmdArgsI.RegisterConstraint( + "--width", + ParamConstraint::Require() + .AddTypeSafety(DATA_TYPE::FLOAT) + .AddIncompatibility({ "--antiwidth" }) + ); + + cmdArgsI.Parse(C_Ify(args)); + } + ); + + return; + } + + // Tests that daisychained construction of constraints works. Tests for the type safety constraint to work + TEST_METHOD(Daisychained_Construction_Test_TypeSafety) + { + // Setup + ArgList args({ + "/my/fake/path/wahoo.out", + "--width", + "alejandro" + }); + + Assert::ExpectException( + [args] + { + CmdArgsInterface cmdArgsI; + cmdArgsI.SetCrashOnFail(false); + + cmdArgsI.RegisterConstraint( + "--width", + ParamConstraint::TypeSafety(DATA_TYPE::FLOAT) + .AddRequire() + .AddIncompatibility({ "--antiwidth" }) + ); + + cmdArgsI.Parse(C_Ify(args)); + } + ); + + return; + } + + // Tests that daisychained construction of constraints works. Tests for the incompatibility constraint to work + TEST_METHOD(Daisychained_Construction_Test_Incompatibility) + { + // Setup + ArgList args({ + "/my/fake/path/wahoo.out", + "--width", + "8930", + "--antiwidth" + }); + + Assert::ExpectException( + [args] + { + CmdArgsInterface cmdArgsI; + cmdArgsI.SetCrashOnFail(false); + + cmdArgsI.RegisterConstraint( + "--width", + ParamConstraint::Incompatibility({ "--antiwidth" }) + .AddTypeSafety(DATA_TYPE::FLOAT) + .AddRequire() + ); + + cmdArgsI.Parse(C_Ify(args)); + } + ); + + return; + } + + // Tests that daisychained construction of constraints works. Tests for the command to pass, because all constraints should be respected + TEST_METHOD(Daisychained_Construction_Test_AllOkay) + { + // Setup + ArgList args({ + "/my/fake/path/wahoo.out", + "--width", + "8930" + }); + + { + CmdArgsInterface cmdArgsI; + cmdArgsI.SetCrashOnFail(false); + + cmdArgsI.RegisterConstraint( + "--width", + ParamConstraint::Require() + .AddTypeSafety(DATA_TYPE::FLOAT) + .AddIncompatibility({ "--antiwidth" }) + ); + + cmdArgsI.Parse(C_Ify(args)); + } + + return; + } }; } diff --git a/readme.md b/readme.md index ef87790..5769881 100644 --- a/readme.md +++ b/readme.md @@ -275,17 +275,17 @@ int main(int argc, char** argv) ``` --- -Note that you can also combine these two constraint-types by populating the struct yourself: +Keep in mind that you can only register ONE constraint for each parameter! +Adding another one will just overwrite the prior one. +However, one constraint can do all three "types" at once if you daisychain them: ```cpp -ParamConstraint pc; -pc.constrainType = true; -pc.requiredType = DATA_TYPE::STRING; -pc.defaultValue = {}; // no default value -pc.required = true; - -args.RegisterConstraint("--my-key", pc); +args.RegisterConstraint( + "--width", + ParamConstraint::Require() // Make this parameter mandatory + .AddTypeSafety(DATA_TYPE::FLOAT) // Force this param to be a float + .AddIncompatibility({ "--antiwidth" }) // Make this param incompatible with '--antiwidth' +); ``` -What doesn't work is inserting multiple constraints for one key. It will just discard the older one. But that's okay because one can describe all possible constraints for a single key in **one** struct. ## Automatic parameter documentation