00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef NGETOPT_HPP
00023 #define NGETOPT_HPP
00024
00036 template <typename HandlerType>
00037 class NGetOpt: public NObject {
00038 public:
00039
00043 enum Style {
00044 GNU_STYLE,
00045 BSD_STYLE,
00046 WINDOWS_STYLE,
00047 };
00048
00052 typedef NList< NOpt<HandlerType> > NOptList;
00053
00054
00065 NGetOpt(int argc, char **argv, HandlerType *handler,
00066 nuint32 min_args = 0, Style style = GNU_STYLE);
00067
00071 ~NGetOpt(void);
00072
00077 void setStyle(Style style);
00078
00084 Style getStyle(void) const;
00085
00097 NGetOpt &add(const NString &opt_short, const NString &opt_long,
00098 bool opt_opt, const NString &help,
00099 typename NOpt<HandlerType>::Handler handler);
00100
00106 NGetOpt &add(const NOpt<HandlerType> &opt);
00107
00112 bool proccess(void);
00113
00117 void help(void);
00118
00119 private:
00120 int m_argc;
00121 char **m_argv;
00122 HandlerType *m_handler;
00123 Style m_style;
00124 NOptList m_opts;
00125 NString m_style_str_short;
00126 NString m_style_str_long;
00127 NOptList m_passed;
00128 nint32 m_min_args;
00129
00130 NOpt<HandlerType> getOptByName(const NString &str);
00131 bool isLongOpt(const NString &str) const;
00132 bool isShortOpt(const NString &str) const;
00133
00134 NException valueErr(const NOpt<HandlerType> *opt);
00135 char **addValue(NOpt<HandlerType> *opt, nint32 pos, char **list);
00136 void checkRequired(void);
00137
00138
00139 void showUsage(void);
00140 void showHelp(void);
00141
00142 NGetOpt(const NGetOpt &);
00143 NGetOpt &operator=(const NGetOpt &);
00144 };
00145
00146
00147 template <typename HandlerType>
00148 NGetOpt<HandlerType>::NGetOpt(int argc, char **argv, HandlerType *handler,
00149 nuint32 min_args, Style style)
00150 : NObject(),
00151 m_argc(argc - 1),
00152 m_argv(argv),
00153 m_handler(handler),
00154 m_style(style),
00155 m_opts(),
00156 m_style_str_short(),
00157 m_style_str_long(),
00158 m_passed(),
00159 m_min_args(min_args)
00160
00161 {
00162 assert(handler);
00163
00164 if (m_style == GNU_STYLE) {
00165 m_style_str_short = "-";
00166 m_style_str_long = "--";
00167 }
00168 else {
00169 if (m_style == BSD_STYLE) {
00170 m_style_str_short = "-";
00171 m_style_str_long = "-";
00172 }
00173 else {
00174 m_style_str_short = "/";
00175 m_style_str_long = "/";
00176 }
00177 }
00178 }
00179
00180
00181 template <typename HandlerType>
00182 NGetOpt<HandlerType>::~NGetOpt(void) {
00183
00184 }
00185
00186
00187 template <typename HandlerType>
00188 void NGetOpt<HandlerType>::setStyle(Style style) {
00189 m_style = style;
00190 }
00191
00192
00193 template <typename HandlerType>
00194 typename NGetOpt<HandlerType>::Style NGetOpt<HandlerType>::getStyle(void) const {
00195 return m_style;
00196 }
00197
00198
00199 template <typename HandlerType>
00200 NGetOpt<HandlerType> &NGetOpt<HandlerType>::add(const NString &opt_short, const NString &opt_long,
00201 bool opt_opt, const NString &opt_help,
00202 typename NOpt<HandlerType>::Handler handler)
00203 {
00204 NOpt<HandlerType> opt(opt_short, opt_long, opt_opt, opt_help, handler);
00205 NDebug::print() << "Adding options";
00206 NDebug::print() << "Option: " << opt_short << ". Value: " << opt_long <<
00207 "(" << opt_help << ")";
00208
00209
00210
00211 return add(opt);
00212 }
00213
00214
00215 template <typename HandlerType>
00216 NGetOpt<HandlerType> &NGetOpt<HandlerType>::add(const NOpt<HandlerType> &opt) {
00217 if (!m_opts.contains(opt)) {
00218 m_opts.append(opt);
00219 }
00220 else {
00221 NWarning::print() << "Trying to insert a value '-" << opt.getShort()
00222 << "' [ --" << opt.getLong() << " ] already in the argument list";
00223 }
00224 return *this;
00225 }
00226
00227
00228 template <typename HandlerType>
00229 bool NGetOpt<HandlerType>::isLongOpt(const NString &str) const {
00230 NDebug::print() << " ---> " << m_style_str_long << " & " << str;
00231
00232 if (str.compare(0, m_style_str_long.length(), m_style_str_long)) {
00233 return true;
00234 }
00235
00236 return false;
00237 }
00238
00239
00240 template <typename HandlerType>
00241 bool NGetOpt<HandlerType>::isShortOpt(const NString &str) const {
00242 if (str.compare(0, m_style_str_short.length(), m_style_str_short)) {
00243 if (!isLongOpt(str)) {
00244 return true;
00245 }
00246 }
00247
00248 return false;
00249 }
00250
00251
00252 template <typename HandlerType>
00253 NOpt<HandlerType> NGetOpt<HandlerType>::getOptByName(const NString &str) {
00254 NString opt_str;
00255 NString cmd_str;
00256 typename NOptList::iterator i = m_opts.begin();
00257 NOpt<HandlerType> ret;
00258
00259 bool is_short = false;
00260 nuint32 opt_length = m_style_str_long.length();
00261
00262 NDebug::print() << "Looking for option: " << str;
00263 if (isShortOpt(str)) {
00264 NDebug::print() << "Given option is short";
00265 is_short = true;
00266 opt_length = m_style_str_short.length();
00267 }
00268 else {
00269 NDebug::print() << "Given option is not short, checking if it's long";
00270 if (!isLongOpt(str)) {
00271 NString msg = "Option ";
00272 msg = msg + str + " is not valid";
00273 throw NException(msg, NException::BASE);
00274 }
00275 }
00276
00277 cmd_str = str.substr(opt_length, str.length() - opt_length);
00278 for (i = m_opts.begin(); i != m_opts.end(); i++) {
00279 opt_str = is_short ? i->getShort() : i->getLong();
00280
00281 NDebug::print() << "Comparing: " << cmd_str << "(" << cmd_str.length()
00282 << ") with " << opt_str << "(" << opt_str.length() << ")";
00283
00284 if (cmd_str == opt_str) {
00285 NDebug::print() << "Ok, found!";
00286 ret = *i;
00287 break;
00288 }
00289 }
00290
00291 return ret;
00292 }
00293
00294 template <typename HandlerType>
00295 NException NGetOpt<HandlerType>::valueErr(const NOpt<HandlerType> *opt) {
00296 NString msg = "The option ";
00297
00298 if (opt->getShort() != "") {
00299 msg = msg + "'" + opt->getShort() + "'";
00300 }
00301
00302 if (opt->getLong() != "") {
00303 msg = msg + " [ " + opt->getLong() + " ] ";
00304 }
00305
00306 msg += "requires an argument but it was not given";
00307 return NException(msg, NException::BASE);
00308 }
00309
00310
00311
00312 template <typename HandlerType>
00313 char **NGetOpt<HandlerType>::addValue(NOpt<HandlerType> *opt, nint32 pos, char **list) {
00314 NString tmp;
00315 assert(opt);
00316
00317 list++;
00318 if (!*list || isLongOpt(*list) || isShortOpt(*list)) {
00319 throw valueErr(opt);
00320 }
00321
00322 opt->addValue(*list);
00323 return list;
00324 }
00325
00326
00327 template <typename HandlerType>
00328 void NGetOpt<HandlerType>::showUsage(void) {
00329 NMessage::print() << LIGHT_WHITE << "Usage:";
00330 for (typename NOptList::iterator i = m_opts.begin();
00331 i != m_opts.end();
00332 i++)
00333 {
00334 NString tmp;
00335 NString msg = "\t";
00336
00337 if (i->getShort() != "") {
00338 msg = msg + LIGHT_GREEN + "-" + i->getShort();
00339
00340 if (i->getLong() != "") {
00341 msg = msg + RESET + " [ " + LIGHT_GREEN + "--" + i->getLong() + RESET + " ] ";
00342 }
00343 }
00344 else {
00345 if (i->getLong() != "") {
00346 msg = msg + LIGHT_GREEN + "--" + i->getLong() + RESET;
00347 }
00348 }
00349
00350 if (i->hasOpt()) {
00351 msg = msg + LIGHT_CYAN + "< value > ";
00352 }
00353
00354 NMessage::print() << msg;
00355 }
00356 }
00357
00358
00359 template <typename HandlerType>
00360 void NGetOpt<HandlerType>::showHelp(void) {
00361 NMessage::print() << LIGHT_WHITE << "Help:";
00362 for (typename NOptList::iterator i = m_opts.begin();
00363 i != m_opts.end();
00364 i++)
00365 {
00366 NString msg = "\t";
00367
00368 if (i->getLong() != "") {
00369 msg = msg + LIGHT_GREEN + " --" + i->getLong() + RESET + " ";
00370 }
00371
00372 if (i->getShort() != "") {
00373 msg = msg + "(" + LIGHT_GREEN "-" + i->getShort() + RESET + " short option)";
00374
00375 }
00376
00377 msg += "\n\t\t";
00378 msg += i->getHelp();
00379 msg += "\n";
00380
00381 NMessage::print() << msg;
00382 }
00383 }
00384
00385 template <typename HandlerType>
00386 void NGetOpt<HandlerType>::help(void) {
00387 showUsage();
00388 NMessage::print();
00389 showHelp();
00390 }
00391
00392
00393 template <typename HandlerType>
00394 bool NGetOpt<HandlerType>::proccess(void) {
00395 typename NOpt<HandlerType>::Handler method;
00396 NOpt<HandlerType> opt;
00397 NString tmp;
00398 char **local_argv = m_argv;
00399
00400 if (m_argc <= m_min_args) {
00401 help();
00402 return false;
00403 }
00404
00405 local_argv++;
00406 for (nint32 i = 1; i <= m_argc; i++, local_argv++) {
00407 tmp = *local_argv;
00408
00409 opt = getOptByName(tmp);
00410 if (!opt.isNull()) {
00411 if (opt.hasOpt()) {
00412 local_argv = addValue(&opt, i, local_argv);
00413 i++;
00414 }
00415
00416 m_passed.append(opt);
00417 }
00418 else {
00419 NWarning::print() << "Invalid option " << tmp;
00420 help();
00421
00422 return false;
00423
00424 }
00425 }
00426
00427
00428 for (typename NOptList::iterator i = m_passed.begin();
00429 i != m_passed.end();
00430 i++)
00431 {
00432 method = i->getHandler();
00433 if (!method) {
00434 help();
00435 return false;
00436 }
00437 else {
00438 if (!(m_handler->*method)(*i)) {
00439 return false;
00440 };
00441 }
00442 }
00443
00444 return true;
00445
00446 }
00447
00448 #endif // NGETOPT_HPP