cmdlineparser.hh
Go to the documentation of this file.
1 /* -*- mia-c++ -*-
2  *
3  * This file is part of MIA - a toolbox for medical image analysis
4  * Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
5  *
6  * MIA is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with MIA; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef mia_core_cmdlineparser_hh
22 #define mia_core_cmdlineparser_hh
23 
24 //#include <miaconfig.h>
25 #include <vector>
26 #include <map>
27 #include <memory>
28 #include <sstream>
29 #include <iostream>
30 #include <string>
31 #include <iterator>
32 #include <mia/core/cmdoption.hh>
33 #include <mia/core/cmdoption.hh>
34 #include <mia/core/typedescr.hh>
35 #include <mia/core/paramoption.hh>
36 #include <mia/core/dictmap.hh>
37 #include <mia/core/flagstring.hh>
38 #include <mia/core/handlerbase.hh>
39 
41 
43 extern EXPORT_CORE const char *g_help_optiongroup;
44 
46 typedef std::map<std::string, std::string> CHistoryRecord;
47 
49 typedef std::pair<std::string, CHistoryRecord> CHistoryEntry;
50 
59  pdi_group = 0, /*<! The group the program belongs to, in the help the program will be described in this section */
60  pdi_short = 1, /*<! A sgort description of the program, this will be the head line in the unix man page. */
61  pdi_description = 2, /*<! The full description of the program */
62  pdi_example_descr = 3, /*<! description of the example that follows */
63  pdi_example_code = 4, /*<! The example command line without the program name */
64  pdi_author = 5 /*<! Author name (if other than main MIA contributer(s) */
65 };
66 
67 extern const std::map<EProgramDescriptionEntry, const char *> g_DescriptionEntryNames;
68 
83 typedef std::map<EProgramDescriptionEntry, const char *> SProgramDescription;
84 
85 
86 
103 template <typename T>
104 class TCmdOption: public CCmdOption{
105 
106 public:
116  TCmdOption(T& val, char short_opt, const char *long_opt, const char *long_help,
117  const char *short_help, CCmdOptionFlags flags = CCmdOptionFlags::none);
118 
119 private:
120  virtual void do_get_long_help_xml(std::ostream& os, xmlpp::Element& parent, HandlerHelpMap& handler_map) const;
121  virtual bool do_set_value(const char *str_value);
122  virtual size_t do_get_needed_args() const;
123  virtual void do_write_value(std::ostream& os) const;
124  virtual const std::string do_get_value_as_string() const;
125  T& m_value;
126 };
127 
134 
135 public:
146  CCmdFlagOption(int& val, const CFlagString& map, char short_opt, const char *long_opt,
147  const char *long_help, const char *short_help,
149 private:
150  virtual bool do_set_value(const char *str_value);
151  virtual size_t do_get_needed_args() const;
152  virtual void do_write_value(std::ostream& os) const;
153  virtual void do_get_long_help(std::ostream& os) const;
154  virtual const std::string do_get_value_as_string() const;
155  int& m_value;
156  const CFlagString m_map;
157 };
158 
159 
170 public:
171 
176  class Callback {
177  public:
182  virtual void print(std::ostream& os) const = 0;
183  };
184 
191  CHelpOption(Callback *cb, char short_opt, const char*long_opt, const char *long_help);
192 
196  void print(std::ostream& os) const;
197 
198 private:
199  std::unique_ptr<Callback> m_callback;
200  virtual bool do_set_value(const char *str_value);
201  virtual size_t do_get_needed_args() const;
202  virtual void do_write_value(std::ostream& os) const;
203  virtual void do_get_long_help(std::ostream& os) const;
204  virtual void do_get_long_help_xml(std::ostream& os, xmlpp::Element& parent,
205  HandlerHelpMap& /*handler_map*/) const;
206 
207 };
208 
214 template <typename PluginHandler>
216  void print(std::ostream& os) const{
217  PluginHandler::instance().print_help(os);
218  }
219 };
220 
221 
231 public:
232 
237  hr_no = 0,
242  hr_copyright
243  };
244 
252 
254  ~CCmdOptionList();
255 
259  void add(PCmdOption opt);
260 
265  void add(const std::string& group, PCmdOption opt);
266 
277  EHelpRequested parse(size_t argc, char *args[], const std::string& additional_type,
278  const CPluginHandlerBase *additional_help = NULL)
279  __attribute__((warn_unused_result));
280 
292  EHelpRequested parse(size_t argc, const char *args[], const std::string& additional_type,
293  const CPluginHandlerBase *additional_help = NULL)
294  __attribute__((warn_unused_result));
295 
301  EHelpRequested parse(size_t argc, char *args[]) __attribute__((warn_unused_result));
302 
308  EHelpRequested parse(size_t argc, const char *args[]) __attribute__((warn_unused_result));
309 
311  const std::vector<std::string>& get_remaining() const;
312 
316  CHistoryRecord get_values() const;
317 
322  void set_group(const std::string& group);
323 
328  void set_logstream(std::ostream& os);
329 private:
330  EHelpRequested do_parse(size_t argc, const char *args[], bool has_additional,
331  const CPluginHandlerBase *additional_help)
332  __attribute__((warn_unused_result));
333  int handle_shortargs(const char *arg, size_t argc, const char *args[]);
334  struct CCmdOptionListData *m_impl;
335 };
336 
337 
338 // implementation of template classes and functions
339 
352 template <typename T>
353 struct __dispatch_opt {
357  static void init(T& /*value*/){
358  }
359 
365  static bool apply(const char *svalue, T& value) {
366  std::istringstream sval(svalue);
367 
368  sval >> value;
369  while (isspace(sval.peek())) {
370  char c;
371  sval >> c;
372  }
373  return sval.eof();
374  }
376  static size_t size(const T /*value*/) {
377  return 1;
378  }
379 
385  static void apply(std::ostream& os, const T& value, bool /*required*/) {
386  os << "=" << value << " ";
387  }
388 
394  static const std::string get_as_string(const T& value) {
395  std::ostringstream os;
396  os << value;
397  return os.str();
398  }
399 };
400 
406 template <typename T>
407 struct __dispatch_opt< std::vector<T> > {
408  static void init(std::vector<T>& /*value*/){
409 
410  }
411  static bool apply(const char *svalue, std::vector<T>& value) {
412  std::string h(svalue);
413  unsigned int n = 1;
414  for(std::string::iterator hb = h.begin(); hb != h.end(); ++hb)
415  if (*hb == ',') {
416  *hb = ' ';
417  ++n;
418  }
419 
420 
421  if (!value.empty()) {
422  if (n > value.size()) {
423  throw create_exception<std::invalid_argument>("Expect only ", value.size(),
424  " coma separated values, but '",
425  svalue, "' provides ", n);
426  }
427  }else{
428  value.resize(n);
429  }
430 
431  std::istringstream sval(h);
432  auto i = value.begin();
433  while (!sval.eof()) {
434  sval >> *i;
435  ++i;
436  }
437  return sval.eof();
438  }
439 
440  static size_t size(const std::vector<T>& /*value*/) {
441  return 1;
442  }
443 
444  static void apply(std::ostream& os, const std::vector<T>& value, bool required) {
445 
446  os << "=";
447  if (value.empty() && required)
448  os << "[required] ";
449  else {
450  for (auto i = value.begin(); i != value.end(); ++i) {
451  if (i != value.begin())
452  os << ",";
453  os << *i;
454  }
455  os << " ";
456  }
457  }
458 
459  static const std::string get_as_string(const std::vector<T>& value) {
460  std::ostringstream os;
461  for (auto i = value.begin(); i != value.end(); ++i) {
462  if (i != value.begin())
463  os << ",";
464  os << *i;
465  }
466  return os.str();
467  }
468 };
469 
478 template <>
479 struct __dispatch_opt<bool> {
480  static void init(bool& value) {
481  value = false;
482  }
483  static bool apply(const char */*svalue*/, bool& value) {
484  value = true;
485  return true;
486  }
487  static size_t size(bool /*value*/) {
488  return 0;
489  }
490  static void apply(std::ostream& /*os*/, bool /*value*/, bool /*required*/) {
491  }
492  static const std::string get_as_string(const bool& value) {
493  return value ? "true" : "false";
494  }
495 };
496 
497 
506 template <>
507 struct __dispatch_opt<std::string> {
508  static void init(std::string& /*value*/) {
509  }
510  static bool apply(const char *svalue, std::string& value) {
511  value = std::string(svalue);
512  return true;
513  }
514  static size_t size(std::string /*value*/) {
515  return 1;
516  }
517  static void apply(std::ostream& os, const std::string& value, bool required) {
518  if (value.empty())
519  if (required)
520  os << "[required] ";
521  else
522  os << "=NULL ";
523  else
524  os << "=" << value;
525  }
526  static const std::string get_as_string(const std::string& value) {
527  return value;
528  }
529 };
531 
532 
533 //
534 // Implementation of the standard option that holds a value
535 //
536 template <typename T>
537 TCmdOption<T>::TCmdOption(T& val, char short_opt, const char *long_opt,
538  const char *long_help, const char *short_help,
539  CCmdOptionFlags flags):
540  CCmdOption(short_opt, long_opt, long_help, short_help, flags),
541  m_value(val)
542 {
543  __dispatch_opt<T>::init(m_value);
544 }
545 
546 template <typename T>
547 bool TCmdOption<T>::do_set_value(const char *svalue)
548 {
549  return __dispatch_opt<T>::apply(svalue, m_value);
550 }
551 
552 template <typename T>
554 {
555  return __dispatch_opt<T>::size(m_value);
556 }
557 
558 template <typename T>
559 void TCmdOption<T>::do_write_value(std::ostream& os) const
560 {
561  __dispatch_opt<T>::apply( os, m_value, is_required());
562 }
563 
564 template <typename T>
565 void TCmdOption<T>::do_get_long_help_xml(std::ostream& os, xmlpp::Element& parent,
566  HandlerHelpMap& /*handler_map*/) const
567 {
568  do_get_long_help(os);
569  parent.set_attribute("type", __type_descr<T>::value);
570 }
571 
572 template <typename T>
573 const std::string TCmdOption<T>::do_get_value_as_string() const
574 {
575  return __dispatch_opt<T>::get_as_string(m_value);
576 }
577 
594 template <typename T>
595 PCmdOption make_opt(T& value, const char *long_opt, char short_opt,
596  const char *help, CCmdOptionFlags flags = CCmdOptionFlags::none)
597 {
598  bool required = has_flag(flags, CCmdOptionFlags::required);
599  return PCmdOption(new CParamOption( short_opt, long_opt, new CTParameter<T>(value, required, help)));
600 }
601 
619 template <typename T, typename Tmin, typename Tmax>
620 PCmdOption make_opt(T& value, Tmin min, Tmax max, const char *long_opt, char short_opt,
621  const char *help, CCmdOptionFlags flags = CCmdOptionFlags::none)
622 {
623  bool required = has_flag(flags, CCmdOptionFlags::required);
624  return PCmdOption(new CParamOption( short_opt, long_opt,
625  new TRangeParameter<T>(value, min, max, required, help)));
626 }
627 
645 template <typename T>
646 PCmdOption make_opt(std::vector<T>& value, const char *long_opt, char short_opt,
647  const char *help, CCmdOptionFlags flags = CCmdOptionFlags::none)
648 {
649  return PCmdOption(new TCmdOption<std::vector<T> >(value, short_opt, long_opt, help,
650  long_opt, flags ));
651 }
652 
666 PCmdOption make_opt(bool& value, const char *long_opt, char short_opt, const char *help);
667 
683 template <typename T>
684 PCmdOption make_opt(T& value, const TDictMap<T>& map,
685  const char *long_opt, char short_opt, const char *help)
686 {
687  return PCmdOption(new CParamOption( short_opt, long_opt,
688  new CDictParameter<T>(value, map, help)));
689 }
690 
691 
708 PCmdOption make_opt(int& value, const CFlagString& map, const char *long_opt,
709  char short_opt, const char *long_help,
710  const char *short_help,
712 
713 
729 PCmdOption make_opt(std::string& value, const char *long_opt, char short_opt, const char *long_help,
730  CCmdOptionFlags flags = CCmdOptionFlags::none, const CPluginHandlerBase *plugin_hint = NULL);
731 
732 
733 
749 template <typename T>
750 PCmdOption make_opt(T& value, const std::set<T>& valid_set,
751  const char *long_opt, char short_opt,
752  const char *help,
754 {
755  bool required = has_flag(flags, CCmdOptionFlags::required);
756  return PCmdOption(new CParamOption( short_opt, long_opt,
757  new CSetParameter<T>(value, valid_set, help, required)));
758 }
759 
760 
780 template <typename T>
781 PCmdOption make_opt(typename std::shared_ptr<T>& value, const char *default_value, const char *long_opt,
782  char short_opt, const char *help,
784 {
785  bool required = has_flag(flags, CCmdOptionFlags::required);
786  typedef typename FactoryTrait<T>::type F;
787  return PCmdOption(new CParamOption( short_opt, long_opt,
788  new TFactoryParameter<F>(value, default_value, required, help)));
789 }
790 
809 template <typename T>
810 PCmdOption make_opt(typename std::unique_ptr<T>& value, const char *default_value, const char *long_opt,
811  char short_opt, const char *help, CCmdOptionFlags flags = CCmdOptionFlags::none)
812 {
813  bool required = has_flag(flags, CCmdOptionFlags::required);
814  typedef typename FactoryTrait<T>::type F;
815  return PCmdOption(new CParamOption( short_opt, long_opt,
816  new TFactoryParameter<F>(value, default_value, required, help)));
817 }
818 
819 
830 PCmdOption make_help_opt(const char *long_opt, char short_opt,
831  const char *long_help, CHelpOption::Callback* cb);
832 
834 
835 #endif
std::pair< std::string, CHistoryRecord > CHistoryEntry
EXPORT_CORE const char * g_help_optiongroup
the string defining the name of the help options
std::map< std::string, std::string > CHistoryRecord
PCmdOption make_help_opt(const char *long_opt, char short_opt, const char *long_help, CHelpOption::Callback *cb)
Create a command line help option.
A parameter that get's initialized by a factory to a shared or unique pointer.
Definition: parameter.hh:269
A parameter that can only assume values out of a limited set.
Definition: parameter.hh:334
The base class for all command line options.
Definition: cmdoption.hh:50
#define NS_MIA_BEGIN
conveniance define to start the mia namespace
Definition: defines.hh:43
std::map< std::string, const CPluginHandlerBase * > HandlerHelpMap
A map that is used to collect the plug-in handlers used in a program.
Definition: handlerbase.hh:36
Command line option that translates a string to a set of flags.
TCmdOption(T &val, char short_opt, const char *long_opt, const char *long_help, const char *short_help, CCmdOptionFlags flags=CCmdOptionFlags::none)
std::map< EProgramDescriptionEntry, const char * > SProgramDescription
the map that holds a basic program description
The base class for all plugin handlers.
Definition: handlerbase.hh:57
A command line option that will appear in the help group and exits the program after printing the hel...
Templated version based on CCmdOptionValue for values that can be converted to and from strings by st...
Generic type of a complex paramter.
Definition: parameter.hh:164
CCmdFlagOption(int &val, const CFlagString &map, char short_opt, const char *long_opt, const char *long_help, const char *short_help, CCmdOptionFlags flags=CCmdOptionFlags::none)
Interface for the callback to print the help assositated with the given option.
CCmdOptionFlags
command line option that handles a parameter
Definition: paramoption.hh:36
Help callback to print the help for the given plug-in.
const mia::SProgramDescription description
Definition: autotest.hh:44
bool has_flag(CCmdOptionFlags flags, CCmdOptionFlags test)
std::shared_ptr< CCmdOption > PCmdOption
a shared pointer definition of the Option
Definition: cmdoption.hh:181
Scalar parameter with an expected value range.
Definition: parameter.hh:198
EProgramDescriptionEntry
program description entry identifiers
#define EXPORT_CORE
Macro to manage Visual C++ style dllimport/dllexport.
Definition: defines.hh:110
virtual void do_get_long_help(std::ostream &os) const
const char * long_help() const
Dictionary paramater.
Definition: parameter.hh:232
PCmdOption make_opt(T &value, const char *long_opt, char short_opt, const char *help, CCmdOptionFlags flags=CCmdOptionFlags::none)
Create a standard option that sets a value of the give type.
The class to hold the list of options.
const std::map< EProgramDescriptionEntry, const char * > g_DescriptionEntryNames
A mapper from emums to string values. - usefull for names flags.
Definition: dictmap.hh:45
#define NS_MIA_END
conveniance define to end the mia namespace
Definition: defines.hh:46