/*****************************************************************************/ /*! * \file command_line_flags.h * * Author: Sergey Berezin * * Created: Mon Feb 10 16:22:00 2003 * *
* * License to use, copy, modify, sell and/or distribute this software * and its documentation for any purpose is hereby granted without * royalty, subject to the terms and conditions defined in the \ref * LICENSE file provided with this distribution. * *
* */ /*****************************************************************************/ #ifndef _cvc3__command_line_flags_h_ #define _cvc3__command_line_flags_h_ #include #include #include #include "command_line_exception.h" #include "debug.h" namespace CVC3 { //! Different types of command line flags typedef enum { CLFLAG_NULL, CLFLAG_BOOL, CLFLAG_INT, CLFLAG_STRING, CLFLAG_STRVEC //!< Vector of pair } CLFlagType; /*! Class CLFlag (for Command Line Flag) Author: Sergey Berezin Date: Fri May 30 14:10:48 2003 This class implements a data structure to hold a value of a single command line flag. */ class CLFlag { private: //! Type of the argument CLFlagType d_tp; //! The argument union { bool b; int i; std::string* s; std::vector >* sv; } d_data; //! This tag is set to true when the flag is assigned a new value bool d_modified; //! Help string std::string d_help; public: //! Constructor for a boolean flag CLFlag(bool b, const std::string& help) : d_tp(CLFLAG_BOOL), d_modified(0), d_help(help) { d_data.b = b; } //! Constructor for an integer flag CLFlag(int i, const std::string& help) : d_tp(CLFLAG_INT), d_modified(0), d_help(help) { d_data.i = i; } //! Constructor for a string flag CLFlag(const std::string& s, const std::string& help) : d_tp(CLFLAG_STRING), d_modified(0), d_help(help) { d_data.s = new std::string(s); } //! Constructor for a string flag from char* CLFlag(const char* s, const std::string& help) : d_tp(CLFLAG_STRING), d_modified(0), d_help(help) { d_data.s = new std::string((char*)s); } //! Constructor for a vector flag CLFlag(const std::vector >& sv, const std::string& help) : d_tp(CLFLAG_STRVEC), d_modified(0), d_help(help) { d_data.sv = new std::vector >(sv); } //! Default constructor CLFlag(): d_tp(CLFLAG_NULL), d_modified(0), d_help("Undefined flag") { } //! Copy constructor CLFlag(const CLFlag& f) : d_tp(f.d_tp), d_modified(f.d_modified), d_help(f.d_help) { switch(d_tp) { case CLFLAG_STRING: d_data.s = new std::string(*f.d_data.s); break; case CLFLAG_STRVEC: d_data.sv = new std::vector >(*f.d_data.sv); break; default: d_data = f.d_data; } } //! Destructor ~CLFlag() { switch(d_tp) { case CLFLAG_STRING: delete d_data.s; break; case CLFLAG_STRVEC: delete d_data.sv; break; default: break;// Nothing to do } } //! Assignment from another flag CLFlag& operator=(const CLFlag& f) { if(this == &f) return *this; // Self-assignment // Try to preserve the existing heap objects if possible if(d_tp == f.d_tp) { switch(d_tp) { case CLFLAG_STRING: *d_data.s = *f.d_data.s; break; case CLFLAG_STRVEC: *d_data.sv = *f.d_data.sv; break; default: d_data = f.d_data; } } else { switch(d_tp) { case CLFLAG_STRING: delete d_data.s; break; case CLFLAG_STRVEC: delete d_data.sv; break; default: break; } switch(f.d_tp) { case CLFLAG_STRING: d_data.s = new std::string(*f.d_data.s); break; case CLFLAG_STRVEC: d_data.sv=new std::vector >(*f.d_data.sv); break; default: d_data = f.d_data; } } d_tp = f.d_tp; d_modified = f.d_modified; d_help = f.d_help; return *this; } //! Assignment of a boolean value /*! The flag must already have the right type */ CLFlag& operator=(bool b) { DebugAssert(d_tp == CLFLAG_BOOL, ""); d_data.b = b; d_modified = true; return *this; } //! Assignment of an integer value /*! The flag must already have the right type */ CLFlag& operator=(int i) { DebugAssert(d_tp == CLFLAG_INT, ""); d_data.i = i; d_modified = true; return *this; } //! Assignment of a string value /*! The flag must already have a string type. */ CLFlag& operator=(const std::string& s) { DebugAssert(d_tp == CLFLAG_STRING, ""); *d_data.s = s; d_modified = true; return *this; } //! Assignment of an string value from char* /*! The flag must already have a string type. */ CLFlag& operator=(const char* s) { DebugAssert(d_tp == CLFLAG_STRING, ""); *d_data.s = s; d_modified = true; return *this; } //! Assignment of a string value with a boolean tag to a vector flag /*! The flag must already have a vector type. The pair of will be appended to the vector. */ CLFlag& operator=(const std::pair& p) { DebugAssert(d_tp == CLFLAG_STRVEC, ""); d_data.sv->push_back(p); d_modified = true; return *this; } //! Assignment of a vector value /*! The flag must already have a vector type. */ CLFlag& operator=(const std::vector >& sv) { DebugAssert(d_tp == CLFLAG_STRVEC, ""); *d_data.sv = sv; d_modified = true; return *this; } // Accessor methods //! Return the type of the flag CLFlagType getType() const { return d_tp; } /*! @brief Return true if the flag was modified from the default value (e.g. set on the command line) */ bool modified() const { return d_modified; } // The value accessors return a reference. For the system-wide // flags, this reference will remain valid throughout the run of the // program, even if the flag's value changes. So, the reference can // be cached, and the value can be checked directly (which is more // efficient). const bool& getBool() const { DebugAssert(d_tp == CLFLAG_BOOL, "CLFlag::getBool: not a boolean flag"); return d_data.b; } const int& getInt() const { DebugAssert(d_tp == CLFLAG_INT, "CLFlag::getInt: not an integer flag"); return d_data.i; } const std::string& getString() const { DebugAssert(d_tp == CLFLAG_STRING, "CLFlag::getString: not a string flag"); return *d_data.s; } const std::vector >& getStrVec() const { DebugAssert(d_tp == CLFLAG_STRVEC, "CLFlag::getStrVec: not a string vector flag"); return *d_data.sv; } const std::string& getHelp() const { return d_help; } }; // end of class CLFlag /////////////////////////////////////////////////////////////////////// // Class CLFlag (for Command Line Flag) // // Author: Sergey Berezin // Date: Fri May 30 14:10:48 2003 // // Database of command line flags. /////////////////////////////////////////////////////////////////////// class CLFlags { private: typedef std::map CharMap; CharMap d_map; // Private methods // Retrieve an existing flag for modification. The 'name' must be a // full name of an existing flag. CLFlag& getFlag0(const std::string& name) { DebugAssert(d_map.count(name) > 0, "getFlag0("+name+"): there are no flags with this name"); return (*d_map.find(name)).second; } public: // Public methods // Add a new flag. The name must be a complete flag name. void addFlag(const std::string& name, const CLFlag& f) { d_map[name] = f; } // Count how many flags match the name prefix size_t countFlags(const std::string& name) const { size_t res(0), len(name.size()); for(CharMap::const_iterator i=d_map.begin(), iend=d_map.end(); i!=iend; ++i) { if(strncmp(name.c_str(), (*i).first.c_str(), len) == 0) res++; } return res; } // Match the name prefix and add all the matching names to the vector size_t countFlags(const std::string& name, std::vector& names) const { size_t res(0), len(name.size()); for(CharMap::const_iterator i=d_map.begin(), iend=d_map.end(); i!=iend; ++i) { if(strncmp(name.c_str(), (*i).first.c_str(), len) == 0) { names.push_back((*i).first); res++; } } return res; } // Retrieve an existing flag. The 'name' must be a full name of an // existing flag. const CLFlag& getFlag(const std::string& name) const { DebugAssert(d_map.count(name) > 0, "getFlag("+name+"): there are no flags with this name"); return (*d_map.find(name)).second; } const CLFlag& operator[](const std::string& name) const { return getFlag(name); } // Setting the flag to a new value, but preserving the help string. // The 'name' prefix must uniquely resolve to an existing flag. void setFlag(const std::string& name, const CLFlag& f) { CLFlag& oldF(getFlag0(name)); DebugAssert(oldF.getType() == f.getType(), "setFlag("+name+"): flag type doesn't match"); oldF = f; } // Variants of setFlag for all the types void setFlag(const std::string& name, bool b) { getFlag0(name) = b; } void setFlag(const std::string& name, int i) { getFlag0(name) = i; } void setFlag(const std::string& name, const std::string& s) { getFlag0(name) = s; } void setFlag(const std::string& name, const char* s) { getFlag0(name) = s; } void setFlag(const std::string& name, const std::pair& p) { getFlag0(name) = p; } void setFlag(const std::string& name, const std::vector >& sv) { getFlag0(name) = sv; } }; // end of class CLFlags } // end of namespace CVC3 #endif