Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

parsecl.hpp

Go to the documentation of this file.
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       }; // end of class: CommandLine::Parameter
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     // Search for a unique match to the flag.
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     // Make sure there is a match.
00357     if (match == NULL) {
00358       err << "error: unrecognized flag: " << flag << std::endl;
00359       return false;
00360     }
00361     // Parse the flag.
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   // Check that all required options have been supplied.
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     }; // end of class: CommmandLine
00412 
00413   } // end of namespace: Arak::Util
00414 
00415 } // end of namespace: Arak
00416 
00417 #endif

Generated on Wed May 25 14:39:18 2005 for Arak by doxygen 1.3.6