ORTS

Options.H

Go to the documentation of this file.
00001 #ifndef Options_H
00002 #define Options_H
00003 
00004 /** @file Options.H
00005     Command line options.
00006 
00007     $Id: Options.H 5817 2007-09-12 23:59:14Z sorsten $
00008     $Source$
00009 */
00010 
00011 // This is an ORTS file (c) Michael Buro, licensed under the GPL
00012 
00013 #include "Global.H"
00014 
00015 //===================================================================
00016 
00017 /** Base class for command line option. */
00018 class Opt {
00019 
00020 public:
00021 
00022   std::string remark;
00023   bool param;
00024   
00025   /** Parse option value from string.
00026       @return true on error
00027   */
00028   virtual bool from_string(const std::string &s) = 0;
00029   virtual std::string to_string() const = 0;
00030   virtual std::string get_type_name() const = 0;
00031 
00032   Opt() : param(true) {}
00033   virtual ~Opt() {}
00034 };
00035 
00036 //===================================================================
00037 
00038 /** Command line option. */
00039 template <class T> class OptT : public Opt
00040 {
00041 public:
00042   
00043   T value;
00044 
00045   OptT(T v) { value = v; }
00046 
00047   std::string to_string() const;
00048   bool from_string(const std::string &s);
00049   std::string get_type_name() const;
00050   
00051   static std::string type_name;
00052 };
00053 
00054 //===================================================================
00055 
00056 /** Command line option parser. */
00057 class Options {
00058 
00059 public:
00060 
00061   typedef std::map<std::string, Opt*> OMap;
00062   typedef OMap::iterator OMapIt;
00063   typedef OMap::const_iterator OMapCIt;  
00064 
00065 protected:
00066 
00067   static Vector<std::string> heading_name;
00068   static Vector<OMap> options;
00069   static OMap s_omap;
00070 
00071   OMap *omap;
00072 
00073   template <class T> struct Type {
00074     static std::string name;
00075   };
00076   
00077 public:
00078 
00079   /** Add an option that takes a parameter. */
00080 
00081   template <class T>
00082   void put(const char *skey, T v, const char *remark=0)
00083   {
00084     std::string key(skey);
00085     OMapIt oit = s_omap.find(key);
00086 
00087     if (oit == s_omap.end()) {
00088 
00089       if (!remark) {
00090         errstr << "remark missing: " << skey << std::endl;
00091         ERR("");
00092       }
00093       
00094       // new entry
00095       OptT<T> *o = new OptT<T>(v);
00096       o->remark = std::string(remark);
00097       s_omap[key] = o;
00098       (*omap)[key] = o;
00099       return;
00100     }
00101 
00102     // entry found, check type
00103 
00104     OptT<T> *o = dynamic_cast<OptT<T>*>(oit->second);
00105 
00106     if (!o) {
00107       errstr << "different type for option " << skey << " - " << remark << std::endl;      
00108       abort(); exit(20);
00109     }
00110 
00111     // when redefining skey, type and value have to match
00112     
00113     if (remark && o->value != v) {
00114       OptT<T> temp(v);
00115       errstr << "different value for option " << skey << ": was " << o->to_string() << ", now: " << temp.to_string() << std::endl;
00116       abort(); exit(20);
00117     }
00118 
00119     o->value = v; // overwrite
00120   }
00121 
00122   //-------------------------------------------------------------------
00123 
00124   /** Add a flag - does not take any parameters. */
00125 
00126   void put(const char *skey, const char *remark=0)
00127   {
00128     std::string key(skey);
00129     OMapIt oit = s_omap.find(key);
00130 
00131     if (oit == s_omap.end()) {
00132 
00133       if (!remark) {
00134         errstr << "remark missing: " << skey << std::endl;
00135         ERR("");
00136       }
00137       
00138       // new entry
00139       OptT<bool> *o = new OptT<bool>(false);
00140       o->remark = std::string(remark);
00141       s_omap[key] = o;
00142       (*omap)[key] = o;
00143       o->param = false;
00144       return;
00145     }
00146 
00147     // entry found, check type
00148 
00149     OptT<bool> *o = dynamic_cast<OptT<bool>*>(oit->second);
00150 
00151     if (!o) {
00152       errstr << "different type for option " << skey << " - " << remark << std::endl;      
00153       ERR("");
00154     }
00155 
00156     // when redefining skey, type and value have to match
00157     
00158     if (remark && o->value != false) {
00159       errstr << "different value for option " << skey << ": was " << o->value << ", now: " << false << std::endl;
00160       ERR("");
00161     }
00162 
00163     o->value = false; // overwrite    
00164   }
00165 
00166   //-------------------------------------------------------------------
00167 
00168   /** Get value of option.
00169       @param key          Name of the option to extract.
00170       @param v            Location to store the retrieved value.
00171       @param bReportErr
00172       If true, then function reports errors (ERR iff illegal).
00173       If false, the function returns true on errors.
00174       This is useful in cases where we would like to fail silently or
00175       report/handle the error in the calling code.
00176   */
00177   template <class T>
00178   static bool get(const std::string &key, T &v, bool bReportErr = true)
00179   {
00180     OMapCIt oit = s_omap.find(key);
00181 
00182     if (oit == s_omap.end()) {
00183       // not found
00184       if (bReportErr) {
00185         errstr << "option not found: " << key << std::endl;
00186         ERR("");
00187       }
00188       return true;
00189     }      
00190     
00191     OptT<T> *o = dynamic_cast<OptT<T>*>(oit->second);
00192     if (!o) {
00193       // illegal type
00194       if (bReportErr) {
00195         errstr << "illegal value type for option " << key << ": expected "
00196                << oit->second->get_type_name() << ", got " << Type<T>::name << std::endl;
00197         ERR("");
00198       }
00199       return true;
00200     }
00201 
00202     v = o->value;
00203     return false;
00204   }
00205 
00206   //-------------------------------------------------------------------
00207 
00208   template <class T>
00209   static bool set(const std::string &key, T v, bool bReportErr = true)
00210   {
00211     OMapCIt oit = s_omap.find(key);
00212 
00213     if (oit == s_omap.end()) {
00214       // not found
00215       if (bReportErr) {
00216         errstr << "option not found: " << key << std::endl;
00217         ERR("");
00218       }
00219       return true;
00220     }      
00221     
00222     OptT<T> *o = dynamic_cast<OptT<T>*>(oit->second);
00223     if (!o) {
00224       // illegal type
00225       if (bReportErr) {
00226         errstr << "illegal value type for option " << key << ": expected "
00227                << oit->second->get_type_name() << ", got " << Type<T>::name << std::endl;
00228         ERR("");
00229       }
00230       return true;
00231     }
00232 
00233     o->value = v;
00234     return false;
00235   }
00236 
00237   // write options to stream
00238   static void write(std::ostream &os);
00239   
00240   // clears all options
00241   static void reset();
00242   
00243   // @return false iff OK
00244   static bool process(sint4 argc, char **argv, std::ostream &oserr, const char *remark=0);
00245   // return non-options in rest (useful for mandatory parameters)
00246   static bool process2(sint4 argc, char **argv, std::ostream &oserr, Vector<std::string> &rest);
00247   static bool process(const std::string& args , std::ostream &oserr, const char *remark);
00248 
00249   Options(std::string heading="");
00250   virtual ~Options();
00251 
00252 private:
00253 
00254   // prevent copying and assigning (not implemented yet)
00255   Options(const Options &) {}
00256   //  Options &operator=(const Options &) {}
00257 };
00258 
00259 //===================================================================
00260 
00261 REGISTER_TYPEOF(20, Options::OMap::iterator);
00262 REGISTER_TYPEOF(21, Options::OMap::const_iterator);
00263 REGISTER_TYPEOF(22, Vector<Options::OMap>::iterator);
00264 REGISTER_TYPEOF(23, Vector<Options::OMap>::const_iterator);
00265 
00266 #endif


Generated on Fri May 18 2012 03:02:43 for ORTS by Doxygen1.7.3