are commented out - but still appear. Uses the (now public and pure virtual in the base class eoParameterLoader) method isItThere.
353 lines
8.3 KiB
C++
353 lines
8.3 KiB
C++
#ifdef _MSC_VER
|
|
#pragma warning(disable:4786)
|
|
#endif
|
|
|
|
#include <stdexcept>
|
|
#include <algorithm>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
|
|
#include <utils/compatibility.h>
|
|
|
|
#include <utils/eoParser.h>
|
|
|
|
using namespace std;
|
|
|
|
void eoWarning(std::string str)
|
|
{
|
|
cout << str << '\n';
|
|
}
|
|
|
|
std::ostream& printSectionHeader(std::ostream& os, std::string section)
|
|
{
|
|
if (section == "")
|
|
section = "General";
|
|
|
|
os << '\n' << setw(10) << "###### " << setw(20) << section << setw(10) << " ######\n";
|
|
return os;
|
|
}
|
|
|
|
eoParameterLoader::~eoParameterLoader()
|
|
{
|
|
for (unsigned i = 0; i < ownedParams.size(); ++i)
|
|
{
|
|
delete ownedParams[i];
|
|
}
|
|
}
|
|
|
|
|
|
eoParser::eoParser ( unsigned _argc, char **_argv , string _programDescription, string _lFileParamName, char _shortHand) :
|
|
programName( _argv[0]),
|
|
programDescription( _programDescription),
|
|
needHelp(false, "help", "Prints this message", 'h')
|
|
{
|
|
// need to process the param file first
|
|
// if we want command-line to have highest priority
|
|
unsigned i;
|
|
for (i = 1; i < _argc; ++i)
|
|
{
|
|
if (_argv[i][0] == '@')
|
|
{ // read response file
|
|
char *pts = _argv[i]+1; // yes a char*, sorry :-)
|
|
|
|
ifstream ifs (pts);
|
|
|
|
ifs.peek(); // check if it exists
|
|
|
|
if (!ifs)
|
|
{
|
|
string msg = (string)("Could not open response file: ") + pts;
|
|
throw runtime_error(msg);
|
|
}
|
|
|
|
// read - will be overwritten by command-line
|
|
readFrom(ifs);
|
|
break; // stop reading command line args for '@'
|
|
}
|
|
}
|
|
|
|
// now read arguments on command-line
|
|
strstream stream;
|
|
|
|
for (i = 1; i < _argc; ++i)
|
|
{
|
|
stream << _argv[i] << '\n';
|
|
}
|
|
|
|
readFrom(stream);
|
|
|
|
processParam(needHelp);
|
|
}
|
|
|
|
void eoParser::processParam(eoParam& param, std::string section)
|
|
{
|
|
doRegisterParam(param); // plainly register it
|
|
params.insert(make_pair(section, ¶m));
|
|
}
|
|
|
|
void eoParser::doRegisterParam(eoParam& param) const
|
|
{
|
|
if (param.required() && !isItThere(param))
|
|
{
|
|
string msg = "Required parameter: " + param.longName() + " missing";
|
|
messages.push_back(msg);
|
|
}
|
|
|
|
pair<bool, string> value = getValue(param);
|
|
|
|
if (value.first)
|
|
{
|
|
param.setValue(value.second);
|
|
}
|
|
}
|
|
|
|
pair<bool, string> eoParser::getValue(eoParam& _param) const
|
|
{
|
|
pair<bool, string> result(false, "");
|
|
|
|
if (_param.shortName() != 0)
|
|
{
|
|
map<char, string>::const_iterator it = shortNameMap.find(_param.shortName());
|
|
if (it != shortNameMap.end())
|
|
{
|
|
result.second = it->second;
|
|
result.first = true;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
map<string, string>::const_iterator it = longNameMap.find(_param.longName());
|
|
|
|
if (it != longNameMap.end())
|
|
{
|
|
result.second = it->second;
|
|
result.first = true;
|
|
return result;
|
|
}
|
|
// else (TODO: check environment, just long names)
|
|
|
|
return result;
|
|
}
|
|
|
|
void eoParser::updateParameters() const
|
|
{
|
|
typedef MultiMapType::const_iterator It;
|
|
|
|
for (It p = params.begin(); p != params.end(); ++p)
|
|
{
|
|
doRegisterParam(*p->second);
|
|
}
|
|
}
|
|
|
|
void eoParser::readFrom(istream& is)
|
|
{
|
|
string str;
|
|
while (is >> str)
|
|
{
|
|
|
|
if (str[0] == '#')
|
|
{ // skip the rest of the line
|
|
string tempStr;
|
|
getline(is, tempStr);
|
|
}
|
|
if (str[0] == '-')
|
|
{
|
|
if (str.size() < 2)
|
|
{
|
|
eoWarning("Missing parameter");
|
|
needHelp.value() = true;
|
|
return;
|
|
}
|
|
|
|
if (str[1] == '-') // two consecutive dashes
|
|
{
|
|
string::iterator equalLocation = find(str.begin() + 2, str.end(), '=');
|
|
string value;
|
|
|
|
if (equalLocation == str.end())
|
|
{ // TODO: it should be the next string
|
|
value = "";
|
|
}
|
|
else
|
|
{
|
|
value = string(equalLocation + 1, str.end());
|
|
}
|
|
|
|
string name(str.begin() + 2, equalLocation);
|
|
longNameMap[name] = value;
|
|
|
|
}
|
|
else // it should be a char
|
|
{
|
|
string value = "1"; // flags do not need a special
|
|
|
|
if (str.size() >= 2)
|
|
{
|
|
if (str[2] == '=')
|
|
{
|
|
if (str.size() >= 3)
|
|
value = string(str.begin() + 3, str.end());
|
|
}
|
|
else
|
|
{
|
|
value = string(str.begin() + 2, str.end());
|
|
}
|
|
}
|
|
|
|
shortNameMap[str[1]] = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
updateParameters();
|
|
}
|
|
|
|
void eoParser::printOn(ostream& os) const
|
|
{
|
|
typedef MultiMapType::const_iterator It;
|
|
|
|
It p = params.begin();
|
|
|
|
std::string section = p->first;
|
|
|
|
printSectionHeader(os, section);
|
|
//print every param with its value
|
|
for (; p != params.end(); ++p)
|
|
{
|
|
std::string newSection = p->first;
|
|
|
|
if (newSection != section)
|
|
{
|
|
section = newSection;
|
|
printSectionHeader(os, section);
|
|
}
|
|
|
|
eoParam* param = p->second;
|
|
|
|
if (!isItThere(*param)) // comment out the ones not set by the user
|
|
os << "# ";
|
|
|
|
string str = "--" + param->longName() + "=" + param->getValue();
|
|
|
|
os.setf(ios_base::left, ios_base::adjustfield);
|
|
os << setw(40) << str;
|
|
|
|
os << setw(0) << " # ";
|
|
if (param->shortName())
|
|
os << '-' << param->shortName() << " : ";
|
|
os << param->description();
|
|
|
|
if (param->required())
|
|
{
|
|
os << " REQUIRED ";
|
|
}
|
|
|
|
os << '\n';
|
|
}
|
|
}
|
|
|
|
void eoParser::printHelp(ostream& os)
|
|
{
|
|
if (needHelp.value() == false && !messages.empty())
|
|
{
|
|
std::copy(messages.begin(), messages.end(), ostream_iterator<string>(os, "\n"));
|
|
messages.clear();
|
|
return;
|
|
}
|
|
|
|
// print program name and description
|
|
os << this->programName <<": "<< programDescription << "\n\n";
|
|
|
|
// print the usage when calling the program from the command line
|
|
os << "Usage: "<< programName<<" [Options]\n";
|
|
// only short usage!
|
|
os << "Options of the form \"-f[=Value]\" or \"--Name[=value]\"" << endl;
|
|
|
|
os << "Where:"<<endl;
|
|
|
|
typedef MultiMapType::const_iterator It;
|
|
|
|
It p = params.begin();
|
|
|
|
std::string section = p->first;
|
|
|
|
printSectionHeader(os, section);
|
|
|
|
//print every param with its value
|
|
for (; p != params.end(); ++p)
|
|
{
|
|
std::string newSection = p->first;
|
|
|
|
if (newSection != section)
|
|
{
|
|
section = newSection;
|
|
printSectionHeader(os, section);
|
|
}
|
|
|
|
if (p->second->shortName())
|
|
os << "-" << p->second->shortName() << ", ";
|
|
|
|
os << "--" <<p->second->longName() <<":\t"
|
|
<< p->second->description() ;
|
|
|
|
os << "\n" << setw(20) << ( (p->second->required())?"Required":"Optional" );
|
|
os <<". By default: "<<p->second->defValue() << '\n';
|
|
} // for p
|
|
|
|
os << "\n@param_file \t defines a file where the parameters are stored\n";
|
|
os << '\n';
|
|
|
|
}
|
|
|
|
bool eoParser::userNeedsHelp(void)
|
|
{
|
|
/*
|
|
check whether there are long or short names entered
|
|
without a corresponding parameter
|
|
*/
|
|
|
|
for (LongNameMapType::const_iterator lIt = longNameMap.begin(); lIt != longNameMap.end(); ++lIt)
|
|
{
|
|
string entry = lIt->first;
|
|
|
|
MultiMapType::const_iterator it;
|
|
|
|
for (it = params.begin(); it != params.end(); ++it)
|
|
{
|
|
if (entry == it->second->longName())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (it == params.end())
|
|
{
|
|
string msg = "Unknown parameter: --" + entry + " entered, type -h or --help to see available parameters";
|
|
messages.push_back(msg);
|
|
}
|
|
}
|
|
|
|
for (ShortNameMapType::const_iterator sIt = shortNameMap.begin(); sIt != shortNameMap.end(); ++sIt)
|
|
{
|
|
char entry = sIt->first;
|
|
|
|
MultiMapType::const_iterator it;
|
|
|
|
for (it = params.begin(); it != params.end(); ++it)
|
|
{
|
|
if (entry == it->second->shortName())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (it == params.end())
|
|
{
|
|
string entryString(1, entry);
|
|
string msg = "Unknown parameter: -" + entryString + " entered, type -h or --help to see available parameters";
|
|
messages.push_back(msg);
|
|
}
|
|
}
|
|
|
|
return needHelp.value() || !messages.empty();
|
|
}
|