Argument Class¶
Class Definition¶
-
template<class
T>
classJSL::Argument: public JSL::ArgumentInterface¶ A class which allows arbitrary template parameters to be read in as command-line arguments or from a configuraiton file using a Name/Value pair system. Upon construction, the Value parameter takes the default value (if provided), until it is overriden by a successful argument/TriggerString match.
Public Functions
-
inline
Argument()¶ Default constructor.
-
inline
Argument(std::string trigger)¶ Constructor initialising the TriggerString. Value is set to uninitialised memory of the Template type.
- Parameters:
trigger – The value of TriggerString, and the “name” of this parameter
-
inline
Argument(T defaultValue, std::string trigger)¶ Constructor which initialises the TriggerString and Value members.
- Parameters:
defaultValue – The initialisation value of Value - overridden if Parse() is called.
trigger – The value of TriggerString, and the “name” of this parameter
-
inline
Argument(T defaultValue, std::string trigger, int argc, char *argv[])¶ Constructor which initialises as per Argument(T defaultValue, std::string trigger), but which also immediately calls ListParse() to check for assignment.
- Parameters:
defaultValue – The initialisation value of Value - overridden if Parse() is called.
trigger – The value of TriggerString, and the “name” of this parameter
argc – The number of commandline arguments
argv[] – the command line list
-
inline
Argument(T defaultValue, std::string trigger, std::string configFile, char configDelimiter)¶ Constructor which initialises as per Argument(T defaultValue, std::string trigger), but which also immediately calls Configure() to check for assignment.
- Parameters:
defaultValue – The initialisation value of Value - overridden if Parse() is called.
trigger – The value of TriggerString, and the “name” of this parameter
configFile – The path to the file to open and parse for configuration data
configDelimiter – The delimiter used to separate Name/Value pairs in the cofiguration file
-
inline virtual void
Configure(std::string configFile, char configDelimiter)¶ Iterate through a configuration file, extracting Name/Value pairs and calling Parse() in them. Each Name/Value pair should be on a new line in the file, and separated by the configDelimiter.
- Parameters:
configFile – The path to the file to open and parse for configuration data
configDelimiter – The delimiter used to separate Name/Value pairs in the cofiguration file
-
inline virtual void
ListParse(int argc, char *argv[])¶ Iterate through the provided commandline args, extracting Name/Value pairs and calling Parse() on them.
- Parameters:
argc – The number of arguments passed to the program
argv[] – The argument list (argv[0] is assumed to be the the name of the program, and is ignored)
-
inline virtual void
Parse(char *name, char *value)¶ Checks if the Name matches the TriggerString. For a successful match, Name must be prefaced by one more dash than found in TriggerString.
- Parameters:
name – The name-string of the Name/Value pair
value – The value-string of the Name/Value pair.
-
inline
operator T()¶ Allow the Argument object to be implicitly casted into the value of Value, and hence treated as an object of the templated type.
-
inline
operator T() const¶ Annoying const version.
Private Functions
-
inline void
CheckForInvalidTriggers()¶ Some Triggers are disallowed - they usually are protected names such as “help”, though other properties may trigger this funciton to throw an error.
-
inline virtual void
StreamTo(std::stringstream &stream, std::string delimiter)¶
-
inline virtual void
AssignValue(const char *value)¶ Virtual override for template-specific AssignValue calls. Most template types will require a custom handler to convert value into the chosen template type — some default ones are provided below.
-
inline void
AssignValue(const char *value) Override of the AssignValue() function for Argument<double> objects. Throws an error if the value is a non-integer, to prevent silent casting/truncation.
-
inline void
AssignValue(const char *value) Override of the AssignValue() function for Argument<double> objects.
-
inline void
AssignValue(const char *value) Override of the AssignValue() function for Argument<std::string> objects.
-
inline void
AssignValue(const char *value) Override of the AssignValue() function for Argument<bool> objects. Accepts only 0/1 as valid bool-strings.
-
inline
Example Usage¶
Consider the following code
#include <iostream>
#include "JSL.h"
int main(int argc, char * argv[])
{
//Explicit initialisation + parsing
JSL::Argument<int> integer1(1,"integer1");
integer1.ListParse(argc,argv);
//Parsing at construction time
JSL::Argument<int> integer2(5,"integer2",argc,argv);
//Parsing from a configuration file
std::string configFile = "config.txt";
char delimiter = ",";
JSL::Argument<double> double1(2.5,"double1",configFile, delimiter);
JSL::Argument<std::string> string1("Goodbye","welcome-string",configFile,delimiter)
//Print the output & Demonstrate the implicit casting ability of the "()" to work on almost everything except strings
std::cout << (std::string)string1 << "\n"; // <- have to explicitly cast here because of char/string shenanigans. Everything else works.
std::cout << integer1 << "\n";
std::cout << integer2 << "\n";
std::cout << double1 << "\n";
std::cout << integer1 + integer2 << "\n";
std::cout << integer1 + integer2 - double1 << "\n";
}
When called in the same directory as the configuration file config.txt
config.txt
integer1, 3
integer2, 23
double1, 101.1
welcome-string, Hello World!
The output is:
> ./argument
Hello World!
integer1 = 1
integer2 = 5
double1 = 101.1
integer1 + integer2 = 6
(integer2 - integer1) * double1 = 404.4
>./argument -integer1 3 -integer2 29 -double1 2.2
Hello World!
integer1 = 3
integer2 = 29
double1 = 101.1
integer1 + integer2 = 32
(integer2 - integer1) * double1 = 2628.6
The wrapper class ArgumentInterface also allows us to build heterogenous arrays which we can loop over to allow for easy & generalised initialisation:
JSL::Argument<int> integer1(1,"integer1");
JSL::Argument<int> integer2(2,"integer2");
JSL::Argument<double> double1(1.5,"double1");
JSL::Argument<double> double2(-2.2,"double2");
JSL::Argument<bool> bool1(true,"bool1");
std::vector<JSL::ArgumentInterface *> arguments = {&integer1, &integer2, &double1, &double2, &bool1};
for (int i = 0; i < arguments.size(); ++i)
{
arguments[i]->ListParse(argc,argv);
}
Adding additional parameters merely requires initialising them and adding them to the arguments list.
Oddities & Notes of Caution¶
In the first example, note that although the -double1 2.2 pair was passed, the code still used the default value double1 = 101.1, as this parameter was only ever assigned to use the configuration file, rather than the command line agruments.
There is no centralised list of assigned TriggerStrings, so it is entirely possible for two different parameters to have the same name. Both will initialise to the same value. Equally, there is no checking if a parameter is assigned to multiple times (either from repeated arguments, or from both the command line and a configuration file). The command line/configuration files are read sequentially from top to bottom.