soma-io  5.0.5
getopt.h
Go to the documentation of this file.
1 /* This software and supporting documentation are distributed by
2  * Institut Federatif de Recherche 49
3  * CEA/NeuroSpin, Batiment 145,
4  * 91191 Gif-sur-Yvette cedex
5  * France
6  *
7  * This software is governed by the CeCILL-B license under
8  * French law and abiding by the rules of distribution of free software.
9  * You can use, modify and/or redistribute the software under the
10  * terms of the CeCILL-B license as circulated by CEA, CNRS
11  * and INRIA at the following URL "http://www.cecill.info".
12  *
13  * As a counterpart to the access to the source code and rights to copy,
14  * modify and redistribute granted by the license, users are provided only
15  * with a limited warranty and the software's author, the holder of the
16  * economic rights, and the successive licensors have only limited
17  * liability.
18  *
19  * In this respect, the user's attention is drawn to the risks associated
20  * with loading, using, modifying and/or developing or reproducing the
21  * software by the user in light of its specific status of free software,
22  * that may mean that it is complicated to manipulate, and that also
23  * therefore means that it is reserved for developers and experienced
24  * professionals having in-depth computer knowledge. Users are therefore
25  * encouraged to load and test the software's suitability as regards their
26  * requirements in conditions enabling the security of their systems and/or
27  * data to be ensured and, more generally, to use and operate it in the
28  * same conditions as regards security.
29  *
30  * The fact that you are presently reading this means that you have had
31  * knowledge of the CeCILL-B license and that you accept its terms.
32  */
33 
34 #ifndef SOMAIO_GETOPT_GETOPT_H
35 #define SOMAIO_GETOPT_GETOPT_H
36 
37 #include <cartobase/type/types.h>
40 #include <string>
41 #include <vector>
42 #include <stdexcept>
43 #include <algorithm>
44 #include <iostream>
45 
46 namespace carto {
47 
48 
50  // missign_option //
52 
53 class missing_option : public std::runtime_error
54 {
55 public:
56 
57  missing_option( const std::string &optionName );
58  inline missing_option( const std::string &message, bool ) :
59  std::runtime_error( message ) {}
60 };
61 
62 
64  // unexpected_option //
66 
67 class unexpected_option : public std::runtime_error
68 {
69 public:
70 
71  unexpected_option( const std::string &optionName );
72  inline unexpected_option( const std::string &message, bool ) :
73  std::runtime_error( message ) {}
74 };
75 
76 
78  // unexpected_option_value //
80 
81 class unexpected_option_value : public std::runtime_error
82 {
83 public:
84 
85  unexpected_option_value( const std::string &optionName,
86  const std::string &value );
87  inline unexpected_option_value( const std::string &message, bool ) :
88  std::runtime_error( message ) {}
89 };
90 
91 
93  // OptionBase //
95 
97 {
98  friend class OptionsParser;
99 
100 protected:
101 
102  std::vector<std::string> _names;
103  std::string _info;
104 
105 
106  virtual bool recognizeName( const std::string & ) = 0;
107  virtual bool feed( const std::string & ) = 0;
108  virtual void check() = 0;
109 
110 
111  OptionBase( const std::string &name, const std::string &info );
112  virtual inline ~OptionBase();
113 
114  inline void addName( const std::string &name );
115  inline const std::string &name() const;
116  std::string names() const;
117  inline bool _nameInList( const std::string &name ) const;
118 
119 public:
120 
121  virtual std::string info() const = 0;
122 };
123 
124 //-----------------------------------------------------------------------------
126 
127 //-----------------------------------------------------------------------------
128 inline void OptionBase::addName( const std::string &name ) {
129  _names.push_back( name );
130  }
131 
132 //-----------------------------------------------------------------------------
133 inline const std::string &OptionBase::name() const
134 {
135  return *_names.begin();
136 }
137 
138 //-----------------------------------------------------------------------------
139 inline bool OptionBase::_nameInList( const std::string &name ) const
140 {
141  return find( _names.begin(), _names.end(), name ) != _names.end();
142 }
143 
144 
146  // OptionSeries<T> //
148 
149 template <typename T>
150 class OptionSeries : public OptionBase
151 {
152  friend class OptionsParser;
153 
154  OptionSeries( T &serie, const std::string &name, const std::string &info,
155  unsigned numMin, unsigned numMax );
156  virtual inline ~OptionSeries();
157 
158  virtual bool recognizeName( const std::string & );
159  virtual bool feed( const std::string & );
160  virtual void check();
161  virtual std::string info() const;
162 
163  T &_values;
164  unsigned _numMin, _numMax;
165  typename T::iterator _storeNextValue;
166  unsigned _numValuesStored;
167 };
168 
169 //-----------------------------------------------------------------------------
170 template <typename T>
172 
173 //-----------------------------------------------------------------------------
174 template <typename T> inline
175 OptionSeries<T>::OptionSeries( T &serie, const std::string &name,
176  const std::string &info,
177  unsigned numMin, unsigned numMax ) :
178  OptionBase( name, info ),
179  _values( serie ),
180  _numMin( numMin ),
181  _numMax( numMax ),
182  _storeNextValue( _values.begin() ),
183  _numValuesStored( 0 )
184 {
185 }
186 
187 //-----------------------------------------------------------------------------
188 template <typename T> inline
189 bool OptionSeries<T>::recognizeName( const std::string &name )
190 {
191  if( _nameInList( name ) ) {
192  if ( _numMax && _numValuesStored >= _numMax ) {
193  throw unexpected_option( name );
194  }
195  return true;
196  }
197  return false;
198 }
199 
200 //-----------------------------------------------------------------------------
201 template <typename T> inline
202 bool OptionSeries<T>::feed( const std::string &value )
203 {
204  if ( _numMax == 0 || _numValuesStored < _numMax ) {
205  if ( _storeNextValue == _values.end() ) {
206  _values.push_back( typename T::value_type() );
207  stringTo< typename T::value_type >( value, *(_values.rbegin()) );
208  _storeNextValue = _values.end();
209  } else {
210  stringTo< typename T::value_type >( value, *_storeNextValue );
211  ++_storeNextValue;
212  }
213  ++_numValuesStored;
214  return true;
215  }
216  return false;
217 }
218 
219 //-----------------------------------------------------------------------------
220 template <typename T> inline
222 {
223  if ( _values.size() < _numMin ) throw missing_option( name() );
224 }
225 
226 //-----------------------------------------------------------------------------
227 template <typename T> inline
228 std::string OptionSeries<T>::info() const
229 {
230  if ( _numMin ) {
231  return names() + " <" + DataTypeCode<T>::name() + ">\n" + _info;
232  } else {
233  return std::string( "[ " ) + names() + " <"
235  + "> ]\n" + _info;
236  }
237 }
238 
239 
240 
241 
243  // SingleOption<T> //
245 
246 template <typename T>
247 class SingleOption : public OptionBase
248 {
249 protected:
250 
251  T &_value;
252  bool _optional;
254 
255 public:
256 
257  inline SingleOption( T &value, const std::string &name,
258  const std::string &info, bool optional );
259  virtual inline ~SingleOption();
260 
261  virtual bool recognizeName( const std::string & );
262  virtual bool feed( const std::string & );
263  virtual void check();
264  std::string info() const;
265 };
266 
267 //-----------------------------------------------------------------------------
268 template <typename T>
270 
271 //-----------------------------------------------------------------------------
272 template <typename T>
273 inline SingleOption<T>::SingleOption( T &value, const std::string &name,
274  const std::string &info,
275  bool optional ) :
276  OptionBase( name, info ),
277  _value( value ),
278  _optional( optional ),
279  _valueRead( false )
280 {
281 }
282 
283 //-----------------------------------------------------------------------------
284 template <typename T>
285 bool SingleOption<T>::recognizeName( const std::string &n )
286 {
287  if( _nameInList( n ) ) {
288  if ( _valueRead ) {
289  throw unexpected_option( n );
290  }
291  return true;
292  }
293  return false;
294 }
295 
296 //-----------------------------------------------------------------------------
297 template <typename T>
298 bool SingleOption<T>::feed( const std::string &value )
299 {
300  if ( _valueRead ) {
301  return false;
302  } else {
303  stringTo< T >( value, _value );
304  _valueRead = true;
305  return true;
306  }
307 }
308 
309 //-----------------------------------------------------------------------------
310 template <typename T> inline
312 {
313  if ( ! _optional && ! _valueRead ) {
314  throw missing_option( name() );
315  }
316 }
317 
318 //-----------------------------------------------------------------------------
319 template <typename T> inline
320 std::string SingleOption<T>::info() const
321 {
322  if ( _optional ) {
323  return std::string( "[ " ) + names() + " <"
325  + "> ]\n" + _info;
326  } else {
327  return names() + " <" + DataTypeCode<T>::name() + ">\n" + _info;
328  }
329 }
330 
331 
333  // SingleOption<bool> //
335 
336 //-----------------------------------------------------------------------------
337 template <>
338 bool SingleOption<bool>::recognizeName( const std::string &n );
339 
340 
341 //-----------------------------------------------------------------------------
342 template <>
343 bool SingleOption<bool>::feed( const std::string &value );
344 
345 
346 
348  // BoolOrNumber<T> //
350 
351 template <class NumberType>
353 {
354 public:
355 
356  inline BoolOrNumber( NumberType &v ) : value( v ) {}
357  NumberType &value;
358 };
359 
360 
361 
363  // SingleOption< BoolOrNumber > //
365 
366 template <class NumberType>
367 class SingleOption< BoolOrNumber<NumberType> > :
368  public SingleOption<NumberType>
369 {
370 
371 public:
372 
374  const std::string &name,
375  const std::string &info, bool optional );
376  virtual inline ~SingleOption();
377 
378  virtual bool recognizeName( const std::string & );
379  virtual bool feed( const std::string & );
380  std::string info() const;
381 };
382 
383 //-----------------------------------------------------------------------------
384 template <typename NumberType>
387  const std::string &name,
388  const std::string &info, bool optional ) :
389  SingleOption<NumberType>( value.value, name, info, optional ) {}
390 
391 //-----------------------------------------------------------------------------
392 template <typename NumberType>
394 
395 //-----------------------------------------------------------------------------
396 template <typename NumberType>
398 recognizeName( const std::string &n )
399 {
400  if( this->_nameInList( n ) ) {
401  if ( this->_valueRead ) {
402  throw unexpected_option( n );
403  }
404  this->_value = NumberType( 1 );
405  return true;
406  }
407  return false;
408 }
409 
410 
411 //-----------------------------------------------------------------------------
412 template <typename NumberType>
413 bool SingleOption< BoolOrNumber<NumberType> >::feed( const std::string &value )
414 {
415  if ( this->_valueRead ) {
416  return false;
417  } else {
418  try {
419  stringTo< NumberType >( value, this->_value );
420  }
421  catch( invalid_number &e ) {
422  return false;
423  }
424  this->_valueRead = true;
425  return true;
426  }
427 }
428 
429 //-----------------------------------------------------------------------------
430 template <class NumberType> inline
432 {
433  return std::string( "[ " ) + this->names() + " [ <"
435  + "> ] ]\n" + this->_info;
436 }
437 
438 
440  // OptionsParser //
442 
471 {
472 public:
473  typedef std::vector< std::string > CommandLineArguments;
474 
475 protected:
476  CommandLineArguments cla;
477 
478  typedef std::vector< OptionBase * > OptionList;
479  OptionList options;
480 
482  void pushOption( OptionBase * );
483 
484 public:
485 
486  OptionsParser( int argc, const char **argv );
487  ~OptionsParser();
488 
508  template <typename T>
509  void addOption( T & param, const std::string & token,
510  const std::string & description,
511  bool optional = false );
531  template <typename T>
532  void addOptionSeries( T & param, const std::string & token,
533  const std::string & description, unsigned minnum = 0,
534  unsigned maxnum = 0 );
536  void alias( const std::string &to, const std::string &from );
541  void parse();
545  void check();
546 };
547 
548 //-----------------------------------------------------------------------------
549 template <typename T> inline
550 void OptionsParser::addOption( T &value, const std::string &name,
551  const std::string &info, bool optional )
552 {
553  pushOption( new SingleOption<T>( value, name, info, optional ) );
554 }
555 
556 //-----------------------------------------------------------------------------
557 template <typename T> inline
558 void OptionsParser::addOptionSeries( T &values, const std::string &name,
559  const std::string &info,
560  unsigned numMin, unsigned numMax )
561 {
562  pushOption( new OptionSeries<T>( values, name, info, numMin, numMax ) );
563 }
564 
565 
567  // CartoApplication //
569 
582 {
583  std::string _documentation;
584  std::string _name;
585 
586 public:
587 
588  CartoApplication( int argc, const char **argv,
589  const std::string &documentation );
590  virtual ~CartoApplication();
596  virtual void initialize();
597 };
598 
599 
601  // user_interruption //
603 
608 class user_interruption : public std::runtime_error
609 {
610 public:
611 
613  inline user_interruption( const std::string &message ) :
614  std::runtime_error( message ) {}
615 };
616 
617 } // namespace carto
618 
619 
620 #endif // ifndef CARTO_GETOPT_GETOPT_H
621 
NumberType & value
Definition: getopt.h:357
unexpected_option(const std::string &message, bool)
Definition: getopt.h:72
std::vector< OptionBase *> OptionList
Definition: getopt.h:478
virtual bool recognizeName(const std::string &)
Definition: getopt.h:285
void addOptionSeries(T &param, const std::string &token, const std::string &description, unsigned minnum=0, unsigned maxnum=0)
Adds a series of parameters to be parsed on the commandline.
Definition: getopt.h:558
virtual ~SingleOption()
Definition: getopt.h:269
STL namespace.
SingleOption(T &value, const std::string &name, const std::string &info, bool optional)
Definition: getopt.h:273
std::string _info
Definition: getopt.h:103
Cartograph options parser.
Definition: getopt.h:581
OptionList options
Definition: getopt.h:479
std::vector< std::string > _names
Definition: getopt.h:102
void addOption(T &param, const std::string &token, const std::string &description, bool optional=false)
Adds a single parameter to be parsed on the commandline.
Definition: getopt.h:550
unexpected_option_value(const std::string &message, bool)
Definition: getopt.h:87
std::string name()
void addName(const std::string &name)
Definition: getopt.h:128
bool _nameInList(const std::string &name) const
Definition: getopt.h:139
virtual bool feed(const std::string &)
Definition: getopt.h:298
missing_option(const std::string &optionName)
BoolOrNumber(NumberType &v)
Definition: getopt.h:356
virtual void check()
Definition: getopt.h:311
friend class OptionsParser
Definition: getopt.h:98
Commandline options parser.
Definition: getopt.h:470
virtual ~OptionBase()
Definition: getopt.h:125
std::string names() const
std::vector< std::string > CommandLineArguments
Definition: getopt.h:473
const std::string & name() const
Definition: getopt.h:133
CommandLineArguments cla
Definition: getopt.h:476
std::string info() const
Definition: getopt.h:320
user_interruption(const std::string &message)
Definition: getopt.h:613
missing_option(const std::string &message, bool)
Definition: getopt.h:58
A special exception which is thrown after a command help is requested and displayed in a CartoApplica...
Definition: getopt.h:608