Options.h

00001 // -*- mode: C++ -*-
00002 //
00003 // Copyright (C) 2006 Christian Holm Christensen <cholm@nbi.dk>
00004 //
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public License
00007 // as published by the Free Software Foundation; either version 2.1
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free
00017 // Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018 // 02111-1307 USA
00019 //
00020 //
00021 // ROOT based acquisition 
00022 //
00023 #include <iostream>
00024 #include <iomanip>
00025 #include <sstream>
00026 #include <set>
00027 #include <vector>
00028 
00029 //____________________________________________________________________
00035 template <typename T>
00036 void str2val(const std::string& str, T& v) 
00037 {
00038   std::stringstream s(str);
00039   if (str[0] == '0') {
00040     if (str[1] == 'x' || str[1] == 'X') s >> std::hex >> v;
00041     else                                s >> std::oct >> v;
00042   }
00043   else 
00044     s >> v;
00045 }
00046 
00047 //____________________________________________________________________
00053 template <typename T>
00054 void str2val(const char* str, T& v)
00055 {
00056   str2val<T>(std::string(str), v);
00057 }
00058 
00059 
00060 //____________________________________________________________________
00065 struct OptionBase
00066 {
00072   OptionBase(char s, const char* l, const char* h, bool arg)
00073     : fShort(s), 
00074       fLong(l), 
00075       fHelp(h), 
00076       fNeedArg(arg), 
00077       fSet(false)
00078   {}
00080   virtual ~OptionBase() {}
00082   bool IsSet() const { return fSet; }
00084   bool NeedArg() const { return fNeedArg; }
00086   virtual char Short() const { return fShort; }
00088   virtual const std::string& Long() const { return fLong; }
00094   virtual bool Handle(char s, const char* arg) = 0;
00100   virtual bool Handle(const std::string& l, const std::string& arg) = 0;
00102   virtual void Help() const 
00103   {
00104     std::cout << "\t-" << fShort << ",--" << fLong 
00105               << (fNeedArg ? "=ARG" : "") << "\t" << fHelp;
00106   }
00107 protected:
00109   char        fShort;
00111   std::string fLong;
00113   std::string fHelp;
00115   bool        fNeedArg;
00117   bool        fSet;
00118 };
00119   
00120 namespace std 
00121 {
00125   template <>
00126   struct less<OptionBase*> 
00127   {
00130     bool operator()(OptionBase* const & lhs, OptionBase* const & rhs) 
00131     {
00132       if (lhs->Short() == '\0' && rhs->Short())
00133         return lhs->Long() < rhs->Long();
00134       return lhs->Short() < rhs->Short();
00135     }
00136   };
00137 }
00138 
00139 //____________________________________________________________________
00143 template <typename T> 
00144 struct Option : public OptionBase
00145 {
00152   Option(char s, const char*  l, const char* h, const T& v=T(), bool arg=true)
00153     : OptionBase(s, l, h, arg),
00154       fValue(v)
00155   {}
00161   bool Handle(char s, const char* arg) 
00162   {
00163     if (s != fShort) return false;
00164     if (!fNeedArg)   {
00165       std::stringstream s;
00166       s << true;
00167       s >> fValue;
00168       return fSet = true;
00169     }
00170     if (!arg)        return true;
00171     str2val(arg, fValue);
00172     return fSet = true;
00173   }
00179   bool Handle(const std::string& l, const std::string& arg) 
00180   {
00181     if (l != fLong) return false;
00182     if (!fNeedArg)   {
00183       std::stringstream s;
00184       s << true;
00185       s >> fValue;
00186       return fSet = true;
00187     }
00188     str2val(arg, fValue);
00189     return fSet = true;
00190   }
00192   const T& Value() const { return fValue; }
00194   void Help() const 
00195   {
00196     OptionBase::Help();
00197     if (NeedArg()) {
00198       std::cout << "\t[";
00199       if (!IsSet()) std::cout << "default: ";
00200       std::cout  << fValue << "]";
00201     }
00202     std::cout << std::endl;
00203   }
00206   const T* operator->() const { return &fValue; }
00209   operator const T&() const { return fValue; }
00213   Option<T>& operator=(const T& v) { fValue = v; return *this; }
00214 private: 
00216   T fValue;
00217 };
00218 
00219 //____________________________________________________________________
00224 struct CommandLine
00225 {
00228   CommandLine(const char* args="") : fArg(args) {}
00233   bool Process(int argc, char** argv) 
00234   {
00235     fProg = argv[0];
00236     int ret = 0;
00237     for (int i = 1; i < argc; i++) {
00238       if (argv[i][0] == '-') {
00239         if (argv[i][1] == '-') {
00240           std::string opt, val;
00241           GetLong(argv[i], opt, val);
00242           ret = CheckOptions(opt, val);
00243         }
00244         else 
00245           ret = CheckOptions(argv[i][1], argv[i+1]);
00246         if (ret < 0) {
00247           std::cerr << fProg << ": Unknown option '" << argv[i] 
00248                     << "', try '" << fProg << " --help'" 
00249                     << std::endl;
00250           return false;
00251         }
00252         if (ret > 0) {
00253           ret = 0; 
00254           i++;
00255         }
00256       }
00257       else fRemain.push_back(argv[i]);
00258     }
00259     return true;
00260   }
00262   std::vector<std::string>& Remain() { return fRemain; }
00265   void Add(OptionBase& option) 
00266   {
00267     fList.insert(&option);
00268   }
00270   void Help() const
00271   {
00272     std::cout << "Usage: " << fProg << " [OPTIONS] " << fArg << "\n\n" 
00273               << "Options:"  << std::endl;
00274     for (OptionList::const_iterator i = fList.begin(); i != fList.end(); i++) 
00275       (*i)->Help();
00276     std::cout << std::endl;
00277   }
00278 protected:
00283   void GetLong(const char* str, std::string& opt, std::string& val) 
00284   {
00285     std::string arg(str);
00286     size_t eq = arg.find("=");
00287     if (eq != std::string::npos) {
00288       opt = arg.substr(0, eq);
00289       val = arg.substr(eq+1, arg.size() - eq);
00290     }
00291     else 
00292       opt = arg;
00293     opt.erase(0,2);
00294   }
00302   int CheckOptions(const std::string& opt, const std::string& arg) 
00303   {
00304     for (OptionList::iterator i = fList.begin(); i != fList.end(); i++) 
00305       if ((*i)->Handle(opt, arg)) return 0;
00306     return -1;
00307   }
00315   int CheckOptions(char s, const char* arg) 
00316   {
00317     for (OptionList::iterator i = fList.begin(); i != fList.end(); i++) {
00318       if ((*i)->Handle(s, arg)) { 
00319         if ((*i)->NeedArg()) return 1;
00320         return 0;
00321       }
00322     }
00323     return -1;
00324   }
00326   std::string fArg;
00328   std::string fProg;
00330   typedef std::set<OptionBase*> OptionList;
00332   OptionList fList;
00334   std::vector<std::string> fRemain;
00335 };
00336   
00337 //____________________________________________________________________
00338 //
00339 // EOF
00340 //
Top of page Last update Fri Apr 27 01:54:15 2007
Copyright © 2004 Christian Holm Created by DoxyGen 1.3.5