command_line_flags.h

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file command_line_flags.h
00004  * 
00005  * Author: Sergey Berezin
00006  * 
00007  * Created: Mon Feb 10 16:22:00 2003
00008  *
00009  * <hr>
00010  *
00011  * License to use, copy, modify, sell and/or distribute this software
00012  * and its documentation for any purpose is hereby granted without
00013  * royalty, subject to the terms and conditions defined in the \ref
00014  * LICENSE file provided with this distribution.
00015  * 
00016  * <hr>
00017  * 
00018  */
00019 /*****************************************************************************/
00020 
00021 #ifndef _cvc3__command_line_flags_h_
00022 #define _cvc3__command_line_flags_h_
00023 
00024 #include <sstream>
00025 #include <vector>
00026 #include <map>
00027 #include "command_line_exception.h"
00028 #include "debug.h"
00029 
00030 namespace CVC3 {
00031 
00032   //! Different types of command line flags
00033   typedef enum {
00034     CLFLAG_NULL, 
00035     CLFLAG_BOOL,
00036     CLFLAG_INT,
00037     CLFLAG_STRING,
00038     CLFLAG_STRVEC //!< Vector of pair<string, bool>
00039   } CLFlagType;
00040 
00041   /*!
00042     Class CLFlag (for Command Line Flag)
00043 
00044     Author: Sergey Berezin
00045     
00046     Date: Fri May 30 14:10:48 2003
00047     
00048     This class implements a data structure to hold a value of a single
00049     command line flag.
00050   */
00051 
00052 class CLFlag {
00053  private:
00054   //! Type of the argument
00055   CLFlagType d_tp;
00056   //! The argument
00057   union {
00058     bool b;
00059     int i;
00060     std::string* s;
00061     std::vector<std::pair<std::string,bool> >* sv;
00062   } d_data;
00063   //! This tag is set to true when the flag is assigned a new value
00064   bool d_modified;
00065   //! Help string
00066   std::string d_help;
00067  public:
00068   //! Constructor for a boolean flag
00069   CLFlag(bool b, const std::string& help)
00070     : d_tp(CLFLAG_BOOL), d_modified(0), d_help(help)
00071     { d_data.b = b; }
00072   //! Constructor for an integer flag
00073   CLFlag(int i, const std::string& help)
00074     : d_tp(CLFLAG_INT), d_modified(0), d_help(help)
00075     { d_data.i = i; }
00076   //! Constructor for a string flag
00077   CLFlag(const std::string& s, const std::string& help)
00078     : d_tp(CLFLAG_STRING), d_modified(0), d_help(help) {
00079     d_data.s = new std::string(s);
00080   }
00081   //! Constructor for a string flag from char*
00082   CLFlag(const char* s, const std::string& help)
00083     : d_tp(CLFLAG_STRING), d_modified(0), d_help(help) {
00084     d_data.s = new std::string((char*)s);
00085   }
00086   //! Constructor for a vector flag
00087   CLFlag(const std::vector<std::pair<std::string,bool> >& sv,
00088    const std::string& help)
00089     : d_tp(CLFLAG_STRVEC), d_modified(0), d_help(help) {
00090     d_data.sv = new std::vector<std::pair<std::string,bool> >(sv);
00091   }
00092   //! Default constructor
00093   CLFlag(): d_tp(CLFLAG_NULL), d_modified(0), d_help("Undefined flag") { }
00094   //! Copy constructor
00095   CLFlag(const CLFlag& f)
00096     : d_tp(f.d_tp), d_modified(f.d_modified), d_help(f.d_help) {
00097     switch(d_tp) {
00098     case CLFLAG_STRING:
00099       d_data.s = new std::string(*f.d_data.s); break;
00100     case CLFLAG_STRVEC:
00101       d_data.sv = new std::vector<std::pair<std::string,bool> >(*f.d_data.sv); break;
00102     default: d_data = f.d_data;
00103     }
00104   }
00105   //! Destructor
00106   ~CLFlag() {
00107     switch(d_tp) {
00108     case CLFLAG_STRING: delete d_data.s; break;
00109     case CLFLAG_STRVEC: delete d_data.sv; break;
00110     default: break;// Nothing to do
00111     }
00112   }
00113   //! Assignment from another flag
00114   CLFlag& operator=(const CLFlag& f) {
00115     if(this == &f) return *this; // Self-assignment
00116     // Try to preserve the existing heap objects if possible
00117     if(d_tp == f.d_tp) {
00118       switch(d_tp) {
00119       case CLFLAG_STRING: *d_data.s = *f.d_data.s; break;
00120       case CLFLAG_STRVEC: *d_data.sv = *f.d_data.sv; break;
00121       default: d_data = f.d_data;
00122       }
00123     } else {
00124       switch(d_tp) {
00125       case CLFLAG_STRING: delete d_data.s; break;
00126       case CLFLAG_STRVEC: delete d_data.sv; break;
00127       default: break;
00128       }
00129       switch(f.d_tp) {
00130       case CLFLAG_STRING: d_data.s = new std::string(*f.d_data.s); break;
00131       case CLFLAG_STRVEC:
00132   d_data.sv=new std::vector<std::pair<std::string,bool> >(*f.d_data.sv);
00133   break;
00134       default: d_data = f.d_data;
00135       }
00136     }
00137     d_tp = f.d_tp;
00138     d_modified = f.d_modified;
00139     d_help = f.d_help;
00140     return *this;
00141   }
00142   //! Assignment of a boolean value
00143   /*! The flag must already have the right type */
00144   CLFlag& operator=(bool b) {
00145     DebugAssert(d_tp == CLFLAG_BOOL, "");
00146     d_data.b = b;
00147     d_modified = true;
00148     return *this;
00149   }
00150   //! Assignment of an integer value
00151   /*! The flag must already have the right type */
00152   CLFlag& operator=(int i) {
00153     DebugAssert(d_tp == CLFLAG_INT, "");
00154     d_data.i = i;
00155     d_modified = true;
00156     return *this;
00157   }
00158   //! Assignment of a string value
00159   /*! The flag must already have a string type. */
00160   CLFlag& operator=(const std::string& s) {
00161     DebugAssert(d_tp == CLFLAG_STRING, "");
00162     *d_data.s = s;
00163     d_modified = true;
00164     return *this;
00165   }
00166   //! Assignment of an string value from char*
00167   /*! The flag must already have a string type. */
00168   CLFlag& operator=(const char* s) {
00169     DebugAssert(d_tp == CLFLAG_STRING, "");
00170     *d_data.s = s;
00171     d_modified = true;
00172     return *this;
00173   }
00174   //! Assignment of a string value with a boolean tag to a vector flag
00175   /*! The flag must already have a vector type.  The pair of
00176     <string,bool> will be appended to the vector. */
00177   CLFlag& operator=(const std::pair<std::string,bool>& p) {
00178     DebugAssert(d_tp == CLFLAG_STRVEC, "");
00179     d_data.sv->push_back(p);
00180     d_modified = true;
00181     return *this;
00182   }
00183   //! Assignment of a vector value
00184   /*! The flag must already have a vector type. */
00185   CLFlag& operator=(const std::vector<std::pair<std::string,bool> >& sv) {
00186     DebugAssert(d_tp == CLFLAG_STRVEC, "");
00187     *d_data.sv = sv;
00188     d_modified = true;
00189     return *this;
00190   }
00191   // Accessor methods
00192   //! Return the type of the flag
00193   CLFlagType getType() const { return d_tp; }
00194   /*! @brief Return true if the flag was modified from the default
00195     value (e.g. set on the command line) */
00196   bool modified() const { return d_modified; }
00197 
00198   // The value accessors return a reference.  For the system-wide
00199   // flags, this reference will remain valid throughout the run of the
00200   // program, even if the flag's value changes.  So, the reference can
00201   // be cached, and the value can be checked directly (which is more
00202   // efficient).
00203   const bool& getBool() const {
00204     DebugAssert(d_tp == CLFLAG_BOOL, "CLFlag::getBool: not a boolean flag");
00205     return d_data.b;
00206   }
00207 
00208   const int& getInt() const {
00209     DebugAssert(d_tp == CLFLAG_INT, "CLFlag::getInt: not an integer flag");
00210     return d_data.i;
00211   }
00212 
00213   const std::string& getString() const {
00214     DebugAssert(d_tp == CLFLAG_STRING,
00215     "CLFlag::getString: not a string flag");
00216     return *d_data.s;
00217   }
00218 
00219   const std::vector<std::pair<std::string,bool> >& getStrVec() const {
00220     DebugAssert(d_tp == CLFLAG_STRVEC,
00221     "CLFlag::getStrVec: not a string vector flag");
00222     return *d_data.sv;
00223   }
00224 
00225   const std::string& getHelp() const {
00226     return d_help;
00227   }
00228 
00229 }; // end of class CLFlag
00230 
00231 ///////////////////////////////////////////////////////////////////////
00232 // Class CLFlag (for Command Line Flag)
00233 // 
00234 // Author: Sergey Berezin
00235 // Date: Fri May 30 14:10:48 2003
00236 // 
00237 // Database of command line flags.
00238 ///////////////////////////////////////////////////////////////////////
00239 
00240 class CLFlags {
00241  private:
00242   typedef std::map<std::string, CLFlag> CharMap;
00243   CharMap d_map;
00244 
00245   // Private methods
00246 
00247   // Retrieve an existing flag for modification.  The 'name' must be a
00248   // full name of an existing flag.
00249   CLFlag& getFlag0(const std::string& name) {
00250     DebugAssert(d_map.count(name) > 0,
00251     "getFlag0("+name+"): there are no flags with this name");
00252     return (*d_map.find(name)).second;
00253   }
00254  public:
00255   // Public methods
00256   // Add a new flag.  The name must be a complete flag name.
00257   void addFlag(const std::string& name, const CLFlag& f) {
00258     d_map[name] = f;
00259   }
00260   // Count how many flags match the name prefix
00261   size_t countFlags(const std::string& name) const {
00262     size_t res(0), len(name.size());
00263     for(CharMap::const_iterator i=d_map.begin(), iend=d_map.end();
00264   i!=iend; ++i) {
00265       if(strncmp(name.c_str(), (*i).first.c_str(), len) == 0) res++;
00266     }
00267     return res;
00268   }
00269   // Match the name prefix and add all the matching names to the vector
00270   size_t countFlags(const std::string& name,
00271         std::vector<std::string>& names) const {
00272     size_t res(0), len(name.size());
00273     for(CharMap::const_iterator i=d_map.begin(), iend=d_map.end();
00274   i!=iend; ++i) {
00275       if(strncmp(name.c_str(), (*i).first.c_str(), len) == 0) {
00276   names.push_back((*i).first);
00277   res++;
00278       }
00279     }
00280     return res;
00281   }
00282   // Retrieve an existing flag.  The 'name' must be a full name of an
00283   // existing flag.
00284   const CLFlag& getFlag(const std::string& name) const {
00285     DebugAssert(d_map.count(name) > 0,
00286     "getFlag("+name+"): there are no flags with this name");
00287     return (*d_map.find(name)).second;
00288   }
00289 
00290   const CLFlag& operator[](const std::string& name) const {
00291     return getFlag(name);
00292   }
00293 
00294   // Setting the flag to a new value, but preserving the help string.
00295   // The 'name' prefix must uniquely resolve to an existing flag.
00296   void setFlag(const std::string& name, const CLFlag& f) {
00297     CLFlag& oldF(getFlag0(name));
00298     DebugAssert(oldF.getType() == f.getType(),
00299     "setFlag("+name+"): flag type doesn't match");
00300     oldF = f;
00301   }
00302 
00303   // Variants of setFlag for all the types
00304   void setFlag(const std::string& name, bool b) { getFlag0(name) = b; }
00305   void setFlag(const std::string& name, int i) { getFlag0(name) = i; }
00306   void setFlag(const std::string& name, const std::string& s)
00307     { getFlag0(name) = s; }
00308   void setFlag(const std::string& name, const char* s)
00309     { getFlag0(name) = s; }
00310   void setFlag(const std::string& name, const std::pair<std::string,bool>& p)
00311     { getFlag0(name) = p; }
00312   void setFlag(const std::string& name,
00313          const std::vector<std::pair<std::string,bool> >& sv)
00314     { getFlag0(name) = sv; }
00315 
00316 }; // end of class CLFlags
00317 
00318 } // end of namespace CVC3
00319 
00320 #endif

Generated on Tue Jul 3 14:33:35 2007 for CVC3 by  doxygen 1.5.1