#ifdef _MSC_VER #pragma warning(disable:4786) #endif #include #include #include #include #include #include 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 ( int _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 value = getValue(param); if (value.first) { param.setValue(value.second); } } pair eoParser::getValue(eoParam& _param) const { pair result(false, ""); if (_param.shortName() != 0) { map::const_iterator it = shortNameMap.find(_param.shortName()); if (it != shortNameMap.end()) { result.second = it->second; result.first = true; return result; } } map::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"; if (str.size() > 2) value = string(str.begin() + 3, 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; 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(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:"<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 << "--" <second->longName() <<":\t" << p->second->description() ; os << "\n" << setw(20) << ( (p->second->required())?"Required":"Optional" ); os <<". By default: "<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(); }