option_parser.h
Go to the documentation of this file.
1 
12 #pragma once
13 #include <string>
14 #include <sstream>
15 #include <vector>
16 #include "interop/util/exception.h"
18 
19 namespace illumina { namespace interop { namespace util
20 {
21 
25  {
26  public:
32  abstract_option(const std::string &flag, const std::string &help) : m_flag(flag), m_help(help)
33  { }
36  virtual ~abstract_option(){}
37 
38  public:
42  virtual void set_value(const std::string& str) = 0;
46  virtual std::string get_value()const = 0;
47 
48  public:
53  const std::string &flag() const
54  {
55  return m_flag;
56  }
61  const std::string &help() const
62  {
63  return m_help;
64  }
65 
66  private:
67  std::string m_flag;
68  std::string m_help;
69  };
72  class option_exception : public std::runtime_error
73  {
74  public:
79  option_exception(const std::string& msg) : std::runtime_error(msg){}
80  };
84  {
85  public:
90  invalid_option_value_exception(const std::string& msg) : option_exception(msg){}
91  };
95  {
96  public:
101  invalid_option_exception(const std::string& msg) : option_exception(msg){}
102  };
105  template<typename T>
107  {
108  public:
110  typedef T value_type;
115  value_container(T* ptr) : m_ptr(ptr)
116  {
117  }
118 
123  void set_value(const value_type& val)const
124  {
125  *m_ptr = val;
126  }
131  const T& get()const
132  {
133  return *m_ptr;
134  }
135 
136  private:
137  T* m_ptr;
138  };
139 
142  template<typename T, typename R, typename P1>
143  class value_container< R (T::* )(P1) >
144  {
145  typedef R (T::* function_pointer )(P1);
146  public:
148  typedef P1 value_type;
154  value_container(T* ptr_obj, function_pointer ptr_func) : m_obj(ptr_obj), m_func(ptr_func){}
155 
160  void set_value(const value_type& val)const
161  {
162  ((*m_obj).*m_func)(val);
163  }
168  std::string get()const
169  {
170  return "";
171  }
172 
173  private:
174  T* m_obj;
175  function_pointer m_func;
176  };
183  template<typename T, typename R, typename P1>
184  inline value_container< R (T::* )(P1) > wrap_setter(T& obj, R (T::* func)(P1))
185  {
186  return value_container< R (T::* )(P1) >(&obj, func);
187  }
188 
189 
190 
195  template<typename T>
196  class option : public abstract_option
197  {
198  public:
205  option(const value_container<T>& value, const std::string &flag, const std::string &help) : abstract_option(flag, help), m_value(
206  value)
207  { }
210  virtual ~option(){}
211 
212  public:
217  void set_value(const std::string& str)
218  {
219  std::istringstream iss(str);
220  typename value_container<T>::value_type val;
221  iss >> val;
222  m_value.set_value(val);
223  int ch;
224  if(!iss.eof() && (ch=iss.get()) != ' ')
225  {
226  INTEROP_THROW(invalid_option_value_exception, "Failed to parse character: " << static_cast<char>(ch));
227  }
228  }
232  std::string get_value()const
233  {
234  std::ostringstream oss;
235  oss << m_value.get();
236  return oss.str();
237  }
238 
239  private:
240  value_container<T> m_value;
241  };
242 
250  {
251  typedef stdbp::unique_ptr<abstract_option> option_pointer;
252  typedef std::vector <option_pointer> option_vector;
253  public:
261  template<typename T>
262  option_parser &operator()(T &value, const std::string &flag, const std::string &help)
263  {
264  m_options.push_back(option_pointer(new option<T>(&value, flag, help)));
265  return *this;
266  }
274  template<typename T>
275  option_parser &operator()(const value_container<T> &value, const std::string &flag, const std::string &help)
276  {
277  m_options.push_back(option_pointer(new option<T>(value, flag, help)));
278  return *this;
279  }
286  bool is_help_requested(int argc, const char **argv)
287  {
288  const std::string help1 = "-help";
289  const std::string help2 = "--help";
290  const std::string help3 = "-h";
291  for(int i=1;i<argc;++i)
292  {
293  if(help1 == argv[i]) return true;
294  if(help2 == argv[i]) return true;
295  if(help3 == argv[i]) return true;
296  }
297  return false;
298  }
304  void parse(int &argc, const char **argv)
305  {
306  for(int i=1;i<argc;++i)
307  {
308  if(!is_option(argv[i])) continue;
309  if(parse_option(argv[i]))
310  {
311  // Remove argument from command line
312  for (int j = i; j != argc; ++j) {
313  argv[j] = argv[j + 1];
314  }
315 
316  // Decrements the argument count.
317  --argc;
318  --i;
319  }
320  }
321  }
326  void check_for_unknown_options(const int argc, const char **argv)
327  {
328  for(int i=1;i<argc;++i)
329  {
330  if(is_option(argv[i]))
331  {
332  INTEROP_THROW(invalid_option_exception, "Unexpected option: " << argv[i]);
333  }
334  }
335  }
343  void display_help(std::ostream &out, const char* prefix="\t", const char* sep=": ", const char* postfix="\n")
344  {
345  for(size_t i=0;i<m_options.size();++i)
346  out << prefix << "--"<< m_options[i]->flag() << "[" << m_options[i]->get_value() << "]" << sep << m_options[i]->help() << postfix;
347  }
348 
349  private:
350  bool is_option(const char* argv)
351  {
352  if(argv[0] == '\0' || argv[1] == '\0' ) return false;
353  if(argv[0] != '-' || argv[1] != '-') return false;
354  return true;
355  }
356  bool parse_option(const std::string& option)
357  {
358  std::string::size_type n;
359  if((n=option.find('=')) == std::string::npos)
360  INTEROP_THROW(invalid_option_exception, "Option must be of the form --option=value");
361  for(size_t i=0;i<m_options.size();++i)
362  {
363  if(m_options[i]->flag() == option.substr(2, n-2) )
364  {
365  m_options[i]->set_value(option.substr(n+1));
366  return true;
367  }
368  }
369  return false;
370  }
371 
372  private:
373  option_vector m_options;
374  };
375 
376 
377 }}}
378 
option_parser & operator()(T &value, const std::string &flag, const std::string &help)
Definition: option_parser.h:262
invalid_option_exception(const std::string &msg)
Definition: option_parser.h:101
bool is_help_requested(int argc, const char **argv)
Definition: option_parser.h:286
void check_for_unknown_options(const int argc, const char **argv)
Definition: option_parser.h:326
void set_value(const value_type &val) const
Definition: option_parser.h:160
Definition: enum_description.h:15
virtual ~option()
Definition: option_parser.h:210
value_container(T *ptr_obj, function_pointer ptr_func)
Definition: option_parser.h:154
#define INTEROP_THROW(EXCEPTION, MESSAGE)
Definition: exception.h:18
Definition: option_parser.h:249
Definition: option_parser.h:106
void set_value(const std::string &str)
Definition: option_parser.h:217
value_container< R(T::*)(P1) > wrap_setter(T &obj, R(T::*func)(P1))
Definition: option_parser.h:184
abstract_option(const std::string &flag, const std::string &help)
Definition: option_parser.h:32
virtual std::string get_value() const =0
const std::string & flag() const
Definition: option_parser.h:53
void display_help(std::ostream &out, const char *prefix="\t", const char *sep=": ", const char *postfix="\n")
Definition: option_parser.h:343
std::string get_value() const
Definition: option_parser.h:232
invalid_option_value_exception(const std::string &msg)
Definition: option_parser.h:90
Definition: option_parser.h:72
T value_type
Definition: option_parser.h:110
virtual ~abstract_option()
Definition: option_parser.h:36
option_exception(const std::string &msg)
Definition: option_parser.h:79
option(const value_container< T > &value, const std::string &flag, const std::string &help)
Definition: option_parser.h:205
std::unique_ptr< T > unique_ptr
Definition: unique_ptr.h:96
Definition: enums.h:301
void parse(int &argc, const char **argv)
Definition: option_parser.h:304
value_container(T *ptr)
Definition: option_parser.h:115
Definition: option_parser.h:24
const std::string & help() const
Definition: option_parser.h:61
Definition: option_parser.h:196
virtual void set_value(const std::string &str)=0
option_parser & operator()(const value_container< T > &value, const std::string &flag, const std::string &help)
Definition: option_parser.h:275
void set_value(const value_type &val) const
Definition: option_parser.h:123