00001 #ifndef _PARSECL_H
00002 #define _PARSECL_H
00003
00004 #include <list>
00005 #include <vector>
00006 #include <cstring>
00007 #include <string>
00008 #include <iostream>
00009 #include <sstream>
00010 #include <typeinfo>
00011
00012 namespace Arak {
00013
00014 namespace Util {
00015
00020 class CommandLine {
00021
00022 public:
00023
00027 class Option {
00028
00029 friend class CommandLine;
00030
00031 protected:
00032
00037 const char* sflag;
00038
00043 const char* lflag;
00044
00049 const char* desc;
00050
00055 bool _supplied;
00056
00060 const bool required;
00061
00070 bool matches(const char* flag) const {
00071 int len = strlen(flag);
00072 return ((strncmp(flag, sflag, len) == 0) ||
00073 (strncmp(flag, lflag, len) == 0));
00074 }
00075
00083 virtual bool read(const char* str) {
00084 return false;
00085 }
00086
00091 virtual void printUsage(std::ostream& out) const {
00092 out << " "
00093 << sflag << "|"
00094 << lflag << " : "
00095 << desc;
00096 }
00097
00098 public:
00099
00114 Option(const char* sflag, const char* lflag, const char* desc,
00115 bool required = false)
00116 : sflag(sflag), lflag(lflag), desc(desc),
00117 _supplied(false), required(false) { }
00118
00122 virtual ~Option() { }
00123
00128 virtual bool supplied() const { return _supplied; }
00129
00133 virtual bool hasArg() { return false; }
00134
00135 };
00136
00141 template <class T>
00142 class Parameter : public Option {
00143
00144 friend class CommandLine;
00145
00146 private:
00147
00151 T val;
00152
00157 virtual void printUsage(std::ostream& out) const {
00158 out << " "
00159 << sflag << "|"
00160 << lflag << " <"
00161 << typeid(val).name() << "> : "
00162 << desc;
00163 }
00164
00165 protected:
00166
00173 virtual bool read(const char* str) {
00174 std::string string(str);
00175 std::istringstream in(string);
00176 in >> val;
00177 return !in.bad();
00178 }
00179
00180 public:
00181
00198 Parameter(const char* sflag,
00199 const char* lflag,
00200 const char* desc,
00201 const T& def,
00202 bool required = false)
00203 : Option(sflag, lflag, desc, required), val(def) { }
00204
00208 virtual ~Parameter() { }
00209
00213 const T& value() const { return val; }
00214
00218 virtual bool hasArg() { return true; }
00219
00220 };
00221
00226 template <class T>
00227 class MultiParameter : public Option {
00228
00229 friend class CommandLine;
00230
00231 private:
00232
00236 std::vector<T> vals;
00237
00242 virtual void printUsage(std::ostream& out) const {
00243 T t;
00244 out << " "
00245 << sflag << "|"
00246 << lflag << " <"
00247 << typeid(t).name() << "> : "
00248 << desc;
00249 }
00250
00251 protected:
00252
00259 virtual bool read(const char* str) {
00260 std::string string(str);
00261 std::istringstream in(string);
00262 T val;
00263 in >> val;
00264 vals.push_back(val);
00265 return !in.bad();
00266 }
00267
00268 public:
00269
00283 MultiParameter(const char* sflag,
00284 const char* lflag,
00285 const char* desc)
00286 : Option(sflag, lflag, desc, false), vals() { }
00287
00291 virtual ~MultiParameter() { }
00292
00296 const std::vector<T>& values() const { return vals; }
00297
00301 virtual bool hasArg() { return true; }
00302
00303 };
00304
00305 protected:
00306
00310 const char* name;
00311
00316 std::list<Option*> options;
00317
00318 public:
00319
00323 CommandLine() : name(""), options() { }
00324
00328 ~CommandLine() { }
00329
00338 bool parse(int argc, char** argv, std::ostream& err) {
00339 typedef std::list<Option*> OptionList;
00340 name = argv[0];
00341 for (int i = 1; i < argc; i++) {
00342 const char* flag = argv[i];
00343
00344 Option* match = NULL;
00345 for (OptionList::const_iterator it = options.begin();
00346 it != options.end(); it++) {
00347 Option* opt = *it;
00348 if (opt->matches(flag)) {
00349 if (match != NULL) {
00350 err << "error: ambiguous flag: " << flag << std::endl;
00351 return false;
00352 }
00353 match = opt;
00354 }
00355 }
00356
00357 if (match == NULL) {
00358 err << "error: unrecognized flag: " << flag << std::endl;
00359 return false;
00360 }
00361
00362 match->_supplied = true;
00363 if (match->hasArg()) {
00364 i++;
00365 const char* arg = argv[i];
00366 if (!(match->read(arg))) {
00367 err << "error: cannot parse value " << arg
00368 << " for flag " << flag << std::endl;
00369 return false;
00370 }
00371 }
00372 }
00373
00374 for (OptionList::const_iterator it = options.begin();
00375 it != options.end(); it++) {
00376 Option* opt = *it;
00377 if (opt->required && !(opt->_supplied)) {
00378 err << "error: required flag " << opt->sflag
00379 << " not supplied" << std::endl;
00380 return false;
00381 }
00382 }
00383 return true;
00384 }
00385
00391 void printUsage(std::ostream& out) const {
00392 out << name << std::endl;
00393 typedef std::list<Option*> OptionList;
00394 for (OptionList::const_iterator it = options.begin();
00395 it != options.end(); it++) {
00396 Option* opt = *it;
00397 opt->printUsage(out);
00398 out << std::endl;
00399 }
00400 }
00401
00407 void add(Option& opt) {
00408 options.push_front(&opt);
00409 }
00410
00411 };
00412
00413 }
00414
00415 }
00416
00417 #endif