CVC3  2.4.1
command_line_flags.h
Go to the documentation of this file.
1 /*****************************************************************************/
2 /*!
3  * \file command_line_flags.h
4  *
5  * Author: Sergey Berezin
6  *
7  * Created: Mon Feb 10 16:22:00 2003
8  *
9  * <hr>
10  *
11  * License to use, copy, modify, sell and/or distribute this software
12  * and its documentation for any purpose is hereby granted without
13  * royalty, subject to the terms and conditions defined in the \ref
14  * LICENSE file provided with this distribution.
15  *
16  * <hr>
17  *
18  */
19 /*****************************************************************************/
20 
21 #ifndef _cvc3__command_line_flags_h_
22 #define _cvc3__command_line_flags_h_
23 
24 #include <sstream>
25 #include <cstring>
26 #include <vector>
27 #include <map>
28 #include "command_line_exception.h"
29 #include "debug.h"
30 
31 namespace CVC3 {
32 
33  //! Different types of command line flags
34  typedef enum {
39  CLFLAG_STRVEC //!< Vector of pair<string, bool>
40  } CLFlagType;
41 
42  /*!
43  Class CLFlag (for Command Line Flag)
44 
45  Author: Sergey Berezin
46 
47  Date: Fri May 30 14:10:48 2003
48 
49  This class implements a data structure to hold a value of a single
50  command line flag.
51  */
52 
53 class CLFlag {
54  private:
55  //! Type of the argument
57  //! The argument
58  union {
59  bool b;
60  int i;
61  std::string* s;
62  std::vector<std::pair<std::string,bool> >* sv;
63  } d_data;
64  //! This tag is set to true when the flag is assigned a new value
65  bool d_modified;
66  //! Help string
67  std::string d_help;
68  //! Whether to display this flag when user invokes cvc3 -h
69  bool d_display;
70  public:
71  //! Constructor for a boolean flag
72  CLFlag(bool b, const std::string& help, bool display = true)
74  { d_data.b = b; }
75  //! Constructor for an integer flag
76  CLFlag(int i, const std::string& help, bool display = true)
78  { d_data.i = i; }
79  //! Constructor for a string flag
80  CLFlag(const std::string& s, const std::string& help, bool display = true)
82  d_data.s = new std::string(s);
83  }
84  //! Constructor for a string flag from char*
85  CLFlag(const char* s, const std::string& help, bool display = true)
87  d_data.s = new std::string((char*)s);
88  }
89  //! Constructor for a vector flag
90  CLFlag(const std::vector<std::pair<std::string,bool> >& sv,
91  const std::string& help, bool display = true)
93  d_data.sv = new std::vector<std::pair<std::string,bool> >(sv);
94  }
95  //! Default constructor
96  CLFlag(): d_tp(CLFLAG_NULL), d_modified(0), d_help("Undefined flag"), d_display(false) { }
97  //! Copy constructor
98  CLFlag(const CLFlag& f)
100  switch(d_tp) {
101  case CLFLAG_STRING:
102  d_data.s = new std::string(*f.d_data.s); break;
103  case CLFLAG_STRVEC:
104  d_data.sv = new std::vector<std::pair<std::string,bool> >(*f.d_data.sv); break;
105  default: d_data = f.d_data;
106  }
107  }
108  //! Destructor
110  switch(d_tp) {
111  case CLFLAG_STRING: delete d_data.s; break;
112  case CLFLAG_STRVEC: delete d_data.sv; break;
113  default: break;// Nothing to do
114  }
115  }
116  //! Assignment from another flag
117  CLFlag& operator=(const CLFlag& f) {
118  if(this == &f) return *this; // Self-assignment
119  // Try to preserve the existing heap objects if possible
120  if(d_tp == f.d_tp) {
121  switch(d_tp) {
122  case CLFLAG_STRING: *d_data.s = *f.d_data.s; break;
123  case CLFLAG_STRVEC: *d_data.sv = *f.d_data.sv; break;
124  default: d_data = f.d_data;
125  }
126  } else {
127  switch(d_tp) {
128  case CLFLAG_STRING: delete d_data.s; break;
129  case CLFLAG_STRVEC: delete d_data.sv; break;
130  default: break;
131  }
132  switch(f.d_tp) {
133  case CLFLAG_STRING: d_data.s = new std::string(*f.d_data.s); break;
134  case CLFLAG_STRVEC:
135  d_data.sv=new std::vector<std::pair<std::string,bool> >(*f.d_data.sv);
136  break;
137  default: d_data = f.d_data;
138  }
139  }
140  d_tp = f.d_tp;
142  d_help = f.d_help;
143  d_display = f.d_display;
144  return *this;
145  }
146  //! Assignment of a boolean value
147  /*! The flag must already have the right type */
148  CLFlag& operator=(bool b) {
149  DebugAssert(d_tp == CLFLAG_BOOL, "");
150  d_data.b = b;
151  d_modified = true;
152  return *this;
153  }
154  //! Assignment of an integer value
155  /*! The flag must already have the right type */
157  DebugAssert(d_tp == CLFLAG_INT, "");
158  d_data.i = i;
159  d_modified = true;
160  return *this;
161  }
162  //! Assignment of a string value
163  /*! The flag must already have a string type. */
164  CLFlag& operator=(const std::string& s) {
166  *d_data.s = s;
167  d_modified = true;
168  return *this;
169  }
170  //! Assignment of an string value from char*
171  /*! The flag must already have a string type. */
172  CLFlag& operator=(const char* s) {
174  *d_data.s = s;
175  d_modified = true;
176  return *this;
177  }
178  //! Assignment of a string value with a boolean tag to a vector flag
179  /*! The flag must already have a vector type. The pair of
180  <string,bool> will be appended to the vector. */
181  CLFlag& operator=(const std::pair<std::string,bool>& p) {
183  d_data.sv->push_back(p);
184  d_modified = true;
185  return *this;
186  }
187  //! Assignment of a vector value
188  /*! The flag must already have a vector type. */
189  CLFlag& operator=(const std::vector<std::pair<std::string,bool> >& sv) {
191  *d_data.sv = sv;
192  d_modified = true;
193  return *this;
194  }
195  // Accessor methods
196  //! Return the type of the flag
197  CLFlagType getType() const { return d_tp; }
198  /*! @brief Return true if the flag was modified from the default
199  value (e.g. set on the command line) */
200  bool modified() const { return d_modified; }
201  //! Return true if flag should be displayed in regular help
202  bool display() const { return d_display; }
203 
204  // The value accessors return a reference. For the system-wide
205  // flags, this reference will remain valid throughout the run of the
206  // program, even if the flag's value changes. So, the reference can
207  // be cached, and the value can be checked directly (which is more
208  // efficient).
209  const bool& getBool() const {
210  DebugAssert(d_tp == CLFLAG_BOOL, "CLFlag::getBool: not a boolean flag");
211  return d_data.b;
212  }
213 
214  const int& getInt() const {
215  DebugAssert(d_tp == CLFLAG_INT, "CLFlag::getInt: not an integer flag");
216  return d_data.i;
217  }
218 
219  const std::string& getString() const {
221  "CLFlag::getString: not a string flag");
222  return *d_data.s;
223  }
224 
225  const std::vector<std::pair<std::string,bool> >& getStrVec() const {
227  "CLFlag::getStrVec: not a string vector flag");
228  return *d_data.sv;
229  }
230 
231  const std::string& getHelp() const {
232  return d_help;
233  }
234 
235 }; // end of class CLFlag
236 
237 ///////////////////////////////////////////////////////////////////////
238 // Class CLFlag (for Command Line Flag)
239 //
240 // Author: Sergey Berezin
241 // Date: Fri May 30 14:10:48 2003
242 //
243 // Database of command line flags.
244 ///////////////////////////////////////////////////////////////////////
245 
246 class CLFlags {
247  private:
248  typedef std::map<std::string, CLFlag> CharMap;
250 
251  // Private methods
252 
253  // Retrieve an existing flag for modification. The 'name' must be a
254  // full name of an existing flag.
255  CLFlag& getFlag0(const std::string& name) {
256  DebugAssert(d_map.count(name) > 0,
257  "getFlag0("+name+"): there are no flags with this name");
258  return (*d_map.find(name)).second;
259  }
260  public:
261  // Public methods
262  // Add a new flag. The name must be a complete flag name.
263  void addFlag(const std::string& name, const CLFlag& f) {
264  d_map[name] = f;
265  }
266  // Count how many flags match the name prefix
267  size_t countFlags(const std::string& name) const {
268  size_t res(0), len(name.size());
269  for(CharMap::const_iterator i=d_map.begin(), iend=d_map.end();
270  i!=iend; ++i) {
271  if(std::strncmp(name.c_str(), (*i).first.c_str(), len) == 0) res++;
272  }
273  return res;
274  }
275  // Match the name prefix and add all the matching names to the vector
276  size_t countFlags(const std::string& name,
277  std::vector<std::string>& names) const {
278  size_t res(0), len(name.size());
279  for(CharMap::const_iterator i=d_map.begin(), iend=d_map.end();
280  i!=iend; ++i) {
281  if(std::strncmp(name.c_str(), (*i).first.c_str(), len) == 0) {
282  names.push_back((*i).first);
283  res++;
284  }
285  }
286  return res;
287  }
288  // Retrieve an existing flag. The 'name' must be a full name of an
289  // existing flag.
290  const CLFlag& getFlag(const std::string& name) const {
291  DebugAssert(d_map.count(name) > 0,
292  "getFlag("+name+"): there are no flags with this name");
293  return (*d_map.find(name)).second;
294  }
295 
296  const CLFlag& operator[](const std::string& name) const {
297  return getFlag(name);
298  }
299 
300  // Setting the flag to a new value, but preserving the help string.
301  // The 'name' prefix must uniquely resolve to an existing flag.
302  void setFlag(const std::string& name, const CLFlag& f) {
303  CLFlag& oldF(getFlag0(name));
304  DebugAssert(oldF.getType() == f.getType(),
305  "setFlag("+name+"): flag type doesn't match");
306  oldF = f;
307  }
308 
309  // Variants of setFlag for all the types
310  void setFlag(const std::string& name, bool b) { getFlag0(name) = b; }
311  void setFlag(const std::string& name, int i) { getFlag0(name) = i; }
312  void setFlag(const std::string& name, const std::string& s)
313  { getFlag0(name) = s; }
314  void setFlag(const std::string& name, const char* s)
315  { getFlag0(name) = s; }
316  void setFlag(const std::string& name, const std::pair<std::string,bool>& p)
317  { getFlag0(name) = p; }
318  void setFlag(const std::string& name,
319  const std::vector<std::pair<std::string,bool> >& sv)
320  { getFlag0(name) = sv; }
321 
322 }; // end of class CLFlags
323 
324 } // end of namespace CVC3
325 
326 #endif