wibble  1.1
options.h
Go to the documentation of this file.
1 #ifndef WIBBLE_COMMANDLINE_OPTIONS_H
2 #define WIBBLE_COMMANDLINE_OPTIONS_H
3 
5 #include <string>
6 #include <vector>
7 
8 namespace wibble {
9 namespace commandline {
10 
11 // Types of values for the command line options
12 
13 struct Bool
14 {
15  typedef bool value_type;
16  static bool parse(const std::string& val);
17 
18  static bool toBool(const value_type& val);
19  static int toInt(const value_type& val);
20  static std::string toString(const value_type& val);
21  static bool init_val;
22 };
23 
24 struct Int
25 {
26  typedef int value_type;
27  static int parse(const std::string& val);
28 
29  static bool toBool(const value_type& val);
30  static int toInt(const value_type& val);
31  static std::string toString(const value_type& val);
32  static int init_val;
33 };
34 
35 struct String
36 {
37  typedef std::string value_type;
38  static std::string parse(const std::string& val);
39 
40  static bool toBool(const value_type& val);
41  static int toInt(const value_type& val);
42  static std::string toString(const value_type& val);
43  static std::string init_val;
44 };
45 
47 {
48  typedef std::string value_type;
49  static std::string parse(const std::string& val);
50  static std::string toString(const value_type& val);
51  static std::string init_val;
52 };
53 
55 class Option : public Managed
56 {
57  std::string m_name;
58  mutable std::string m_fullUsage;
59 
60 protected:
61  bool m_isset;
62 
63  Option(const std::string& name) : m_name(name), m_isset(false), hidden(false) {}
64  Option(const std::string& name,
65  char shortName,
66  const std::string& longName,
67  const std::string& usage = std::string(),
68  const std::string& description = std::string())
69  : m_name(name), m_isset(false), usage(usage), description(description), hidden(false)
70  {
71  if (shortName != 0)
72  shortNames.push_back(shortName);
73  if (!longName.empty())
74  longNames.push_back(longName);
75  }
76 
89 
95  virtual bool parse(const std::string& param) = 0;
96 
101  virtual void parse_noarg() = 0;
102 
104  virtual bool arg_is_optional() const { return false; }
105 
106 public:
107  Option();
108  virtual ~Option() {}
109 
110  bool isSet() const { return m_isset; }
111  const std::string& name() const { return m_name; }
112 
113  void addAlias(char c) { shortNames.push_back(c); }
114  void addAlias(const std::string& str) { longNames.push_back(str); }
115 
117  const std::string& fullUsage() const;
118  std::string fullUsageForMan() const;
119 
120  std::vector<char> shortNames;
121  std::vector<std::string> longNames;
122 
123  std::string usage;
124  std::string description;
125 
126  // Set to true if the option should not be documented
127  bool hidden;
128 
129  friend class OptionGroup;
130  friend class Engine;
131 };
132 
134 class BoolOption : public Option
135 {
136  bool m_value;
137 
138 protected:
139  BoolOption(const std::string& name)
140  : Option(name), m_value(false) {}
141  BoolOption(const std::string& name,
142  char shortName,
143  const std::string& longName,
144  const std::string& usage = std::string(),
145  const std::string& description = std::string())
146  : Option(name, shortName, longName, usage, description), m_value(false) {}
147 
149  virtual bool parse(const std::string&) { parse_noarg(); return false; }
150  virtual void parse_noarg() { m_isset = true; m_value = true; }
151 
152 public:
153  bool boolValue() const { return m_value; }
154  std::string stringValue() const { return m_value ? "true" : "false"; }
155 
156  friend class OptionGroup;
157  friend class Engine;
158 };
159 
160 template<typename T>
161 class SingleOption : public Option
162 {
163 protected:
164  typename T::value_type m_value;
165 
166  SingleOption(const std::string& name)
167  : Option(name), m_value(T::init_val)
168  {
169  usage = "<val>";
170  }
171  SingleOption(const std::string& name,
172  char shortName,
173  const std::string& longName,
174  const std::string& usage = std::string(),
175  const std::string& description = std::string())
176  : Option(name, shortName, longName, usage, description)
177  {
178  if (usage.empty())
179  this->usage = "<val>";
180  }
181 
183  {
184  if (begin == list.end())
185  throw exception::BadOption("option requires an argument");
186  m_value = T::parse(*begin);
187  m_isset = true;
188  // Remove the parsed element
189  return list.eraseAndAdvance(begin);
190  }
191  bool parse(const std::string& param)
192  {
193  m_value = T::parse(param);
194  m_isset = true;
195  return true;
196  }
197  void parse_noarg()
198  {
199  throw exception::BadOption("option requires an argument");
200  }
201 
202 public:
203  void setValue( const typename T::value_type &a ) {
204  m_value = a;
205  }
206 
207  typename T::value_type value() const { return m_value; }
208 
209  // Deprecated
210  bool boolValue() const { return T::toBool(m_value); }
211  int intValue() const { return T::toInt(m_value); }
212  std::string stringValue() const { return T::toString(m_value); }
213 
214  friend class OptionGroup;
215  friend class Engine;
216 };
217 
224 template<typename T>
226 {
227 protected:
228  typename T::value_type m_value;
229  bool m_hasval;
230 
231  SingleOptvalOption(const std::string& name)
232  : Option(name)
233  {
234  usage = "<val>";
235  }
236  SingleOptvalOption(const std::string& name,
237  char shortName,
238  const std::string& longName,
239  const std::string& usage = std::string(),
240  const std::string& description = std::string())
241  : Option(name, 0, longName, usage, description)
242  {
243  if (shortName != 0)
245  "creating option " + name + " with optional value"
246  "short options with optional values are not allowed");
247  if (usage.empty())
248  this->usage = "<val>";
249  }
250 
252  {
254  "parsing option with optional value"
255  "short options with optional values are not allowed");
256  }
257  bool parse(const std::string& param)
258  {
259  m_value = T::parse(param);
260  m_isset = true;
261  m_hasval = true;
262  return true;
263  }
264  void parse_noarg()
265  {
266  m_isset = true;
267  m_hasval = false;
268  }
269 
270  virtual bool arg_is_optional() const { return true; }
271 
272 public:
273  bool hasValue() const { return m_hasval; }
274 
275  void setValue( const typename T::value_type &a ) {
276  m_value = a;
277  }
278 
279  typename T::value_type value() const { return m_value; }
280 
281  friend class OptionGroup;
282  friend class Engine;
283 };
284 
285 // Option needing a compulsory string value
287 
288 // Option with an optional string value
290 
291 // Option needing a compulsory int value
293 
294 // Option with an optional int value
296 
299 
302 
303 
304 // Option that can be specified multiple times
305 template<typename T>
306 class VectorOption : public Option
307 {
308  std::vector< typename T::value_type > m_values;
309 
310 protected:
311  VectorOption(const std::string& name)
312  : Option(name)
313  {
314  usage = "<val>";
315  }
316  VectorOption(const std::string& name,
317  char shortName,
318  const std::string& longName,
319  const std::string& usage = std::string(),
320  const std::string& description = std::string())
321  : Option(name, shortName, longName, usage, description)
322  {
323  if (usage.empty())
324  this->usage = "<val>";
325  }
326 
328  {
329  if (begin == list.end())
330  throw exception::BadOption("no string argument found");
331  m_isset = true;
332  m_values.push_back(T::parse(*begin));
333  // Remove the parsed element
334  return list.eraseAndAdvance(begin);
335  }
336  bool parse(const std::string& param)
337  {
338  m_isset = true;
339  m_values.push_back(T::parse(param));
340  return true;
341  }
342  void parse_noarg()
343  {
344  throw exception::BadOption("option requires an argument");
345  }
346 
347 public:
348  bool boolValue() const { return !m_values.empty(); }
349  const std::vector< typename T::value_type >& values() const { return m_values; }
350 
351  friend class OptionGroup;
352  friend class Engine;
353 };
354 
355 
359 class OptionGroup : public Managed
360 {
361  MemoryManager* m_manager;
362 
363 protected:
364  OptionGroup(MemoryManager* mman = 0, const std::string& description = std::string())
365  : m_manager(mman), description(description), hidden(false) {}
366 
367 public:
368  Option* add(Option* o) { options.push_back(o); return o; }
369 
370  std::vector<Option*> options;
371 
372  std::string description;
373 
374  // Set to true if the option group should not be documented
375  bool hidden;
376 
380  template<typename T>
381  T* create(const std::string& name,
382  char shortName,
383  const std::string& longName,
384  const std::string& usage = std::string(),
385  const std::string& description = std::string())
386  {
387  T* item = new T(name, shortName, longName, usage, description);
388  if (m_manager) m_manager->add(item);
389  return item;
390  }
391 
395  template<typename T>
396  T* add(const std::string& name,
397  char shortName,
398  const std::string& longName,
399  const std::string& usage = std::string(),
400  const std::string& description = std::string())
401  {
402  T* res = create<T>(name, shortName, longName, usage, description);
403  add(res);
404  return res;
405  }
406 
407  friend class Engine;
408 };
409 
410 }
411 }
412 
413 // vim:set ts=4 sw=4:
414 #endif