commit
24ba96a17f
339 changed files with 26058 additions and 0 deletions
@ -0,0 +1,581 @@ |
||||
#include "argumentparser.h" |
||||
#include "failure.h" |
||||
#include "../conversion/stringconversion.h" |
||||
#include "../misc/random.h" |
||||
|
||||
#include <algorithm> |
||||
#include <vector> |
||||
#include <iostream> |
||||
#include <sstream> |
||||
#include <stdexcept> |
||||
|
||||
using namespace std; |
||||
using namespace std::placeholders; |
||||
|
||||
/*!
|
||||
\namespace ApplicationUtilities |
||||
\brief Contains currently only ArgumentParser and related classes. |
||||
*/ |
||||
namespace ApplicationUtilities { |
||||
|
||||
/*!
|
||||
* \class ApplicationUtilities::Argument |
||||
* \brief The Argument class is a wrapper for command line argument information. |
||||
* |
||||
* Instaces of the Argument class are used as definition when parsing command line |
||||
* arguments. Arguments can be assigned to an ArgumentParser using |
||||
* ArgumentParser::setMainArguments() and to another Argument instance using |
||||
* Argument::setSecondaryArguments(). |
||||
*/ |
||||
|
||||
/*!
|
||||
* Constructs an Argument with the given \a name, \a abbreviation and \a description. |
||||
* |
||||
* The \a name and the abbreviation mustn't contain any whitespaces. |
||||
* The \a name mustn't be empty. The \a abbreviation and the \a description might be empty. |
||||
*/ |
||||
Argument::Argument(const std::string &name, const std::string abbreviation, const std::string &description) : |
||||
m_required(false), |
||||
m_combinable(false), |
||||
m_implicit(false), |
||||
m_requiredValueCount(0), |
||||
m_default(false), |
||||
m_present(false), |
||||
m_isMainArg(false) |
||||
{ |
||||
setName(name); |
||||
setAbbreviation(abbreviation); |
||||
setDescription(description); |
||||
} |
||||
|
||||
/*!
|
||||
* Constructs an Argument with the given \a name, \a abbreviation and \a description. |
||||
* The \a name and the abbreviation mustn't contain any whitespaces. |
||||
* The \a name mustn't be empty. The \a abbreviation and the \a description might be empty. |
||||
*/ |
||||
Argument::Argument(const char *name, const char *abbreviation, const char *description) : |
||||
m_required(false), |
||||
m_combinable(false), |
||||
m_implicit(false), |
||||
m_requiredValueCount(0), |
||||
m_default(false), |
||||
m_present(false), |
||||
m_isMainArg(false) |
||||
{ |
||||
setName(name); |
||||
setAbbreviation(abbreviation); |
||||
setDescription(description); |
||||
} |
||||
|
||||
/*!
|
||||
* Destroys the Argument. |
||||
*/ |
||||
Argument::~Argument() |
||||
{} |
||||
|
||||
///*!
|
||||
// * \brief Checks whether the argument is ambigious.
|
||||
// * \returns Returns zero if the argument is not ambigious. Returns 1 if the name
|
||||
// * is ambiguous and 2 if the abbreviation is ambiguous.
|
||||
// */
|
||||
//unsigned char Argument::isAmbiguous(const ArgumentParser &parser) const
|
||||
//{
|
||||
// function<unsigned char (const ArgumentVector &args, const Argument *toCheck)> check;
|
||||
// check = [&check] (const ArgumentVector &args, const Argument *toCheck) -> unsigned char {
|
||||
// for(const auto *arg : args) {
|
||||
// if(arg != toCheck) {
|
||||
// if(!toCheck->name().empty() && arg->name() == toCheck->name()) {
|
||||
// return 1;
|
||||
// } else if(!toCheck->abbreviation().empty() && arg->abbreviation() == toCheck->abbreviation()) {
|
||||
// return 2;
|
||||
// }
|
||||
// }
|
||||
// if(auto res = check(arg->parents(), toCheck)) {
|
||||
// return res;
|
||||
// }
|
||||
// }
|
||||
// return 0;
|
||||
// };
|
||||
// if(auto res = check(parser.mainArguments(), this)) {
|
||||
// return res;
|
||||
// }
|
||||
// return check(parents(), this);
|
||||
//}
|
||||
|
||||
/*!
|
||||
* Appends the name, the abbreviation and the description of the Argument |
||||
* to the give ostream. |
||||
*/ |
||||
void Argument::printInfo(ostream &os, unsigned char indentionLevel) const |
||||
{ |
||||
for(unsigned char i = 0; i < indentionLevel; ++i) os << " "; |
||||
if(!name().empty()) { |
||||
os << "--" << name(); |
||||
} |
||||
if(!name().empty() && !abbreviation().empty()) { |
||||
os << ", "; |
||||
} |
||||
if(!abbreviation().empty()) { |
||||
os << "-" << abbreviation(); |
||||
} |
||||
if(requiredValueCount() > 0) { |
||||
int valueNamesPrint = 0; |
||||
for(auto i = valueNames().cbegin(), end = valueNames().cend(); i != end && valueNamesPrint < requiredValueCount(); ++i) { |
||||
os << " [" << *i << "]"; |
||||
++valueNamesPrint; |
||||
} |
||||
for(; valueNamesPrint < requiredValueCount(); ++valueNamesPrint) { |
||||
os << " [value " << (valueNamesPrint + 1) << "]"; |
||||
} |
||||
} else if(requiredValueCount() < 0) { |
||||
for(auto i = valueNames().cbegin(), end = valueNames().cend(); i != end; ++i) { |
||||
os << " [" << *i << "]"; |
||||
} |
||||
os << " ..."; |
||||
} |
||||
++indentionLevel; |
||||
if(!description().empty()) { |
||||
os << endl; |
||||
for(unsigned char i = 0; i < indentionLevel; ++i) os << " "; |
||||
os << description(); |
||||
} |
||||
if(isRequired()) { |
||||
os << endl; |
||||
for(unsigned char i = 0; i < indentionLevel; ++i) os << " "; |
||||
os << "This argument is required."; |
||||
} |
||||
os << endl; |
||||
for(const Argument *arg : secondaryArguments()) { |
||||
arg->printInfo(os, indentionLevel + 1); |
||||
} |
||||
} |
||||
|
||||
/*!
|
||||
* This function return the first present and uncombinable argument of the given list of arguments. |
||||
* The Argument \a except will be ignored. |
||||
*/ |
||||
Argument *firstPresentUncombinableArg(const ArgumentVector &args, const Argument *except) |
||||
{ |
||||
for(Argument *arg : args) { |
||||
if(arg != except && arg->isPresent() && !arg->isCombinable()) { |
||||
return arg; |
||||
} |
||||
} |
||||
return nullptr; |
||||
} |
||||
|
||||
/*!
|
||||
* Sets the secondary arguments for this arguments. The given arguments will be considered as |
||||
* secondary arguments of this argument by the ArgumentParser. This means that the parser |
||||
* will complain if these arguments are given, but not their parent. If secondary arguments are |
||||
* labeled as mandatory their parent is also mandatory. |
||||
* |
||||
* The Argument does not take ownership. Do not destroy the given arguments as long as they are |
||||
* used as secondary arguments. |
||||
* |
||||
* \sa secondaryArguments() |
||||
* \sa hasSecondaryArguments() |
||||
*/ |
||||
void Argument::setSecondaryArguments(const ArgumentInitializerList &secondaryArguments) |
||||
{ |
||||
// remove this argument from the parents list of the previous secondary arguments
|
||||
for(Argument *arg : m_secondaryArgs) { |
||||
arg->m_parents.erase(remove(arg->m_parents.begin(), arg->m_parents.end(), this), arg->m_parents.end()); |
||||
} |
||||
// assign secondary arguments
|
||||
m_secondaryArgs.assign(secondaryArguments); |
||||
// add this argument to the parents list of the assigned secondary arguments
|
||||
// and set the parser
|
||||
for(Argument *arg : m_secondaryArgs) { |
||||
if(find(arg->m_parents.cbegin(), arg->m_parents.cend(), this) == arg->m_parents.cend()) { |
||||
arg->m_parents.push_back(this); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/*!
|
||||
* Returns the names of the parents in the form "parent1", "parent2, "parent3", ... |
||||
* Returns an empty string if this Argument has no parents. |
||||
* \sa parents() |
||||
*/ |
||||
string Argument::parentNames() const |
||||
{ |
||||
string res; |
||||
if(m_parents.size()) { |
||||
vector<string> names; |
||||
names.reserve(m_parents.size()); |
||||
for(const Argument *parent : m_parents) { |
||||
names.push_back(parent->name()); |
||||
} |
||||
res.assign(ConversionUtilities::joinStrings(names, ", ")); |
||||
} |
||||
return res; |
||||
} |
||||
|
||||
/*!
|
||||
* Returns true if at least one of the parents is present. |
||||
* Returns false if this argument has no parents or none of its parents is present. |
||||
*/ |
||||
bool Argument::isParentPresent() const |
||||
{ |
||||
for(Argument *parent : m_parents) { |
||||
if(parent->isPresent()) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/*!
|
||||
* Checks if this arguments conflicts with other arguments. If the argument is in conflict |
||||
* with an other argument this argument will be returned. Otherwise nullptr will be returned. |
||||
*/ |
||||
Argument *Argument::conflictsWithArgument() const |
||||
{ |
||||
if(!isCombinable() && isPresent()) { |
||||
for(Argument *parent : m_parents) { |
||||
for(Argument *sibling : parent->secondaryArguments()) { |
||||
if(sibling != this && sibling->isPresent() && !sibling->isCombinable()) { |
||||
return sibling; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return nullptr; |
||||
} |
||||
|
||||
/*!
|
||||
* \class ApplicationUtilities::ArgumentParser |
||||
* \brief The ArgumentParser class provides a means for handling command line arguments. |
||||
* |
||||
* To setup the parser create instances of ApplicationUtilities::Argument to define a |
||||
* set of known arguments and assign these to the parser using setMainArguments(). |
||||
* |
||||
* To invoke parsing call parseArgs(). The parser will verify the previously |
||||
* assigned definitions (and might throw std::invalid_argument) and then parse the |
||||
* given command line arguments according the definitions (and might throw |
||||
* ApplicationUtilities::Failure). |
||||
*/ |
||||
|
||||
/*!
|
||||
* Constructs a new ArgumentParser. |
||||
*/ |
||||
ArgumentParser::ArgumentParser() : |
||||
m_actualArgc(0), |
||||
m_ignoreUnknownArgs(false) |
||||
{} |
||||
|
||||
/*!
|
||||
* Sets the main arguments for the parser. The parser will use these argument definitions |
||||
* to when parsing the command line arguments and when printing help information. |
||||
* |
||||
* The parser does not take ownership. Do not destroy the arguments as long as they are used as |
||||
* main arguments. |
||||
*/ |
||||
void ArgumentParser::setMainArguments(const ArgumentInitializerList &mainArguments) |
||||
{ |
||||
for(Argument *arg : mainArguments) { |
||||
arg->m_isMainArg = true; |
||||
} |
||||
m_mainArgs.assign(mainArguments); |
||||
} |
||||
|
||||
/*!
|
||||
* Prints help information for all main arguments which have been set using setMainArguments(). |
||||
*/ |
||||
void ArgumentParser::printHelp(ostream &os) const |
||||
{ |
||||
if(!m_mainArgs.size()) { |
||||
return; |
||||
} |
||||
os << "Available arguments:\n"; |
||||
for(const Argument *arg : m_mainArgs) { |
||||
arg->printInfo(os); |
||||
} |
||||
} |
||||
|
||||
/*!
|
||||
* Returns the first argument definition which matches the predicate. |
||||
* The search includes all assigned main argument definitions and their sub arguments. |
||||
*/ |
||||
Argument *ArgumentParser::findArg(const ArgumentPredicate &predicate) const |
||||
{ |
||||
return findArg(m_mainArgs, predicate); |
||||
} |
||||
|
||||
/*!
|
||||
* Returns the first argument definition which matches the predicate. |
||||
* The search includes all provided \a arguments and their sub arguments. |
||||
*/ |
||||
Argument *ArgumentParser::findArg(const ArgumentVector &arguments, const ArgumentPredicate &predicate) |
||||
{ |
||||
for(Argument *arg : arguments) { |
||||
if(predicate(arg)) { |
||||
return arg; // argument matches
|
||||
} else if(Argument *subarg = findArg(arg->secondaryArguments(), predicate)) { |
||||
return subarg; // a secondary argument matches
|
||||
} |
||||
} |
||||
return nullptr; // no argument matches
|
||||
} |
||||
|
||||
/*!
|
||||
* This method is used to verify the setup of the command line parser before parsing. |
||||
* |
||||
* This function will throw std::invalid_argument when a mismatch is detected: |
||||
* - An argument is used as main argument and as sub argument at the same time. |
||||
* - An argument abbreviation is used more then once. |
||||
* - An argument name is used more then once. |
||||
* If none of these conditions are met, this method will do nothing. |
||||
* |
||||
* \remarks Usually you don't need to call this function manually because it is called by |
||||
* parse() automatically befor the parsing is performed. |
||||
*/ |
||||
void ArgumentParser::verifySetup() const |
||||
{ |
||||
vector<Argument *> verifiedArgs; |
||||
vector<string> abbreviations; |
||||
vector<string> names; |
||||
function<void (const ArgumentVector &args)> checkArguments; |
||||
checkArguments = [&verifiedArgs, &abbreviations, &names, &checkArguments, this] (const ArgumentVector &args) { |
||||
for(Argument *arg : args) { |
||||
if(find(verifiedArgs.cbegin(), verifiedArgs.cend(), arg) != verifiedArgs.cend()) |
||||
continue; // do not verify the same argument twice
|
||||
if(arg->isMainArgument() && arg->parents().size()) |
||||
throw invalid_argument("Argument \"" + arg->name() + "\" can not be used as main argument and sub argument at the same time."); |
||||
if(!arg->abbreviation().empty() && find(abbreviations.cbegin(), abbreviations.cend(), arg->abbreviation()) != abbreviations.cend()) |
||||
throw invalid_argument("Abbreviation \"" + arg->abbreviation() + "\" has been used more then once."); |
||||
if(find(names.cbegin(), names.cend(), arg->name()) != names.cend()) |
||||
throw invalid_argument("Name \"" + arg->name() + "\" has been used more then once."); |
||||
if(arg->isDefault() && arg->requiredValueCount() > 0 && arg->defaultValues().size() < static_cast<size_t>(arg->requiredValueCount())) |
||||
throw invalid_argument("Default argument \"" + arg->name() + "\" doesn't provide the required number of default values."); |
||||
abbreviations.push_back(arg->abbreviation()); |
||||
names.push_back(arg->name()); |
||||
verifiedArgs.push_back(arg); |
||||
checkArguments(arg->secondaryArguments()); |
||||
} |
||||
}; |
||||
checkArguments(m_mainArgs); |
||||
} |
||||
|
||||
/*!
|
||||
* This method invokes verifySetup() before parsing. See its do documentation for more |
||||
* information about execptions that might be thrown to indicate an invalid setup of the parser. |
||||
* |
||||
* If the parser is setup properly this method will parse the given command line arguments using |
||||
* the previsously set argument definitions. |
||||
* If one of the previsously defined arguments has been found, its present flag will be set to true |
||||
* and the parser reads all values tied to this argument. |
||||
* If an argument has been found which does not match any of the previous definitions it will be |
||||
* considered as unknown. |
||||
* If the given command line arguments are not valid according the defined arguments an |
||||
* Failure will be thrown. |
||||
*/ |
||||
void ArgumentParser::parseArgs(int argc, char *argv[]) |
||||
{ |
||||
// initiate parser
|
||||
verifySetup(); |
||||
m_actualArgc = 0; // reset actual agument count
|
||||
unsigned int actualArgc = 0; |
||||
int valuesToRead = 0; |
||||
// read current directory
|
||||
if(argc >= 1) { |
||||
m_currentDirectory = string(*argv); |
||||
} else { |
||||
m_currentDirectory.clear(); |
||||
} |
||||
// parse given arguments
|
||||
if(argc >= 2) { |
||||
Argument *currentArg = nullptr; |
||||
// iterate through given arguments
|
||||
for(char **i = argv + 1, ** end = argv + argc; i != end; ++i) { |
||||
string givenArg(*i); // convert argument to string
|
||||
if(!givenArg.empty()) { // skip empty entries
|
||||
if(valuesToRead <= 0 && givenArg.size() > 1 && givenArg.front() == '-') { |
||||
// we have no values left to read and the given arguments starts with '-'
|
||||
// -> the next "value" is a main argument or a sub argument
|
||||
ArgumentPredicate pred; |
||||
string givenId; |
||||
size_t equationPos = givenArg.find('='); |
||||
if(givenArg.size() > 2 && givenArg[1] == '-') { |
||||
// the argument starts with '--'
|
||||
// -> the full argument name has been provided
|
||||
givenId = givenArg.substr(2, equationPos - 2); |
||||
pred = [&givenId, equationPos] (Argument *arg) { |
||||
return arg->name() == givenId; |
||||
}; |
||||
} else { |
||||
// the argument starts with a single '-'
|
||||
// -> the abbreviation has been provided
|
||||
givenId = givenArg.substr(1, equationPos - 1); |
||||
pred = [&givenId, equationPos] (Argument *arg) { |
||||
return arg->abbreviation() == givenId; |
||||
}; |
||||
} |
||||
// find the corresponding instande of the Argument class
|
||||
currentArg = findArg(pred); |
||||
if(currentArg) { |
||||
// the corresponding instance of Argument class has been found
|
||||
if(currentArg->m_present) { |
||||
// the argument has been provided more then once
|
||||
throw Failure("The argument \"" + currentArg->name() + "\" has been given more then one time."); |
||||
} else { |
||||
// set present flag of argument
|
||||
currentArg->m_present = true; |
||||
++actualArgc; // we actually found an argument
|
||||
// now we might need to read values tied to that argument
|
||||
valuesToRead = currentArg->requiredValueCount(); |
||||
if(equationPos != string::npos) { |
||||
// a value has been specified using the --argument=value syntax
|
||||
string value = givenArg.substr(equationPos + 1); |
||||
if(valuesToRead != 0) { |
||||
currentArg->m_values.push_back(value); |
||||
if(valuesToRead > 0) { |
||||
--valuesToRead; |
||||
} |
||||
} else { |
||||
throw Failure("Invalid extra information \"" + value + "\" (specified using \"--argument=value\" syntax) for the argument \"" + currentArg->name() + "\" given."); |
||||
} |
||||
} |
||||
} |
||||
} else { |
||||
// the given argument seems to be unknown
|
||||
if(valuesToRead < 0) { |
||||
// we have a variable number of values to expect -> treat "unknown argument" as value
|
||||
goto readValue; |
||||
} else { |
||||
// we have no more values to expect so we need to complain about the unknown argument
|
||||
goto invalidArg; |
||||
} |
||||
} |
||||
} else { |
||||
readValue: |
||||
if(!currentArg) { |
||||
// we have not parsed an argument before -> check if there's an implicit argument definition
|
||||
for(Argument *arg : m_mainArgs) { |
||||
if(!arg->isPresent() && arg->isImplicit()) { |
||||
// set present flag of argument
|
||||
arg->m_present = true; |
||||
++actualArgc; // we actually found an argument
|
||||
// now we might need to read values tied to that argument
|
||||
valuesToRead = arg->requiredValueCount(); |
||||
currentArg = arg; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
if(currentArg) { |
||||
// check if the given value is tied to the most recently parsed argument
|
||||
if(valuesToRead == 0) { |
||||
throw Failure("Invalid extra information \"" + givenArg + "\" for the argument \"" + currentArg->name() + "\" given."); |
||||
} else if(valuesToRead < 0) { |
||||
currentArg->m_values.push_back(givenArg); |
||||
} else { |
||||
currentArg->m_values.push_back(givenArg); |
||||
--valuesToRead; // one value less to be read
|
||||
} |
||||
} else { |
||||
// there is no implicit argument definition -> the "value" has to be an argument
|
||||
// but does not start with '-' or '--'
|
||||
invalidArg: |
||||
string msg("The given argument \"" + givenArg + "\" is unknown."); |
||||
if(m_ignoreUnknownArgs) { |
||||
cout << msg << " It will be ignored." << endl; |
||||
} else { |
||||
throw Failure(msg); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
// function for iterating through all arguments
|
||||
function<void(Argument *, const ArgumentVector &, const function<void (Argument *, Argument *)> &)> foreachArg; |
||||
foreachArg = [&foreachArg] (Argument *parent, const ArgumentVector &args, const function<void (Argument *, Argument *)> &proc) { |
||||
for(Argument *arg : args) { |
||||
proc(parent, arg); |
||||
foreachArg(arg, arg->secondaryArguments(), proc); |
||||
} |
||||
}; |
||||
// iterate actually through all arguments using previously defined function to check gathered arguments
|
||||
foreachArg(nullptr, m_mainArgs, [this] (Argument *parent, Argument *arg) { |
||||
if(arg->isPresent()) { |
||||
if(!arg->isMainArgument() && arg->parents().size() && !arg->isParentPresent()) { |
||||
if(arg->parents().size() > 1) { |
||||
throw Failure("The argument \"" + arg->name() + "\" needs to be used together with one the following arguments: " + arg->parentNames()); |
||||
} else { |
||||
throw Failure("The argument \"" + arg->name() + "\" needs to be used together with the argument \"" + arg->parents().front()->name() + "\"."); |
||||
} |
||||
} |
||||
Argument *conflictingArgument = nullptr; |
||||
if(arg->isMainArgument()) { |
||||
if(!arg->isCombinable() && arg->isPresent()) { |
||||
conflictingArgument = firstPresentUncombinableArg(m_mainArgs, arg); |
||||
} |
||||
} else { |
||||
conflictingArgument = arg->conflictsWithArgument(); |
||||
} |
||||
if(conflictingArgument) { |
||||
throw Failure("The argument \"" + conflictingArgument->name() + "\" can not be combined with \"" + arg->name() + "\"."); |
||||
} |
||||
if(!arg->allRequiredValuesPresent()) { |
||||
stringstream ss(stringstream::in | stringstream::out); |
||||
ss << "Not all required information for the given argument \"" << arg->name() << "\" provided. You have to give the following information:"; |
||||
int valueNamesPrint = 0; |
||||
for(const auto &name : arg->m_valueNames) { |
||||
ss << "\n" << name; |
||||
++valueNamesPrint; |
||||
} |
||||
while(valueNamesPrint < arg->m_requiredValueCount) { |
||||
ss << "\nvalue " << (++valueNamesPrint); |
||||
} |
||||
throw Failure(ss.str()); |
||||
} |
||||
} else { // argument not present
|
||||
// the argument might be flagged as present if its a default argument
|
||||
if(arg->isDefault() && (arg->isMainArgument() || (parent && parent->isPresent()))) { |
||||
arg->m_present = true; |
||||
if(firstPresentUncombinableArg(arg->isMainArgument() ? m_mainArgs : parent->secondaryArguments(), arg)) { |
||||
arg->m_present = false; |
||||
} |
||||
} |
||||
// throw an error if mandatory argument is not present
|
||||
if(!arg->isPresent() && (arg->isRequired() && (arg->isMainArgument() || (parent && parent->isPresent())))) { |
||||
throw Failure("The argument \"" + arg->name() + "\" is required but not given."); |
||||
} |
||||
} |
||||
}); |
||||
// set actual argument count
|
||||
m_actualArgc = actualArgc; |
||||
// interate through all arguments again to invoke callback functions
|
||||
foreachArg(nullptr, m_mainArgs, [] (Argument *parent, Argument *arg) { |
||||
if(arg->m_callbackFunction) { |
||||
if(arg->isMainArgument() || (parent && parent->isPresent())) { |
||||
// only invoke if its a main argument or the parent is present
|
||||
if(arg->isPresent()) { |
||||
if(arg->isDefault() && !arg->values().size()) { |
||||
arg->m_callbackFunction(arg->defaultValues()); |
||||
} else { |
||||
arg->m_callbackFunction(arg->values()); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/*!
|
||||
* \brief The HelpArgument class prints help information for an argument parser |
||||
* when present (--help, -h). |
||||
*/ |
||||
|
||||
/*!
|
||||
* \brief Constructs a new help argument for the specified parser. |
||||
*/ |
||||
HelpArgument::HelpArgument(ArgumentParser &parser) : |
||||
Argument("help", "h", "shows this information") |
||||
{ |
||||
setCallback([&parser] (const StringVector &) {parser.printHelp(cout);}); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,581 @@ |
||||
#ifndef ARGUMENTPARSER_H |
||||
#define ARGUMENTPARSER_H |
||||
|
||||
#include "global.h" |
||||
|
||||
#include <string> |
||||
#include <vector> |
||||
#include <list> |
||||
#include <initializer_list> |
||||
#include <functional> |
||||
#include <stdexcept> |
||||
|
||||
namespace ApplicationUtilities { |
||||
|
||||
class Argument; |
||||
|
||||
class ArgumentParser; |
||||
|
||||
typedef std::initializer_list<Argument *> ArgumentInitializerList; |
||||
typedef std::vector<Argument *> ArgumentVector; |
||||
typedef std::vector<std::string> StringVector; |
||||
typedef std::list<std::string> StringList; |
||||
typedef std::function<bool (Argument *)> ArgumentPredicate; |
||||
|
||||
Argument LIB_EXPORT *firstPresentUncombinableArg(const ArgumentVector &args, const Argument *except); |
||||
|
||||
class LIB_EXPORT Argument |
||||
{ |
||||
friend class ArgumentParser; |
||||
|
||||
public: |
||||
typedef std::function <void (const StringVector &)> CallbackFunction; |
||||
|
||||
Argument(const std::string &name, const std::string abbreviation = std::string(), const std::string &description = std::string()); |
||||
Argument(const char *name, const char *abbreviation = nullptr, const char *description = nullptr); |
||||
~Argument(); |
||||
|
||||
const std::string &name() const; |
||||
void setName(const std::string &name); |
||||
const std::string &abbreviation() const; |
||||
void setAbbreviation(const std::string &abbreviation); |
||||
//unsigned char isAmbiguous(const ArgumentParser &parser) const;
|
||||
const std::string &description() const; |
||||
void setDescription(const std::string &description); |
||||
const StringVector &values() const; |
||||
const std::string &value(StringVector::size_type index) const; |
||||
StringVector::size_type valueCount() const; |
||||
int requiredValueCount() const; |
||||
void setRequiredValueCount(int requiredValueCount); |
||||
const StringList &valueNames() const; |
||||
void setValueNames(std::initializer_list<std::string> valueNames); |
||||
void appendValueName(const char *valueName); |
||||
void appendValueName(const std::string &valueName); |
||||
bool allRequiredValuesPresent() const; |
||||
bool isDefault() const; |
||||
void setDefault(bool value); |
||||
const StringVector &defaultValues() const; |
||||
void setDefaultValues(const StringVector &defaultValues); |
||||
bool isPresent() const; |
||||
bool isRequired() const; |
||||
void setRequired(bool value); |
||||
bool isCombinable() const; |
||||
void setCombinable(bool value); |
||||
bool isImplicit() const; |
||||
void setImplicit(bool value); |
||||
void setCallback(CallbackFunction callback); |
||||
void printInfo(std::ostream &os, unsigned char indentionLevel = 0) const; |
||||
const ArgumentVector &secondaryArguments() const; |
||||
void setSecondaryArguments(const ArgumentInitializerList &secondaryArguments); |
||||
bool hasSecondaryArguments() const; |
||||
const ArgumentVector parents() const; |
||||
bool isMainArgument() const; |
||||
std::string parentNames() const; |
||||
bool isParentPresent() const; |
||||
Argument *conflictsWithArgument() const; |
||||
|
||||
private: |
||||
std::string m_name; |
||||
std::string m_abbreviation; |
||||
std::string m_description; |
||||
bool m_required; |
||||
bool m_combinable; |
||||
bool m_implicit; |
||||
int m_requiredValueCount; |
||||
StringList m_valueNames; |
||||
bool m_default; |
||||
StringVector m_defaultValues; |
||||
bool m_present; |
||||
StringVector m_values; |
||||
ArgumentVector m_secondaryArgs; |
||||
CallbackFunction m_callbackFunction; |
||||
ArgumentVector m_parents; |
||||
bool m_isMainArg; |
||||
}; |
||||
|
||||
/*!
|
||||
* \brief Returns the name of the argument. |
||||
* |
||||
* The parser compares the name with the characters following a "--" prefix to |
||||
* identify arguments. |
||||
*/ |
||||
inline const std::string &Argument::name() const |
||||
{ |
||||
return m_name; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Sets the name of the argument. |
||||
* |
||||
* The name mustn't be empty or contain white spaces or equation chars. |
||||
* |
||||
* The parser compares the name with the characters following a "--" prefix to |
||||
* identify arguments. |
||||
*/ |
||||
inline void Argument::setName(const std::string &name) |
||||
{ |
||||
if(name.empty() || name.find(' ') != std::string::npos || name.find('=') != std::string::npos) { |
||||
throw std::invalid_argument("name mustn't be empty or contain white spaces or equation chars"); |
||||
} |
||||
m_name = name; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns the abbreviation of the argument. |
||||
* |
||||
* The parser compares the abbreviation with the characters following a "-" prefix to |
||||
* identify arguments. |
||||
*/ |
||||
inline const std::string &Argument::abbreviation() const |
||||
{ |
||||
return m_abbreviation; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Sets the abbreviation of the argument. |
||||
* |
||||
* The abbreviation might be empty but mustn't contain any white spaces or |
||||
* equation chars when provided. |
||||
* |
||||
* The parser compares the abbreviation with the characters following a "-" prefix to |
||||
* identify arguments. |
||||
*/ |
||||
inline void Argument::setAbbreviation(const std::string &abbreviation) |
||||
{ |
||||
if(!abbreviation.empty() && (abbreviation.find(' ') != std::string::npos || abbreviation.find('=') != std::string::npos)) { |
||||
throw std::invalid_argument("abbreviation mustn't contain white spaces or equation chars"); |
||||
} |
||||
m_abbreviation = abbreviation; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns the description of the argument. |
||||
* |
||||
* The parser uses the description when printing help information. |
||||
*/ |
||||
inline const std::string &Argument::description() const |
||||
{ |
||||
return m_description; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Sets the description of the argument. |
||||
* |
||||
* The parser uses the description when printing help information. |
||||
*/ |
||||
inline void Argument::setDescription(const std::string &description) |
||||
{ |
||||
m_description = description; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns the additional values for the argument. |
||||
* |
||||
* These values set by the parser when the command line arguments. |
||||
*/ |
||||
inline const StringVector &Argument::values() const |
||||
{ |
||||
return m_values; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns the value with the give \a index. |
||||
* |
||||
* These values set by the parser when the command line arguments. |
||||
*/ |
||||
inline const std::string &Argument::value(StringVector::size_type index) const |
||||
{ |
||||
return m_values[index]; |
||||
} |
||||
|
||||
/*!
|
||||
* Returns the number of values which could be found when parsing |
||||
* the command line arguments. |
||||
*/ |
||||
inline StringVector::size_type Argument::valueCount() const |
||||
{ |
||||
return m_values.size(); |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns the number of values which are required to be given |
||||
* for this argument. |
||||
* |
||||
* The parser will expect that many values when parsing command line arguments. |
||||
* A negative value indicates a variable number of arguments to be expected. |
||||
* |
||||
* The default value is 0. |
||||
* |
||||
* \sa setRequiredValueCount() |
||||
* \sa valueNames() |
||||
* \sa setValueNames() |
||||
*/ |
||||
inline int Argument::requiredValueCount() const |
||||
{ |
||||
return m_requiredValueCount; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Sets the number of values which are required to be given |
||||
* for this argument. |
||||
* |
||||
* The parser will expect that many values when parsing command line arguments. |
||||
* A negative value indicates a variable number of arguments to be expected. |
||||
* |
||||
* \sa requiredValueCount() |
||||
* \sa valueNames() |
||||
* \sa setValueNames() |
||||
*/ |
||||
inline void Argument::setRequiredValueCount(int requiredValueCount) |
||||
{ |
||||
m_requiredValueCount = requiredValueCount; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns the names of the requried values. |
||||
* |
||||
* These names will be shown when printing information about the argument. |
||||
* |
||||
* \sa setValueNames() |
||||
* \sa appendValueNames() |
||||
*/ |
||||
inline const StringList &Argument::valueNames() const |
||||
{ |
||||
return m_valueNames; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Sets the names of the requried values. These names will be used |
||||
* when printing information about the argument. |
||||
* |
||||
* If the number of value names is higher then the number of requried values |
||||
* the additional value names will be ignored. |
||||
* If the number of value names is lesser then the number of requried values |
||||
* generic values will be used for the missing names. |
||||
* |
||||
* \sa appendValueName() |
||||
* \sa valueNames() |
||||
* \sa requiredValueCount() |
||||
*/ |
||||
inline void Argument::setValueNames(std::initializer_list<std::string> valueNames) |
||||
{ |
||||
m_valueNames = std::list<std::string>(valueNames); |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Appends a value name. The value names names will be shown |
||||
* when printing information about the argument. |
||||
*/ |
||||
inline void Argument::appendValueName(const char *valueName) |
||||
{ |
||||
m_valueNames.emplace_back(valueName); |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Appends a value name. The value names names will be shown |
||||
* when printing information about the argument. |
||||
* |
||||
* \sa setValueNames() |
||||
* \sa valueNames() |
||||
*/ |
||||
inline void Argument::appendValueName(const std::string &valueName) |
||||
{ |
||||
m_valueNames.push_back(valueName); |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns an indication whether all required values are present. |
||||
*/ |
||||
inline bool Argument::allRequiredValuesPresent() const |
||||
{ |
||||
if(m_requiredValueCount > 0) { |
||||
return (m_values.size() >= static_cast<size_t>(m_requiredValueCount)) |
||||
|| (m_default && m_defaultValues.size() >= static_cast<size_t>(m_requiredValueCount)); |
||||
} else { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns an indication whether the argument is a default argument. |
||||
* |
||||
* A default argument will be flagged as present when parsing arguments event |
||||
* if it is not actually present if there is no uncombinable argument present |
||||
* and it is a main argument or the parent is present. |
||||
* |
||||
* The callback function will be invoked in this case as the argument where |
||||
* actually present. |
||||
* |
||||
* The default value (for this property) is false. |
||||
* |
||||
* \sa setDefault() |
||||
*/ |
||||
inline bool Argument::isDefault() const |
||||
{ |
||||
return m_default; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Sets whether the argument is a default argument. |
||||
* \sa isDefault() |
||||
*/ |
||||
inline void Argument::setDefault(bool value) |
||||
{ |
||||
m_default = value; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns the default values. |
||||
* \sa isDefault() |
||||
* \sa setDefault() |
||||
* \sa setDefaultValues() |
||||
*/ |
||||
inline const StringVector &Argument::defaultValues() const |
||||
{ |
||||
return m_defaultValues; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Sets the default values. |
||||
* |
||||
* There must be as many default values as required values |
||||
* if the argument is a default argument. |
||||
* |
||||
* \sa isDefault() |
||||
* \sa setDefault() |
||||
* \sa defaultValues() |
||||
*/ |
||||
inline void Argument::setDefaultValues(const StringVector &defaultValues) |
||||
{ |
||||
m_defaultValues = defaultValues; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns an indication whether the argument could be detected |
||||
* when parsing. |
||||
*/ |
||||
inline bool Argument::isPresent() const |
||||
{ |
||||
return m_present; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns an indication whether the argument is mandatory. |
||||
* |
||||
* The parser will complain if a mandatory argument is not present. |
||||
* |
||||
* The default value is false. |
||||
* |
||||
* \sa setRequired() |
||||
*/ |
||||
inline bool Argument::isRequired() const |
||||
{ |
||||
return m_required; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Sets if this argument is mandatory or not. |
||||
* |
||||
* The parser will complain if a mandatory argument is not present. |
||||
* |
||||
* * \sa isRequired() |
||||
*/ |
||||
inline void Argument::setRequired(bool value) |
||||
{ |
||||
m_required = value; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns an indication whether the argument is combinable. |
||||
* |
||||
* The parser will complain if two arguments labeled as uncombinable are |
||||
* present at the same time. |
||||
* |
||||
* \sa setCombinable() |
||||
*/ |
||||
inline bool Argument::isCombinable() const |
||||
{ |
||||
return m_combinable; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Sets if this argument can be combined. |
||||
* |
||||
* The parser will complain if two arguments labeled as uncombinable are |
||||
* present at the same time. |
||||
* |
||||
* \sa isCombinable() |
||||
*/ |
||||
inline void Argument::setCombinable(bool value) |
||||
{ |
||||
m_combinable = value; |
||||
} |
||||
|
||||
|
||||
/*!
|
||||
* \brief Returns an indication whether the argument can be specified implicitely. |
||||
* |
||||
* \sa setImplicit() |
||||
*/ |
||||
inline bool Argument::isImplicit() const |
||||
{ |
||||
return m_implicit; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Sets if this argument can be specified implicitely. |
||||
* |
||||
* \sa isImplicit() |
||||
*/ |
||||
inline void Argument::setImplicit(bool value) |
||||
{ |
||||
m_implicit = value; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Sets a \a callback function which will be called by the parser if |
||||
* the argument could be found and no parsing errors occured. |
||||
*/ |
||||
inline void Argument::setCallback(Argument::CallbackFunction callback) |
||||
{ |
||||
m_callbackFunction = callback; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns the secondary arguments for this argument. |
||||
* |
||||
* \sa setSecondaryArguments() |
||||
* \sa hasSecondaryArguments() |
||||
*/ |
||||
inline const ArgumentVector &Argument::secondaryArguments() const |
||||
{ |
||||
return m_secondaryArgs; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns an indication whether the argument has secondary arguments. |
||||
* |
||||
* \sa secondaryArguments() |
||||
* \sa setSecondaryArguments() |
||||
*/ |
||||
inline bool Argument::hasSecondaryArguments() const |
||||
{ |
||||
return !m_secondaryArgs.empty(); |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns the parents of this argument. |
||||
* |
||||
* If this argument is used as secondary argument, the arguments which |
||||
* contain this argument as secondary arguments are returned |
||||
* as "parents" of this argument. |
||||
* |
||||
* If this argument is used as a main argument shouldn't be used as |
||||
* secondary argument at the same time and thus have no parents. |
||||
*/ |
||||
inline const ArgumentVector Argument::parents() const |
||||
{ |
||||
return m_parents; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns an indication whether the argument is used as main argument. |
||||
* |
||||
* An argument used as main argument shouldn't be used as secondary |
||||
* arguments at the same time. |
||||
*/ |
||||
inline bool Argument::isMainArgument() const |
||||
{ |
||||
return m_isMainArg; |
||||
} |
||||
|
||||
class LIB_EXPORT ArgumentParser |
||||
{ |
||||
public: |
||||
ArgumentParser(); |
||||
|
||||
const ArgumentVector &mainArguments() const; |
||||
void setMainArguments(const ArgumentInitializerList &mainArguments); |
||||
void printHelp(std::ostream &os) const; |
||||
Argument *findArg(const ArgumentPredicate &predicate) const; |
||||
static Argument *findArg(const ArgumentVector &arguments, const ArgumentPredicate &predicate); |
||||
void verifySetup() const; |
||||
void parseArgs(int argc, char *argv[]); |
||||
unsigned int actualArgumentCount() const; |
||||
const std::string ¤tDirectory() const; |
||||
bool areUnknownArgumentsIgnored() const; |
||||
void setIgnoreUnknownArguments(bool ignore); |
||||
|
||||
private: |
||||
ArgumentVector m_mainArgs; |
||||
unsigned int m_actualArgc; |
||||
std::string m_currentDirectory; |
||||
bool m_ignoreUnknownArgs; |
||||
}; |
||||
|
||||
/*!
|
||||
* \brief Returns the main arguments. |
||||
* \sa setMainArguments() |
||||
*/ |
||||
inline const ArgumentVector &ArgumentParser::mainArguments() const |
||||
{ |
||||
return m_mainArgs; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns the actual number of arguments that could be found when parsing. |
||||
*/ |
||||
inline unsigned int ArgumentParser::actualArgumentCount() const |
||||
{ |
||||
return m_actualArgc; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns the current directory. |
||||
*/ |
||||
inline const std::string &ArgumentParser::currentDirectory() const |
||||
{ |
||||
return m_currentDirectory; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Returns an indication whether unknown arguments detected |
||||
* when parsing should be ignored. |
||||
* |
||||
* If unknown arguments are not ignored the parser will throw a |
||||
* Failure when an unknown argument is detected. |
||||
* Otherwise only a warning will be shown. |
||||
* |
||||
* The default value is false. |
||||
* |
||||
* \sa setIgnoreUnknownArguments() |
||||
*/ |
||||
inline bool ArgumentParser::areUnknownArgumentsIgnored() const |
||||
{ |
||||
return m_ignoreUnknownArgs; |
||||
} |
||||
|
||||
/*!
|
||||
* \brief Sets whether the parser should ignore unknown arguments |
||||
* when parsing. |
||||
* |
||||
* If set to false the parser should throw a Failure object |
||||
* when an unknown argument is found. Otherwise only a warning |
||||
* will be printed. |
||||
* |
||||
* \sa areUnknownArgumentsIgnored() |
||||
*/ |
||||
inline void ArgumentParser::setIgnoreUnknownArguments(bool ignore) |
||||
{ |
||||
m_ignoreUnknownArgs = ignore; |
||||
} |
||||
|
||||
class LIB_EXPORT HelpArgument : public Argument |
||||
{ |
||||
public: |
||||
HelpArgument(ArgumentParser &parser); |
||||
}; |
||||
|
||||
} |
||||
|
||||
#endif // ARGUMENTPARSER_H
|
@ -0,0 +1,44 @@ |
||||
#include "failure.h" |
||||
|
||||
namespace ApplicationUtilities { |
||||
|
||||
/*!
|
||||
* \class ApplicationUtilities::Failure |
||||
* \brief The exception that is thrown by an ArgumentParser when a parsing error occurs. |
||||
* |
||||
* \sa ApplicationUtilities::ArgumentParser |
||||
*/ |
||||
|
||||
/*!
|
||||
* Constructs a new Failure. |
||||
*/ |
||||
Failure::Failure() : |
||||
m_what("unspecified parsing exception") |
||||
{} |
||||
|
||||
/*!
|
||||
* Constructs a new Failure. \a what is a std::string |
||||
* describing the cause of the Failure. |
||||
*/ |
||||
Failure::Failure(const std::string &what) : |
||||
m_what(what) |
||||
{} |
||||
|
||||
/*!
|
||||
* Destroys the Failure. |
||||
*/ |
||||
Failure::~Failure() USE_NOTHROW |
||||
{} |
||||
|
||||
/*!
|
||||
* Returns a C-style character string describing the cause |
||||
* of the Failure. |
||||
*/ |
||||
const char *Failure::what() const USE_NOTHROW |
||||
{ |
||||
return m_what.c_str(); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
@ -0,0 +1,26 @@ |
||||
#ifndef FAILURE_H |
||||
#define FAILURE_H |
||||
|
||||
#include "global.h" |
||||
|
||||
#include <exception> |
||||
#include <string> |
||||
|
||||
namespace ApplicationUtilities { |
||||
|
||||
class LIB_EXPORT Failure : public std::exception |
||||
{ |
||||
public: |
||||
Failure(); |
||||
Failure(const std::string &what); |
||||
~Failure() USE_NOTHROW; |
||||
|
||||
virtual const char *what() const USE_NOTHROW; |
||||
|
||||
private: |
||||
std::string m_what; |
||||
}; |
||||
|
||||
} |
||||
|
||||
#endif // FAILURE_H
|
@ -0,0 +1,11 @@ |
||||
#include "fakeqtconfigarguments.h" |
||||
|
||||
namespace ApplicationUtilities { |
||||
|
||||
FakeQtConfigArguments::FakeQtConfigArguments() : |
||||
m_qtWidgetsGuiArg("qt-widgets-gui", "g", "shows a Qt widgets based graphical user interface (the application has not been built with Qt widgets support)"), |
||||
m_qtQuickGuiArg("qt-quick-gui", "q", "shows a Qt quick based graphical user interface (the application has not been built with Qt quick support)") |
||||
{} |
||||
|
||||
} // namespace ApplicationUtilities
|
||||
|
@ -0,0 +1,44 @@ |
||||
#ifndef APPLICATIONUTILITIES_FAKEQTCONFIGARGUMENTS_H |
||||
#define APPLICATIONUTILITIES_FAKEQTCONFIGARGUMENTS_H |
||||
|
||||
#include "argumentparser.h" |
||||
|
||||
namespace ApplicationUtilities { |
||||
|
||||
class LIB_EXPORT FakeQtConfigArguments |
||||
{ |
||||
public: |
||||
FakeQtConfigArguments(); |
||||
|
||||
Argument &qtWidgetsGuiArg(); |
||||
Argument &qtQuickGuiArg(); |
||||
|
||||
bool areQtGuiArgsPresent() const; |
||||
|
||||
private: |
||||
Argument m_qtWidgetsGuiArg; |
||||
Argument m_qtQuickGuiArg; |
||||
}; |
||||
|
||||
inline Argument &FakeQtConfigArguments::qtWidgetsGuiArg() |
||||
{ |
||||
return m_qtWidgetsGuiArg; |
||||
} |
||||
|
||||
inline Argument &FakeQtConfigArguments::qtQuickGuiArg() |
||||
{ |
||||
return m_qtQuickGuiArg; |
||||
} |
||||
|
||||
inline bool FakeQtConfigArguments::areQtGuiArgsPresent() const |
||||
{ |
||||
return m_qtWidgetsGuiArg.isPresent() || m_qtQuickGuiArg.isPresent(); |
||||
} |
||||
|
||||
} // namespace ApplicationUtilities
|
||||
|
||||
#ifndef QT_CONFIG_ARGUMENTS |
||||
#define QT_CONFIG_ARGUMENTS ApplicationUtilities::FakeQtConfigArguments |
||||
#endif |
||||
|
||||
#endif // APPLICATIONUTILITIES_FAKEQTCONFIGARGUMENTS_H
|
@ -0,0 +1,77 @@ |
||||
#ifndef MARTCHUSUTILITY_LIBRARY_GLOBAL_H |
||||
#define MARTCHUSUTILITY_LIBRARY_GLOBAL_H |
||||
|
||||
/*!
|
||||
* \def PLATFORM_WINDOWS |
||||
* \brief Defined on Windows. |
||||
*/ |
||||
|
||||
/*!
|
||||
* \def PLATFORM_UNIX |
||||
* \brief Defined on any UNIX system. |
||||
*/ |
||||
|
||||
/*!
|
||||
* \def PLATFORM_LINUX |
||||
* \brief Defined on Linux. |
||||
*/ |
||||
|
||||
#ifdef _WIN32 |
||||
# define PLATFORM_WINDOWS |
||||
#elif __unix__ |
||||
# define PLATFORM_UNIX |
||||
#endif |
||||
|