Implemented constraint for forced types
This commit is contained in:
parent
a2de37264a
commit
9fd183e0cd
@ -4,6 +4,7 @@
|
||||
#include "FloatValue.h"
|
||||
#include "StringValue.h"
|
||||
#include "ListValue.h"
|
||||
#include "HazelnuppException.h"
|
||||
#include "StringTools.h"
|
||||
|
||||
Hazelnupp::Hazelnupp()
|
||||
@ -70,7 +71,10 @@ std::size_t Hazelnupp::ParseNextParameter(const std::size_t parIndex, Parameter*
|
||||
break;
|
||||
}
|
||||
|
||||
Value* parsedVal = ParseValue(values);
|
||||
// Fetch constraint info
|
||||
const ParamConstraint* pcn = GetConstraintForKey(key);
|
||||
|
||||
Value* parsedVal = ParseValue(values, pcn);
|
||||
if (parsedVal != nullptr)
|
||||
{
|
||||
out_Par = new Parameter(key, parsedVal);
|
||||
@ -116,21 +120,38 @@ bool Hazelnupp::HasParam(const std::string& key) const
|
||||
return parameters.find(key) != parameters.end();
|
||||
}
|
||||
|
||||
Value* Hazelnupp::ParseValue(const std::vector<std::string>& values)
|
||||
Value* Hazelnupp::ParseValue(const std::vector<std::string>& values, const ParamConstraint* constraint)
|
||||
{
|
||||
// Constraint values
|
||||
const bool constrainType = (constraint != nullptr) && (constraint->constrainType);
|
||||
|
||||
// Void-type
|
||||
if (values.size() == 0)
|
||||
{
|
||||
return new VoidValue;
|
||||
}
|
||||
|
||||
// Force void type by constraint
|
||||
if ((constrainType) &&
|
||||
(constraint->wantedType == DATA_TYPE::VOID))
|
||||
{
|
||||
return new VoidValue;
|
||||
}
|
||||
|
||||
// List-type
|
||||
else if (values.size() > 1)
|
||||
{
|
||||
// Should the type be something other than list?
|
||||
if ((constrainType) &&
|
||||
(constraint->wantedType != DATA_TYPE::LIST))
|
||||
{
|
||||
throw HazelnutConstraintMissmatch();
|
||||
}
|
||||
|
||||
ListValue* newList = new ListValue();
|
||||
for (const std::string& val : values)
|
||||
{
|
||||
Value* tmp = ParseValue(std::vector<std::string>({ val }));
|
||||
Value* tmp = ParseValue({ val });
|
||||
newList->AddValue(tmp);
|
||||
delete tmp;
|
||||
}
|
||||
@ -142,6 +163,34 @@ Value* Hazelnupp::ParseValue(const std::vector<std::string>& values)
|
||||
|
||||
// String
|
||||
if (!StringTools::IsNumeric(val, true))
|
||||
{
|
||||
// Is the type not supposed to be a string?
|
||||
// void and list are already sorted out
|
||||
if ((constrainType) &&
|
||||
(constraint->wantedType != DATA_TYPE::STRING))
|
||||
{
|
||||
// We can only force a list-value from here
|
||||
if (constraint->wantedType == DATA_TYPE::LIST)
|
||||
{
|
||||
ListValue* list = new ListValue();
|
||||
Value* tmp = ParseValue({ val });
|
||||
list->AddValue(tmp);
|
||||
delete tmp;
|
||||
tmp = nullptr;
|
||||
return list;
|
||||
}
|
||||
// Else it not possible to convert to a numeric
|
||||
else
|
||||
throw HazelnutConstraintMissmatch();
|
||||
}
|
||||
|
||||
return new StringValue(val);
|
||||
}
|
||||
|
||||
// In this case we have a numeric value.
|
||||
// We should still produce a string if requested
|
||||
if ((constrainType) &&
|
||||
(constraint->wantedType == DATA_TYPE::STRING))
|
||||
return new StringValue(val);
|
||||
|
||||
// Numeric
|
||||
@ -149,6 +198,30 @@ Value* Hazelnupp::ParseValue(const std::vector<std::string>& values)
|
||||
long double num;
|
||||
|
||||
if (StringTools::ParseNumber(val, isInt, num))
|
||||
{
|
||||
// Is the type constrained?
|
||||
// (only int and float left)
|
||||
if (constrainType)
|
||||
{
|
||||
// Must it be an integer?
|
||||
if (constraint->wantedType == DATA_TYPE::INT)
|
||||
return new IntValue((long long int)num);
|
||||
// Must it be a floating point?
|
||||
else if (constraint->wantedType == DATA_TYPE::FLOAT)
|
||||
return new FloatValue(num);
|
||||
// Else it must be a List
|
||||
else
|
||||
{
|
||||
ListValue* list = new ListValue();
|
||||
Value* tmp = ParseValue({ val });
|
||||
list->AddValue(tmp);
|
||||
delete tmp;
|
||||
tmp = nullptr;
|
||||
return list;
|
||||
}
|
||||
}
|
||||
// Type is not constrained
|
||||
else
|
||||
{
|
||||
// Integer
|
||||
if (isInt)
|
||||
@ -157,6 +230,7 @@ Value* Hazelnupp::ParseValue(const std::vector<std::string>& values)
|
||||
// Double
|
||||
return new FloatValue(num);
|
||||
}
|
||||
}
|
||||
|
||||
// Failed
|
||||
return nullptr;
|
||||
@ -187,3 +261,22 @@ bool Hazelnupp::HasAbbreviation(const std::string& abbrev) const
|
||||
{
|
||||
return abbreviations.find(abbrev) != abbreviations.end();
|
||||
}
|
||||
|
||||
void Hazelnupp::AddConstraints(const std::vector<ParamConstraint>& constraints)
|
||||
{
|
||||
for (const ParamConstraint& pc : constraints)
|
||||
this->constraints.insert(std::pair<std::string, ParamConstraint>(
|
||||
pc.key,
|
||||
pc
|
||||
));
|
||||
}
|
||||
|
||||
const ParamConstraint* Hazelnupp::GetConstraintForKey(const std::string& key) const
|
||||
{
|
||||
const auto constraint = constraints.find(key);
|
||||
|
||||
if (constraint == constraints.end())
|
||||
return nullptr;
|
||||
|
||||
return &constraint->second;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "Parameter.h"
|
||||
#include "ParamConstraint.h"
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
@ -33,6 +34,8 @@ public:
|
||||
//! Will check wether or not an abbreviation is registered
|
||||
bool HasAbbreviation(const std::string& abbrev) const;
|
||||
|
||||
void AddConstraints(const std::vector<ParamConstraint>& constraints);
|
||||
|
||||
private:
|
||||
//! Will translate the c-like args to an std::vector
|
||||
void PopulateRawArgs(const int argc, const char* const* argv);
|
||||
@ -44,7 +47,13 @@ private:
|
||||
std::size_t ParseNextParameter(const std::size_t parIndex, Parameter*& out_Par);
|
||||
|
||||
//! Will convert a vector of string-values to an actual Value
|
||||
Value* ParseValue(const std::vector<std::string>& values);
|
||||
Value* ParseValue(const std::vector<std::string>& values, const ParamConstraint* constraint = nullptr);
|
||||
|
||||
//! Will apply the loaded constraints on the loaded values.
|
||||
void ApplyConstraints();
|
||||
|
||||
//! Will return a pointer to a paramConstraint given a key. If there is no, it returns nullptr
|
||||
const ParamConstraint* GetConstraintForKey(const std::string& key) const;
|
||||
|
||||
std::string executableName; //! The path of the executable. Always argv[0]
|
||||
std::unordered_map<std::string, Parameter*> parameters;
|
||||
@ -52,5 +61,8 @@ private:
|
||||
// These are abbreviations. Like, -f for --force.
|
||||
std::unordered_map<std::string, std::string> abbreviations;
|
||||
|
||||
// Parameter constraints, mapped to keys
|
||||
std::unordered_map<std::string, ParamConstraint> constraints;
|
||||
|
||||
std::vector<std::string> rawArgs;
|
||||
};
|
||||
|
@ -153,8 +153,10 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="FloatValue.h" />
|
||||
<ClInclude Include="Hazelnupp.h" />
|
||||
<ClInclude Include="HazelnuppException.h" />
|
||||
<ClInclude Include="IntValue.h" />
|
||||
<ClInclude Include="ListValue.h" />
|
||||
<ClInclude Include="ParamConstraint.h" />
|
||||
<ClInclude Include="Parameter.h" />
|
||||
<ClInclude Include="DataType.h" />
|
||||
<ClInclude Include="StringTools.h" />
|
||||
|
@ -77,5 +77,11 @@
|
||||
<ClInclude Include="StringTools.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ParamConstraint.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HazelnuppException.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
5
Hazelnupp/HazelnuppException.h
Normal file
5
Hazelnupp/HazelnuppException.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#include <stdexcept>
|
||||
|
||||
class HazelnutException : public std::exception {};
|
||||
class HazelnutConstraintMissmatch : public HazelnutException {};
|
25
Hazelnupp/ParamConstraint.h
Normal file
25
Hazelnupp/ParamConstraint.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "DataType.h"
|
||||
#include <string>
|
||||
|
||||
struct ParamConstraint
|
||||
{
|
||||
public:
|
||||
//! The key of the parameter to constrain
|
||||
std::string key;
|
||||
|
||||
//! Should this parameter be forced to be of a certain type?
|
||||
//! Remember to set `constrainTo` to the wanted type
|
||||
bool constrainType = false;
|
||||
|
||||
//! Constrain the parameter to this value. Requires `constrainType` to be set to true.
|
||||
DATA_TYPE wantedType;
|
||||
|
||||
//! The default value for this parameter.
|
||||
//! Gets applied if this parameter was not given.
|
||||
std::string defaultValue;
|
||||
|
||||
//! If set to true, and no default value set,
|
||||
//! an error will be produced if this parameter is not supplied by the user.
|
||||
bool required = false;
|
||||
};
|
@ -9,7 +9,7 @@ int main(int argc, char** argv)
|
||||
std::vector<const char*> testArgv = {
|
||||
"meinpfad",
|
||||
"-w",
|
||||
"123",
|
||||
"-99",
|
||||
"--alfred",
|
||||
"apfel",
|
||||
"banane",
|
||||
@ -24,6 +24,16 @@ int main(int argc, char** argv)
|
||||
|
||||
Hazelnupp args;
|
||||
|
||||
ParamConstraint pc;
|
||||
pc.key = "--word";
|
||||
pc.constrainType = true;
|
||||
pc.wantedType = DATA_TYPE::INT;
|
||||
pc.required = true;
|
||||
|
||||
args.AddConstraints({
|
||||
pc
|
||||
});
|
||||
|
||||
args.RegisterAbbreviation("-w", "--word");
|
||||
|
||||
args.Parse(testArgv.size(), testArgv.data());
|
||||
@ -31,7 +41,7 @@ int main(int argc, char** argv)
|
||||
|
||||
if (args.HasParam("--word"))
|
||||
{
|
||||
std::cout << args["--word"]->GetString() << std::endl;
|
||||
std::cout << *args["--word"] << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user