diff options
Diffstat (limited to 'task1/getoptwrapper.cpp')
| -rw-r--r-- | task1/getoptwrapper.cpp | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/task1/getoptwrapper.cpp b/task1/getoptwrapper.cpp new file mode 100644 index 0000000..1efd603 --- /dev/null +++ b/task1/getoptwrapper.cpp | |||
| @@ -0,0 +1,191 @@ | |||
| 1 | /** | ||
| 2 | * $Id: getoptwrapper.cpp 2 2009-10-31 02:48:23Z l0728348 $ | ||
| 3 | * | ||
| 4 | * Copyright 2009 | ||
| 5 | * | ||
| 6 | * @author Manuel Mausz (0728348) | ||
| 7 | * @brief Wraps around getopt_long() using two classes | ||
| 8 | * class CommandOption represents a valid commandline option | ||
| 9 | * class CommandOptionParse calls getopt_long | ||
| 10 | * and generates usage message | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <sstream> | ||
| 14 | #include <iomanip> | ||
| 15 | #include <algorithm> | ||
| 16 | #include <stdexcept> | ||
| 17 | #include <unistd.h> | ||
| 18 | #include "getoptwrapper.h" | ||
| 19 | |||
| 20 | using namespace std; | ||
| 21 | |||
| 22 | CommandOptionParse::CommandOptionList cmdoptionlist; | ||
| 23 | |||
| 24 | /*----------------------------------------------------------------------------*/ | ||
| 25 | |||
| 26 | const std::string CommandOption::printParameters() | ||
| 27 | { | ||
| 28 | ostringstream oss; | ||
| 29 | |||
| 30 | if (!m_longopt.empty() && m_shortopt != 0) | ||
| 31 | oss << "-" << m_shortopt << " [ --" << m_longopt << " ]"; | ||
| 32 | else if (!m_longopt.empty() && m_shortopt == 0) | ||
| 33 | oss << "--" << m_longopt; | ||
| 34 | else if (m_longopt.empty() && m_shortopt != 0) | ||
| 35 | oss << "-" << m_shortopt; | ||
| 36 | |||
| 37 | if (m_type == needArg) | ||
| 38 | oss << " arg"; | ||
| 39 | else if (m_type == optArg) | ||
| 40 | oss << " [ arg ]"; | ||
| 41 | |||
| 42 | return oss.str(); | ||
| 43 | } | ||
| 44 | |||
| 45 | /*----------------------------------------------------------------------------*/ | ||
| 46 | |||
| 47 | void CommandOption::foundOption(const char *value) | ||
| 48 | { | ||
| 49 | m_count++; | ||
| 50 | if (value != NULL) | ||
| 51 | m_value = value; | ||
| 52 | } | ||
| 53 | |||
| 54 | /*----------------------------------------------------------------------------*/ | ||
| 55 | |||
| 56 | bool CommandOptionParse::parse() | ||
| 57 | { | ||
| 58 | CommandOptionList::iterator it; | ||
| 59 | |||
| 60 | /* build optstring */ | ||
| 61 | m_optstring = ""; | ||
| 62 | for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) | ||
| 63 | { | ||
| 64 | CommandOption *opt = *it; | ||
| 65 | if (opt->m_shortopt == 0) | ||
| 66 | continue; | ||
| 67 | |||
| 68 | m_optstring += opt->m_shortopt; | ||
| 69 | if (opt->m_type == CommandOption::needArg) | ||
| 70 | m_optstring += ':'; | ||
| 71 | if (opt->m_type == CommandOption::optArg) | ||
| 72 | m_optstring += "::"; | ||
| 73 | } | ||
| 74 | |||
| 75 | /* build longopts */ | ||
| 76 | if (m_longopts != NULL) | ||
| 77 | delete[] m_longopts; | ||
| 78 | m_longopts = new option[m_cmdlist.size() + 1]; | ||
| 79 | int i = 0; | ||
| 80 | for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) | ||
| 81 | { | ||
| 82 | CommandOption *opt = *it; | ||
| 83 | if (opt->m_longopt.empty()) | ||
| 84 | continue; | ||
| 85 | |||
| 86 | m_longopts[i].name = opt->m_longopt.c_str(); | ||
| 87 | m_longopts[i].has_arg = opt->m_type; | ||
| 88 | m_longopts[i].flag = 0; | ||
| 89 | m_longopts[i].val = 0; | ||
| 90 | ++i; | ||
| 91 | } | ||
| 92 | |||
| 93 | /* append NULL-row */ | ||
| 94 | m_longopts[i].name = 0; | ||
| 95 | m_longopts[i].has_arg = 0; | ||
| 96 | m_longopts[i].flag = 0; | ||
| 97 | m_longopts[i].val = 0; | ||
| 98 | |||
| 99 | //opterr = 0; // no errors from getopt_long! | ||
| 100 | int opt; | ||
| 101 | int optindex = 0; | ||
| 102 | while ((opt = getopt_long(m_argc, m_argv, m_optstring.c_str(), m_longopts, &optindex)) != -1) | ||
| 103 | { | ||
| 104 | if (opt == '?') | ||
| 105 | return 0; | ||
| 106 | |||
| 107 | for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) | ||
| 108 | { | ||
| 109 | CommandOption *option = *it; | ||
| 110 | if (opt == 0) | ||
| 111 | { | ||
| 112 | if (option->m_longopt == m_longopts[optindex].name) | ||
| 113 | option->foundOption(optarg); | ||
| 114 | } | ||
| 115 | else if (opt == option->m_shortopt) | ||
| 116 | option->foundOption(optarg); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | return 1; | ||
| 121 | } | ||
| 122 | |||
| 123 | /*----------------------------------------------------------------------------*/ | ||
| 124 | |||
| 125 | const std::string CommandOptionParse::usage() | ||
| 126 | { | ||
| 127 | ostringstream oss; | ||
| 128 | string me(m_argv[0]); | ||
| 129 | |||
| 130 | /* build usage/synopsis */ | ||
| 131 | oss << "Usage: "; | ||
| 132 | if (!m_synopsis.empty()) | ||
| 133 | { | ||
| 134 | oss << me << " " << m_synopsis.at(0) << endl; | ||
| 135 | for (unsigned i = 1; i < m_synopsis.size(); ++i) | ||
| 136 | oss << " " << me << " " << m_synopsis.at(i) << endl; | ||
| 137 | } | ||
| 138 | else | ||
| 139 | oss << me << " [OPTION]..." << endl; | ||
| 140 | |||
| 141 | /* find maximum width of options */ | ||
| 142 | CommandOptionList::iterator it; | ||
| 143 | unsigned width = 20; // default | ||
| 144 | for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) | ||
| 145 | { | ||
| 146 | stringstream tmpss; | ||
| 147 | tmpss << (*it)->printParameters(); | ||
| 148 | width = (max)(width, static_cast<unsigned>(tmpss.str().size())); | ||
| 149 | } | ||
| 150 | width += 2; | ||
| 151 | |||
| 152 | /* print allowed options + description */ | ||
| 153 | oss << endl << m_description << ":" << endl; | ||
| 154 | for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) | ||
| 155 | { | ||
| 156 | oss << " " << setw(width) << left << (*it)->printParameters() | ||
| 157 | << (*it)->m_description << endl; | ||
| 158 | } | ||
| 159 | |||
| 160 | return oss.str(); | ||
| 161 | } | ||
| 162 | |||
| 163 | /*----------------------------------------------------------------------------*/ | ||
| 164 | |||
| 165 | CommandOption& CommandOptionParse::operator[](const std::string& longopt) | ||
| 166 | { | ||
| 167 | CommandOptionList::iterator it; | ||
| 168 | for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) | ||
| 169 | { | ||
| 170 | CommandOption *opt = *it; | ||
| 171 | if (opt->m_longopt == longopt) | ||
| 172 | return *opt; | ||
| 173 | } | ||
| 174 | throw out_of_range("option not found"); | ||
| 175 | } | ||
| 176 | |||
| 177 | /*----------------------------------------------------------------------------*/ | ||
| 178 | |||
| 179 | CommandOption& CommandOptionParse::operator[](const char shortopt) | ||
| 180 | { | ||
| 181 | CommandOptionList::iterator it; | ||
| 182 | for (it = m_cmdlist.begin(); it != m_cmdlist.end(); ++it) | ||
| 183 | { | ||
| 184 | CommandOption *opt = *it; | ||
| 185 | if (opt->m_shortopt == shortopt) | ||
| 186 | return *opt; | ||
| 187 | } | ||
| 188 | throw out_of_range("option not found"); | ||
| 189 | } | ||
| 190 | |||
| 191 | /* vim: set et sw=2 ts=2: */ | ||
