EasyLocalpp  3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
parameter.hh
Go to the documentation of this file.
1 #if !defined(_PARAMETER_HH_)
2 #define _PARAMETER_HH_
3 
4 #include <stdexcept>
5 #include <list>
6 #include <string>
7 #include <iostream>
8 #include <memory>
9 #include <sstream>
10 #include "easylocal/utils/types.hh"
11 
12 #include "boost/program_options/options_description.hpp"
13 
14 namespace EasyLocal {
15 
16  namespace Core {
17 
20  {
21  friend class Parametrized;
22  friend class ParameterNotSet;
23  friend class ParameterNotValid;
24  public:
25 
27  virtual std::istream& Read(std::istream& is = std::cin) = 0;
28 
30  virtual std::ostream& Write(std::ostream& os = std::cout) const = 0;
31 
33  bool IsSet() const { return is_set; }
34 
36  bool IsValid() const { return is_valid; }
37 
39  virtual std::string ToString() const = 0;
40 
41  protected:
42 
44 
46  AbstractParameter(const std::string& cmdline_flag, const std::string& description);
47 
49  std::string description;
50 
52  std::string cmdline_flag;
53 
55  bool is_set;
56 
58  bool is_valid;
59 
60  virtual void CopyValue(const AbstractParameter& ap) = 0;
61  };
62 
64  class ParameterNotSet : public std::logic_error
65  {
66  public:
70  ParameterNotSet(const AbstractParameter& p) : std::logic_error(std::string("Parameter ") + p.cmdline_flag + " not set") {}
71  };
72 
74  class ParameterNotValid : public std::logic_error
75  {
76  public:
80  ParameterNotValid(const AbstractParameter& p) : std::logic_error(std::string("Parameter ") + p.cmdline_flag + " not valid") {}
81  };
82 
84  class ParameterBox : public std::vector<AbstractParameter*>
85  {
86  public:
91  ParameterBox(const std::string& prefix, const std::string& description);
92 
94  const std::string prefix;
96  boost::program_options::options_description cl_options;
98  static std::list<const ParameterBox*> overall_parameters;
99  };
100 
102  template <typename T>
104  {
105  template <typename _T>
106  friend std::istream& operator>>(std::istream& is, BaseParameter<_T>& p) throw (ParameterNotValid);
107  template <typename _T>
108  friend bool operator==(const BaseParameter<_T>&, const _T&) throw (ParameterNotSet, ParameterNotValid);
110  protected:
112  public:
114  virtual std::istream& Read(std::istream& is = std::cin) throw (ParameterNotValid);
115 
117  virtual std::ostream& Write(std::ostream& os = std::cout) const throw (ParameterNotSet, ParameterNotValid);
118 
120  virtual std::string ToString() const throw (ParameterNotSet, ParameterNotValid)
121  {
122  if (!is_valid)
123  {
124  throw ParameterNotValid(*this);
125  }
126  std::stringstream ss;
127  ss << this->value;
128  return ss.str();
129  }
130 
131  virtual void CopyValue(const AbstractParameter& ap)
132  {
133  const BaseParameter<T>& tp = dynamic_cast<const BaseParameter<T>&>(ap);
134  this->value = tp.value;
135  this->is_set = tp.is_set;
136  this->is_valid = tp.is_valid;
137  }
138 
140  operator T() const throw (ParameterNotSet, ParameterNotValid);
141 
143  const T& operator=(const T&) throw (ParameterNotValid);
144 
145  protected:
147  T value;
148  };
149 
150  template <typename T>
151  class Parameter : public BaseParameter<T>
152  {
153  public:
155  {
156  this->is_valid = false;
157  }
163  Parameter(const std::string& cmdline_flag, const std::string& description, ParameterBox& parameters)
164  : BaseParameter<T>(cmdline_flag, description)
165  {
166  std::string flag = parameters.prefix + "::" + cmdline_flag;
167  parameters.push_back(this);
168  parameters.cl_options.add_options()
169  (flag.c_str(), boost::program_options::value<T>(&this->value)->notifier([this](const T&){ this->is_set = true; }), description.c_str());
170  this->is_valid = true;
171  }
172 
173  virtual void operator()(const std::string& cmdline_flag, const std::string& description, ParameterBox& parameters)
174  {
175  this->cmdline_flag = parameters.prefix + "::" + cmdline_flag;
176  this->description = description;
177  parameters.push_back(this);
178  parameters.cl_options.add_options()
179  (this->cmdline_flag.c_str(), boost::program_options::value<T>(&this->value)->notifier([this](const T&){ this->is_set = true; }), description.c_str());
180  this->is_valid = true;
181  }
182 
183  const T& operator=(const T& v) throw (ParameterNotValid)
184  {
185  if (!this->is_valid)
186  throw ParameterNotValid(*this);
187  this->is_set = true;
188  this->value = v;
189  return this->value;
190  }
191 
192  };
193 
194  template <>
195  class Parameter<bool> : public BaseParameter<bool>
196  {
197  public:
199  {
200  this->is_valid = false;
201  }
202 
203  Parameter(const std::string& cmdline_flag, const std::string& description, ParameterBox& parameters)
204  : BaseParameter<bool>(cmdline_flag, description)
205  {
206  std::string flag = parameters.prefix + "::" + cmdline_flag;
207  parameters.cl_options.add_options()
208  (("enable-" + flag).c_str(), boost::program_options::value<std::string>()->implicit_value("true")->zero_tokens()->notifier([this](const std::string& v){ this->is_set = true; this->value = true; }), "")
209  (("disable-" + flag).c_str(), boost::program_options::value<std::string>()->implicit_value("false")->zero_tokens()->notifier([this](const std::string & v){ this->is_set = true; this->value = false; }),
210  ("[enable/disable] " + description).c_str());
211  }
212 
213  virtual void operator()(const std::string& cmdline_flag, const std::string& description, ParameterBox& parameters)
214  {
215  this->cmdline_flag = parameters.prefix + "::" + cmdline_flag;
216  this->description = description;
217  parameters.push_back(this);
218  parameters.cl_options.add_options()
219  (("enable-" + cmdline_flag).c_str(), boost::program_options::value<std::string>()->implicit_value("true")->zero_tokens()->notifier([this](const std::string& v){ this->is_set = true; this->value = true; }), "")
220  (("disable-" + cmdline_flag).c_str(), boost::program_options::value<std::string>()->implicit_value("false")->zero_tokens()->notifier([this](const std::string & v){ this->is_set = true; this->value = false; }),
221  ("[enable/disable] " + description).c_str());
222  this->is_valid = true;
223  }
224 
225  const bool& operator=(const bool& v) throw (ParameterNotValid)
226  {
227  if (!this->is_valid)
228  throw ParameterNotValid(*this);
229  this->is_set = true;
230  this->value = v;
231  return this->value;
232  }
233  };
234 
236  : public std::logic_error
237  {
238  public:
239  template <typename T>
240  IncorrectParameterValue(const Parameter<T>& p, std::string desc);
241  virtual const char* what() const throw();
242  virtual ~IncorrectParameterValue() throw();
243  protected:
244  std::string message;
245  };
246 
247  template <typename T>
248  BaseParameter<T>::operator T() const throw (ParameterNotSet, ParameterNotValid)
249  {
250  if (!is_valid)
251  throw ParameterNotValid(*this);
252  if (!is_set)
253  throw ParameterNotSet(*this);
254  return value;
255  }
256 
257  template <typename T>
258  std::istream& BaseParameter<T>::Read(std::istream& is) throw (ParameterNotValid)
259  {
260  if (!is_valid)
261  throw ParameterNotValid(*this);
262  std::string in;
263  std::getline(is, in);
264 
265  if (in.size())
266  {
267  std::stringstream ss;
268  ss.str(in);
269  ss >> *this;
270  }
271  else
272  {
273  is_set = true;
274  }
275 
276  return is;
277  }
278 
279  template <typename T>
280  std::ostream& BaseParameter<T>::Write(std::ostream& os) const throw (ParameterNotSet, ParameterNotValid)
281  {
282  if (!this->is_valid)
283  throw ParameterNotValid(*this);
284  if (!is_set)
285  throw ParameterNotSet(*this);
286  os << value;
287  return os;
288  }
289 
290  template <typename T>
291  std::istream& operator>>(std::istream& is, BaseParameter<T>& p) throw (ParameterNotValid)
292  {
293  if (!p.is_valid)
294  throw ParameterNotValid(p);
295  is >> p.value;
296  p.is_set = true;
297 
298  return is;
299  }
300 
301  template <typename T>
302  bool operator==(const BaseParameter<T>& t1, const T& t2) throw (ParameterNotSet, ParameterNotValid)
303  {
304  return t1.value == t2;
305  }
306 
307  bool operator==(const BaseParameter<std::string>& s1, const char* s2) throw (ParameterNotSet, ParameterNotValid);
308 
309  template <typename T>
311  : std::logic_error("Incorrect parameter value")
312  {
313  std::ostringstream os;
314  os << "Parameter " << p.cmdline_flag << " set to incorrect value " << p.value << " (" << desc << ")";
315  message = os.str();
316  }
317 
319  {
320  public:
321  static bool Parse(int argc, const char* argv[], bool check_unregistered = true, bool silent = false);
322  };
323 
326  {
327  friend bool CommandLineParameters::Parse(int argc, const char* argv[], bool check_unregistered, bool silent);
328  public:
329 
334  Parametrized(const std::string& prefix, const std::string& description) : parameters(prefix, description)
335  {
336  overall_parametrized.push_back(this);
337  }
338 
340  virtual void ReadParameters(std::istream& is = std::cin, std::ostream& os = std::cout)
341  {
343 
344  for (auto p : this->parameters)
345  {
346  os << " " << p->description << (p->IsSet() ? (std::string(" (def.: ") + p->ToString() + "): ") : ": ");
347  do
348  {
349  p->Read(is);
350  } while (!p->IsSet());
351  }
352  }
353 
355  virtual void Print(std::ostream& os = std::cout) const
356  {
357  for (auto p : this->parameters)
358  {
359  os << " " << p->description << ": ";
360  p->Write(os) << std::endl;
361  }
362  }
363 
365  template <typename T>
366  void GetParameterValue(std::string flag, T& value)
367  {
368  for (auto p : this->parameters)
369  {
370  if (p->cmdline_flag == flag || p->cmdline_flag == parameters.prefix + "::" + flag)
371  {
372  Parameter<T>* p_par = dynamic_cast<Parameter<T>*>(p);
373  if (!p_par)
374  throw std::logic_error("Parameter " + p->cmdline_flag + " value of an incorrect type");
375  value = *p_par;
376  return;
377  }
378  }
379  // FIXME: a more specific exception should be raised
380  throw std::logic_error("Parameter " + flag + " not in the list");
381  }
382 
384  {
385  for (auto& p1 : this->parameters)
386  {
387  std::string f1 = split(p1->cmdline_flag, boost::regex("::"))[1];
388  for (const auto& p2 : p.parameters)
389  {
390  std::string f2 = split(p2->cmdline_flag, boost::regex("::"))[1];
391  if (f1 == f2)
392  {
393  p1->CopyValue(*p2);
394  break;
395  }
396  }
397  }
398  }
399 
400 
402  template <typename T>
403  void SetParameter(std::string flag, const T& value)
404  {
405  bool found = false;
406  for (auto p : this->parameters)
407  {
408  if (p->cmdline_flag == flag || p->cmdline_flag == parameters.prefix + "::" + flag)
409  {
410  Parameter<T>* p_par = dynamic_cast<Parameter<T>*>(p);
411  if (!p_par)
412  throw std::logic_error("Parameter " + p->cmdline_flag + " value of an incorrect type");
413  (*p_par) = value;
414  found = true;
415  }
416  }
417  // FIXME: a more specific exception should be raised
418  if (!found)
419  throw std::logic_error("Parameter " + flag + " not in the list");
420  }
421 
422  bool IsRegistered() const
423  {
424  for (auto p : parameters)
425  if (!p->IsValid())
426  return false;
427  return true;
428  }
429 
430  protected:
431 
432  virtual void RegisterParameters() = 0;
433 
435 
436  static std::list<Parametrized*> overall_parametrized;
437 
438  };
439 
440  }
441  }
442 
443 #endif // !defined(_PARAMETER_HH_)
virtual std::istream & Read(std::istream &is=std::cin)=0
CFtype max(const std::vector< CFtype > &values)
Definition: types.hh:34
virtual void RegisterParameters()=0
static std::list< const ParameterBox * > overall_parameters
Definition: parameter.hh:98
virtual void operator()(const std::string &cmdline_flag, const std::string &description, ParameterBox &parameters)
Definition: parameter.hh:213
virtual void operator()(const std::string &cmdline_flag, const std::string &description, ParameterBox &parameters)
Definition: parameter.hh:173
virtual std::ostream & Write(std::ostream &os=std::cout) const
Definition: parameter.hh:280
const std::string prefix
Definition: parameter.hh:94
void CopyParameterValues(const Parametrized &p)
Definition: parameter.hh:383
ParameterNotSet(const AbstractParameter &p)
Definition: parameter.hh:70
virtual void CopyValue(const AbstractParameter &ap)
Definition: parameter.hh:131
virtual void ReadParameters(std::istream &is=std::cin, std::ostream &os=std::cout)
Definition: parameter.hh:340
virtual std::ostream & Write(std::ostream &os=std::cout) const =0
boost::program_options::options_description cl_options
Definition: parameter.hh:96
virtual std::istream & Read(std::istream &is=std::cin)
Definition: parameter.hh:258
virtual std::string ToString() const =0
friend std::istream & operator>>(std::istream &is, BaseParameter< _T > &p)
friend class IncorrectParameterValue
Definition: parameter.hh:109
const bool & operator=(const bool &v)
Definition: parameter.hh:225
virtual void CopyValue(const AbstractParameter &ap)=0
Parametrized(const std::string &prefix, const std::string &description)
Definition: parameter.hh:334
ParameterBox(const std::string &prefix, const std::string &description)
friend bool operator==(const BaseParameter< _T > &, const _T &)
static bool Parse(int argc, const char *argv[], bool check_unregistered=true, bool silent=false)
ParameterNotValid(const AbstractParameter &p)
Definition: parameter.hh:80
void SetParameter(std::string flag, const T &value)
Definition: parameter.hh:403
static std::list< Parametrized * > overall_parametrized
Definition: parameter.hh:436
IncorrectParameterValue(const Parameter< T > &p, std::string desc)
Definition: parameter.hh:310
void GetParameterValue(std::string flag, T &value)
Definition: parameter.hh:366
Parameter(const std::string &cmdline_flag, const std::string &description, ParameterBox &parameters)
Definition: parameter.hh:203
const T & operator=(const T &v)
Definition: parameter.hh:183
std::vector< std::string > split(const std::string &input, const boost::regex &regex)
virtual void Print(std::ostream &os=std::cout) const
Definition: parameter.hh:355
Parameter(const std::string &cmdline_flag, const std::string &description, ParameterBox &parameters)
Definition: parameter.hh:163
virtual std::string ToString() const
Definition: parameter.hh:120