Implemented constraint for forced types
This commit is contained in:
parent
a2de37264a
commit
9fd183e0cd
@ -4,6 +4,7 @@
|
|||||||
#include "FloatValue.h"
|
#include "FloatValue.h"
|
||||||
#include "StringValue.h"
|
#include "StringValue.h"
|
||||||
#include "ListValue.h"
|
#include "ListValue.h"
|
||||||
|
#include "HazelnuppException.h"
|
||||||
#include "StringTools.h"
|
#include "StringTools.h"
|
||||||
|
|
||||||
Hazelnupp::Hazelnupp()
|
Hazelnupp::Hazelnupp()
|
||||||
@ -70,7 +71,10 @@ std::size_t Hazelnupp::ParseNextParameter(const std::size_t parIndex, Parameter*
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* parsedVal = ParseValue(values);
|
// Fetch constraint info
|
||||||
|
const ParamConstraint* pcn = GetConstraintForKey(key);
|
||||||
|
|
||||||
|
Value* parsedVal = ParseValue(values, pcn);
|
||||||
if (parsedVal != nullptr)
|
if (parsedVal != nullptr)
|
||||||
{
|
{
|
||||||
out_Par = new Parameter(key, parsedVal);
|
out_Par = new Parameter(key, parsedVal);
|
||||||
@ -116,21 +120,38 @@ bool Hazelnupp::HasParam(const std::string& key) const
|
|||||||
return parameters.find(key) != parameters.end();
|
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
|
// Void-type
|
||||||
if (values.size() == 0)
|
if (values.size() == 0)
|
||||||
{
|
{
|
||||||
return new VoidValue;
|
return new VoidValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force void type by constraint
|
||||||
|
if ((constrainType) &&
|
||||||
|
(constraint->wantedType == DATA_TYPE::VOID))
|
||||||
|
{
|
||||||
|
return new VoidValue;
|
||||||
|
}
|
||||||
|
|
||||||
// List-type
|
// List-type
|
||||||
else if (values.size() > 1)
|
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();
|
ListValue* newList = new ListValue();
|
||||||
for (const std::string& val : values)
|
for (const std::string& val : values)
|
||||||
{
|
{
|
||||||
Value* tmp = ParseValue(std::vector<std::string>({ val }));
|
Value* tmp = ParseValue({ val });
|
||||||
newList->AddValue(tmp);
|
newList->AddValue(tmp);
|
||||||
delete tmp;
|
delete tmp;
|
||||||
}
|
}
|
||||||
@ -142,6 +163,34 @@ Value* Hazelnupp::ParseValue(const std::vector<std::string>& values)
|
|||||||
|
|
||||||
// String
|
// String
|
||||||
if (!StringTools::IsNumeric(val, true))
|
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);
|
return new StringValue(val);
|
||||||
|
|
||||||
// Numeric
|
// Numeric
|
||||||
@ -149,6 +198,30 @@ Value* Hazelnupp::ParseValue(const std::vector<std::string>& values)
|
|||||||
long double num;
|
long double num;
|
||||||
|
|
||||||
if (StringTools::ParseNumber(val, isInt, 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
|
// Integer
|
||||||
if (isInt)
|
if (isInt)
|
||||||
@ -157,6 +230,7 @@ Value* Hazelnupp::ParseValue(const std::vector<std::string>& values)
|
|||||||
// Double
|
// Double
|
||||||
return new FloatValue(num);
|
return new FloatValue(num);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Failed
|
// Failed
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -187,3 +261,22 @@ bool Hazelnupp::HasAbbreviation(const std::string& abbrev) const
|
|||||||
{
|
{
|
||||||
return abbreviations.find(abbrev) != abbreviations.end();
|
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
|
#pragma once
|
||||||
#include "Parameter.h"
|
#include "Parameter.h"
|
||||||
|
#include "ParamConstraint.h"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -33,6 +34,8 @@ public:
|
|||||||
//! Will check wether or not an abbreviation is registered
|
//! Will check wether or not an abbreviation is registered
|
||||||
bool HasAbbreviation(const std::string& abbrev) const;
|
bool HasAbbreviation(const std::string& abbrev) const;
|
||||||
|
|
||||||
|
void AddConstraints(const std::vector<ParamConstraint>& constraints);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Will translate the c-like args to an std::vector
|
//! Will translate the c-like args to an std::vector
|
||||||
void PopulateRawArgs(const int argc, const char* const* argv);
|
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);
|
std::size_t ParseNextParameter(const std::size_t parIndex, Parameter*& out_Par);
|
||||||
|
|
||||||
//! Will convert a vector of string-values to an actual Value
|
//! 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::string executableName; //! The path of the executable. Always argv[0]
|
||||||
std::unordered_map<std::string, Parameter*> parameters;
|
std::unordered_map<std::string, Parameter*> parameters;
|
||||||
@ -52,5 +61,8 @@ private:
|
|||||||
// These are abbreviations. Like, -f for --force.
|
// These are abbreviations. Like, -f for --force.
|
||||||
std::unordered_map<std::string, std::string> abbreviations;
|
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;
|
std::vector<std::string> rawArgs;
|
||||||
};
|
};
|
||||||
|
@ -153,8 +153,10 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="FloatValue.h" />
|
<ClInclude Include="FloatValue.h" />
|
||||||
<ClInclude Include="Hazelnupp.h" />
|
<ClInclude Include="Hazelnupp.h" />
|
||||||
|
<ClInclude Include="HazelnuppException.h" />
|
||||||
<ClInclude Include="IntValue.h" />
|
<ClInclude Include="IntValue.h" />
|
||||||
<ClInclude Include="ListValue.h" />
|
<ClInclude Include="ListValue.h" />
|
||||||
|
<ClInclude Include="ParamConstraint.h" />
|
||||||
<ClInclude Include="Parameter.h" />
|
<ClInclude Include="Parameter.h" />
|
||||||
<ClInclude Include="DataType.h" />
|
<ClInclude Include="DataType.h" />
|
||||||
<ClInclude Include="StringTools.h" />
|
<ClInclude Include="StringTools.h" />
|
||||||
|
@ -77,5 +77,11 @@
|
|||||||
<ClInclude Include="StringTools.h">
|
<ClInclude Include="StringTools.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="ParamConstraint.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="HazelnuppException.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</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 = {
|
std::vector<const char*> testArgv = {
|
||||||
"meinpfad",
|
"meinpfad",
|
||||||
"-w",
|
"-w",
|
||||||
"123",
|
"-99",
|
||||||
"--alfred",
|
"--alfred",
|
||||||
"apfel",
|
"apfel",
|
||||||
"banane",
|
"banane",
|
||||||
@ -24,6 +24,16 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
Hazelnupp args;
|
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.RegisterAbbreviation("-w", "--word");
|
||||||
|
|
||||||
args.Parse(testArgv.size(), testArgv.data());
|
args.Parse(testArgv.size(), testArgv.data());
|
||||||
@ -31,7 +41,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
if (args.HasParam("--word"))
|
if (args.HasParam("--word"))
|
||||||
{
|
{
|
||||||
std::cout << args["--word"]->GetString() << std::endl;
|
std::cout << *args["--word"] << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user