/** * $Id: getoptwrapper.cpp 2 2009-10-31 02:48:23Z l0728348 $ * * Copyright 2009 * * @author Manuel Mausz (0728348) * @brief Wraps around getopt_long() using two classes * class CommandOption represents a valid commandline option * class CommandOptionParse calls getopt_long * and generates usage message */ #include #include #include #include #include #include "getoptwrapper.h" using namespace std; CommandOptionParse::CommandOptionList cmdoptionlist; /*----------------------------------------------------------------------------*/ const std::string CommandOption::printParameters() { ostringstream oss; if (!m_longopt.empty() && m_shortopt != 0) oss << "-" << m_shortopt << " [ --" << m_longopt << " ]"; else if (!m_longopt.empty() && m_shortopt == 0) oss << "--" << m_longopt; else if (m_longopt.empty() && m_shortopt != 0) oss << "-" << m_shortopt; if (m_type == needArg) oss << " arg"; else if (m_type == optArg) oss << " [ arg ]"; return oss.str(); } /*----------------------------------------------------------------------------*/ void CommandOption::foundOption(const char *value) { m_count++; if (value != NULL) m_value = value; } /*----------------------------------------------------------------------------*/ bool CommandOptionParse::parse() { CommandOptionList::iterator it; /* build optstring */ m_optstring = ""; for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) { CommandOption *opt = *it; if (opt->m_shortopt == 0) continue; m_optstring += opt->m_shortopt; if (opt->m_type == CommandOption::needArg) m_optstring += ':'; if (opt->m_type == CommandOption::optArg) m_optstring += "::"; } /* build longopts */ if (m_longopts != NULL) delete[] m_longopts; m_longopts = new option[m_cmdlist.size() + 1]; int i = 0; for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) { CommandOption *opt = *it; if (opt->m_longopt.empty()) continue; m_longopts[i].name = opt->m_longopt.c_str(); m_longopts[i].has_arg = opt->m_type; m_longopts[i].flag = 0; m_longopts[i].val = 0; ++i; } /* append NULL-row */ m_longopts[i].name = 0; m_longopts[i].has_arg = 0; m_longopts[i].flag = 0; m_longopts[i].val = 0; //opterr = 0; // no errors from getopt_long! int opt; int optindex = 0; while ((opt = getopt_long(m_argc, m_argv, m_optstring.c_str(), m_longopts, &optindex)) != -1) { if (opt == '?') return 0; for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) { CommandOption *option = *it; if (opt == 0) { if (option->m_longopt == m_longopts[optindex].name) option->foundOption(optarg); } else if (opt == option->m_shortopt) option->foundOption(optarg); } } return 1; } /*----------------------------------------------------------------------------*/ const std::string CommandOptionParse::usage() { ostringstream oss; string me(m_argv[0]); /* build usage/synopsis */ oss << "Usage: "; if (!m_synopsis.empty()) { oss << me << " " << m_synopsis.at(0) << endl; for (unsigned i = 1; i < m_synopsis.size(); ++i) oss << " " << me << " " << m_synopsis.at(i) << endl; } else oss << me << " [OPTION]..." << endl; /* find maximum width of options */ CommandOptionList::iterator it; unsigned width = 20; // default for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) { stringstream tmpss; tmpss << (*it)->printParameters(); width = (max)(width, static_cast(tmpss.str().size())); } width += 2; /* print allowed options + description */ oss << endl << m_description << ":" << endl; for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) { oss << " " << setw(width) << left << (*it)->printParameters() << (*it)->m_description << endl; } return oss.str(); } /*----------------------------------------------------------------------------*/ CommandOption& CommandOptionParse::operator[](const std::string& longopt) { CommandOptionList::iterator it; for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) { CommandOption *opt = *it; if (opt->m_longopt == longopt) return *opt; } throw out_of_range("option not found"); } /*----------------------------------------------------------------------------*/ CommandOption& CommandOptionParse::operator[](const char shortopt) { CommandOptionList::iterator it; for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) { CommandOption *opt = *it; if (opt->m_shortopt == shortopt) return *opt; } throw out_of_range("option not found"); } /* vim: set et sw=2 ts=2: */