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