Added support for parameter incompatibility constraints
This commit is contained in:
parent
20bb720c6e
commit
cfcd2253ed
@ -45,6 +45,7 @@ void CmdArgsInterface::Parse(const int argc, const char* const* argv)
|
||||
|
||||
executableName = std::string(rawArgs[0]);
|
||||
|
||||
// Read and parse all parameters
|
||||
std::size_t i = 1;
|
||||
while (i < rawArgs.size())
|
||||
{
|
||||
@ -65,13 +66,13 @@ void CmdArgsInterface::Parse(const int argc, const char* const* argv)
|
||||
if ((!catchHelp) || (!HasParam("--help")))
|
||||
ApplyConstraints();
|
||||
}
|
||||
catch (const HazelnuppConstraintTypeMissmatch& exc)
|
||||
catch (const HazelnuppConstraintIncompatibleParameters& exc)
|
||||
{
|
||||
if (crashOnFail)
|
||||
{
|
||||
std::cout << GenerateDocumentation() << std::endl << std::endl;
|
||||
std::cerr << "Parameter error: " << exc.What() << std::endl;
|
||||
quick_exit(-1009);
|
||||
quick_exit(-1000);
|
||||
}
|
||||
else
|
||||
throw exc; // yeet
|
||||
@ -82,7 +83,40 @@ void CmdArgsInterface::Parse(const int argc, const char* const* argv)
|
||||
{
|
||||
std::cout << GenerateDocumentation() << std::endl << std::endl;
|
||||
std::cerr << "Parameter error: " << exc.What() << std::endl;
|
||||
quick_exit(-1010);
|
||||
quick_exit(-1001);
|
||||
}
|
||||
else
|
||||
throw exc; // yeet
|
||||
}
|
||||
catch (const HazelnuppConstraintTypeMissmatch& exc)
|
||||
{
|
||||
if (crashOnFail)
|
||||
{
|
||||
std::cout << GenerateDocumentation() << std::endl << std::endl;
|
||||
std::cerr << "Parameter error: " << exc.What() << std::endl;
|
||||
quick_exit(-1002);
|
||||
}
|
||||
else
|
||||
throw exc; // yeet
|
||||
}
|
||||
catch (const HazelnuppConstraintException& exc)
|
||||
{
|
||||
if (crashOnFail)
|
||||
{
|
||||
std::cout << GenerateDocumentation() << std::endl << std::endl;
|
||||
std::cerr << "Parameter error: " << exc.What() << std::endl;
|
||||
quick_exit(-1003);
|
||||
}
|
||||
else
|
||||
throw exc; // yeet
|
||||
}
|
||||
catch (const HazelnuppException& exc)
|
||||
{
|
||||
if (crashOnFail)
|
||||
{
|
||||
std::cout << GenerateDocumentation() << std::endl << std::endl;
|
||||
std::cerr << "Parameter error: " << exc.What() << std::endl;
|
||||
quick_exit(-1004);
|
||||
}
|
||||
else
|
||||
throw exc; // yeet
|
||||
@ -513,7 +547,6 @@ void CmdArgsInterface::ApplyConstraints()
|
||||
if (pc.second.defaultValue.size() > 0)
|
||||
{
|
||||
// Then create it now, by its default value
|
||||
|
||||
Value* tmp = ParseValue(pc.second.defaultValue, &pc.second);
|
||||
parameters.insert(std::pair<std::string, Parameter*>(
|
||||
pc.second.key,
|
||||
@ -535,6 +568,19 @@ void CmdArgsInterface::ApplyConstraints()
|
||||
);
|
||||
}
|
||||
}
|
||||
// The parameter in question IS supplied
|
||||
else
|
||||
{
|
||||
// Enforce parameter incompatibility
|
||||
|
||||
// Is ANY parameter present listed as incompatible with our current one?
|
||||
for (const std::string& incompatibility : pc.second.incompatibleParameters)
|
||||
for (const std::pair<std::string, Parameter*>& otherParam : parameters)
|
||||
{
|
||||
if (otherParam.first == incompatibility)
|
||||
throw HazelnuppConstraintIncompatibleParameters(pc.second.key, incompatibility);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "Version.h"
|
||||
|
||||
namespace Hazelnp
|
||||
{
|
||||
/** The main class to interface with
|
||||
@ -48,7 +50,7 @@ namespace Hazelnp
|
||||
|
||||
//! Will register a constraint for a parameter.
|
||||
//! IMPORTANT: Any parameter can only have ONE constraint. Applying a new one will overwrite the old one!
|
||||
//! Construct the ParamConstraint struct yourself to combine Require and TypeSafety! You can also use the ParamConstraint constructor!
|
||||
//! Construct the ParamConstraint struct yourself to combine Require, TypeSafety and Incompatibilities! You can also use the ParamConstraint constructor!
|
||||
void RegisterConstraint(const std::string& key, const ParamConstraint& constraint);
|
||||
|
||||
//! Will return the constraint information for a specific parameter
|
||||
|
@ -95,4 +95,21 @@ namespace Hazelnp
|
||||
return;
|
||||
};
|
||||
};
|
||||
|
||||
/** Gets thrown when a parameter constrained to be incompatible with other parameters gets supplied alongside at least one of those incompatible ones
|
||||
*/
|
||||
class HazelnuppConstraintIncompatibleParameters : public HazelnuppConstraintException
|
||||
{
|
||||
public:
|
||||
HazelnuppConstraintIncompatibleParameters() : HazelnuppConstraintException() {};
|
||||
HazelnuppConstraintIncompatibleParameters(const std::string& key1, const std::string& key2)
|
||||
{
|
||||
// Generate descriptive error message
|
||||
std::stringstream ss;
|
||||
ss << "Parameter \"" << key1 << "\" is NOT compatible with parameter \"" << key2 << "\"!";
|
||||
|
||||
message = ss.str();
|
||||
return;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ namespace Hazelnp
|
||||
|
||||
//! Constructs a require constraint.
|
||||
//! Think of the default value like of a list ofparameters. Like {"--width", "800"}
|
||||
static ParamConstraint Require(const std::vector<std::string>& defaultValue = {}, bool required = true)
|
||||
static ParamConstraint Require(const std::initializer_list<std::string>& defaultValue = {}, bool required = true)
|
||||
{
|
||||
ParamConstraint pc;
|
||||
pc.defaultValue = defaultValue;
|
||||
@ -32,13 +32,35 @@ namespace Hazelnp
|
||||
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<std::string>& incompatibleParameters)
|
||||
{
|
||||
ParamConstraint pc;
|
||||
pc.incompatibleParameters = incompatibleParameters;
|
||||
|
||||
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.
|
||||
//! Syntactical-sugar proxy method that will convert the lonely string to an initializer list for you :3
|
||||
static ParamConstraint Incompatibility(const std::string& incompatibleParameters)
|
||||
{
|
||||
ParamConstraint pc;
|
||||
pc.incompatibleParameters = { incompatibleParameters };
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
//! Whole constructor
|
||||
ParamConstraint(bool constrainType, DATA_TYPE requiredType, const std::vector<std::string>& defaultValue, bool required)
|
||||
ParamConstraint(bool constrainType, DATA_TYPE requiredType, const std::initializer_list<std::string>& defaultValue, bool required, const std::initializer_list<std::string>& incompatibleParameters)
|
||||
:
|
||||
constrainType{ constrainType },
|
||||
requiredType{ requiredType },
|
||||
defaultValue{ defaultValue },
|
||||
required{ required }
|
||||
required{ required },
|
||||
incompatibleParameters{incompatibleParameters}
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -59,6 +81,9 @@ namespace Hazelnp
|
||||
//! an error will be produced if this parameter is not supplied by the user.
|
||||
bool required = false;
|
||||
|
||||
//! Parameters that are incompatible with this parameter
|
||||
std::vector<std::string> incompatibleParameters;
|
||||
|
||||
private:
|
||||
//! The parameter this constraint is for.
|
||||
//! This value is automatically set by Hazelnupp.
|
||||
|
2
Hazelnupp/Version.h
Normal file
2
Hazelnupp/Version.h
Normal file
@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
#define HAZELNUPP_VERSION (1.1)
|
@ -22,8 +22,10 @@ int main(int argc, char** argv)
|
||||
|
||||
args.RegisterConstraint("--width", ParamConstraint::TypeSafety(DATA_TYPE::FLOAT));
|
||||
args.RegisterConstraint("--depth", ParamConstraint::TypeSafety(DATA_TYPE::FLOAT));
|
||||
args.RegisterConstraint("--name", ParamConstraint(true, DATA_TYPE::LIST, { "peter", "hannes" }, true));
|
||||
args.RegisterConstraint("--fruit", ParamConstraint(true, DATA_TYPE::STRING, {}, true));
|
||||
args.RegisterConstraint("--name", ParamConstraint(true, DATA_TYPE::LIST, { "peter", "hannes" }, true, {}));
|
||||
args.RegisterConstraint("--fruit", ParamConstraint(true, DATA_TYPE::STRING, {}, true, {}));
|
||||
|
||||
args.RegisterConstraint("--make-food-delicious", ParamConstraint::Incompatibility("--make-food-disgusting"));
|
||||
|
||||
args.Parse(argc, argv);
|
||||
|
||||
|
@ -524,5 +524,157 @@ namespace TestHazelnupp
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Tests that an HazelnuppConstraintIncompatibleParameters gets raised if a required parameter
|
||||
// is incompatible with another parameter passed alongside
|
||||
// This test will use the single-string-to-initializer-list proxy method
|
||||
TEST_METHOD(Exception_Constraint_Incompatible_Parameters_ProxyMethod)
|
||||
{
|
||||
// Setup
|
||||
ArgList args({
|
||||
"/my/fake/path/wahoo.out",
|
||||
"--make-background-glow",
|
||||
"--make-background-transparent",
|
||||
});
|
||||
|
||||
Assert::ExpectException<HazelnuppConstraintIncompatibleParameters>(
|
||||
[args]
|
||||
{
|
||||
CmdArgsInterface cmdArgsI;
|
||||
cmdArgsI.SetCrashOnFail(false);
|
||||
|
||||
cmdArgsI.RegisterConstraint(
|
||||
"--make-background-glow",
|
||||
ParamConstraint::Incompatibility("--make-background-transparent")
|
||||
);
|
||||
|
||||
cmdArgsI.Parse(C_Ify(args));
|
||||
}
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Tests that an HazelnuppConstraintIncompatibleParameters gets raised if a required parameter
|
||||
// is incompatible with another parameter passed alongside
|
||||
TEST_METHOD(Exception_Constraint_Incompatible_Parameters)
|
||||
{
|
||||
// Setup
|
||||
ArgList args({
|
||||
"/my/fake/path/wahoo.out",
|
||||
"--make-background-glow",
|
||||
"--make-background-transparent",
|
||||
});
|
||||
|
||||
Assert::ExpectException<HazelnuppConstraintIncompatibleParameters>(
|
||||
[args]
|
||||
{
|
||||
CmdArgsInterface cmdArgsI;
|
||||
cmdArgsI.SetCrashOnFail(false);
|
||||
|
||||
cmdArgsI.RegisterConstraint(
|
||||
"--make-background-glow",
|
||||
ParamConstraint::Incompatibility({"--make-background-transparent"})
|
||||
);
|
||||
|
||||
cmdArgsI.Parse(C_Ify(args));
|
||||
}
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Tests that an HazelnuppConstraintIncompatibleParameters gets raised if a required parameter
|
||||
// is incompatible with another parameter passed alongside
|
||||
// This test will register multiple incompatibilities
|
||||
TEST_METHOD(Exception_Constraint_Incompatible_Parameters_Multiple_Incompatibilities)
|
||||
{
|
||||
// Setup
|
||||
ArgList args({
|
||||
"/my/fake/path/wahoo.out",
|
||||
"--make-background-blue",
|
||||
"--make-background-transparent",
|
||||
"--make-background-glow",
|
||||
"--make-background-green",
|
||||
});
|
||||
|
||||
Assert::ExpectException<HazelnuppConstraintIncompatibleParameters>(
|
||||
[args]
|
||||
{
|
||||
CmdArgsInterface cmdArgsI;
|
||||
cmdArgsI.SetCrashOnFail(false);
|
||||
|
||||
cmdArgsI.RegisterConstraint(
|
||||
"--make-background-glow",
|
||||
ParamConstraint::Incompatibility({
|
||||
"--make-background-transparent",
|
||||
"--make-background-green",
|
||||
"--make-background-blue",
|
||||
})
|
||||
);
|
||||
|
||||
cmdArgsI.Parse(C_Ify(args));
|
||||
}
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Tests that an HazelnuppConstraintIncompatibleParameters is NOT raised, if incompatible parameters
|
||||
// are NOT supplied
|
||||
TEST_METHOD(Constraint_Incompatible_Parameters_Are_Not_Incompatible)
|
||||
{
|
||||
// Setup
|
||||
ArgList args({
|
||||
"/my/fake/path/wahoo.out",
|
||||
"--make-background-glow",
|
||||
"--set-food-delicious",
|
||||
});
|
||||
|
||||
{
|
||||
CmdArgsInterface cmdArgsI;
|
||||
cmdArgsI.SetCrashOnFail(false);
|
||||
|
||||
cmdArgsI.RegisterConstraint(
|
||||
"--make-background-glow",
|
||||
ParamConstraint::Incompatibility({ "--make-background-transparent" })
|
||||
);
|
||||
|
||||
cmdArgsI.RegisterConstraint(
|
||||
"--set-food-delicious",
|
||||
ParamConstraint::Incompatibility({ "--set-food-disgusting" })
|
||||
);
|
||||
|
||||
cmdArgsI.Parse(C_Ify(args));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Tests that an HazelnuppConstraintIncompatibleParameters is NOT raised, if the incompatible
|
||||
// paremter IS supplied, but not the one attached to the constraint
|
||||
TEST_METHOD(Constraint_Incompatible_Parameters_Are_Not_Incompatible_Constrained_Parameter_Not_Passed)
|
||||
{
|
||||
// Setup
|
||||
ArgList args({
|
||||
"/my/fake/path/wahoo.out",
|
||||
"--make-background-transparent",
|
||||
"--set-food-delicious",
|
||||
});
|
||||
|
||||
{
|
||||
CmdArgsInterface cmdArgsI;
|
||||
cmdArgsI.SetCrashOnFail(false);
|
||||
|
||||
cmdArgsI.RegisterConstraint(
|
||||
"--make-background-glow",
|
||||
ParamConstraint::Incompatibility({ "--make-background-transparent" })
|
||||
);
|
||||
|
||||
cmdArgsI.Parse(C_Ify(args));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user