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

Generated on Thu Apr 13 16:57:30 2006 for CVC Lite by  doxygen 1.4.4