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-2013 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, bool flags = false);
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, bool flags = false);
148 private:
149  virtual bool do_set_value(const char *str_value);
150  virtual size_t do_get_needed_args() const;
151  virtual void do_write_value(std::ostream& os) const;
152  virtual void do_get_long_help(std::ostream& os) const;
153  virtual const std::string do_get_value_as_string() const;
154  int& m_value;
155  const CFlagString m_map;
156 };
157 
158 
169 public:
170 
175  class Callback {
176  public:
181  virtual void print(std::ostream& os) const = 0;
182  };
183 
190  CHelpOption(Callback *cb, char short_opt, const char*long_opt, const char *long_help);
191 
195  void print(std::ostream& os) const;
196 
197 private:
198  std::unique_ptr<Callback> m_callback;
199  virtual bool do_set_value(const char *str_value);
200  virtual size_t do_get_needed_args() const;
201  virtual void do_write_value(std::ostream& os) const;
202  virtual void do_get_long_help(std::ostream& os) const;
203  virtual void do_get_long_help_xml(std::ostream& os, xmlpp::Element& parent,
204  HandlerHelpMap& /*handler_map*/) const;
205 
206 };
207 
213 template <typename PluginHandler>
215  void print(std::ostream& os) const{
216  PluginHandler::instance().print_help(os);
217  }
218 };
219 
220 
230 public:
231 
236  hr_no = 0,
241  hr_copyright
242  };
243 
251 
253  ~CCmdOptionList();
254 
258  void add(PCmdOption opt);
259 
264  void add(const std::string& group, PCmdOption opt);
265 
276  EHelpRequested parse(size_t argc, char *args[], const std::string& additional_type,
277  const CPluginHandlerBase *additional_help = NULL)
278  __attribute__((warn_unused_result));
279 
291  EHelpRequested parse(size_t argc, const char *args[], const std::string& additional_type,
292  const CPluginHandlerBase *additional_help = NULL)
293  __attribute__((warn_unused_result));
294 
300  EHelpRequested parse(size_t argc, char *args[]) __attribute__((warn_unused_result));
301 
307  EHelpRequested parse(size_t argc, const char *args[]) __attribute__((warn_unused_result));
308 
310  const std::vector<std::string>& get_remaining() const;
311 
315  CHistoryRecord get_values() const;
316 
321  void set_group(const std::string& group);
322 
327  void set_logstream(std::ostream& os);
328 private:
329  EHelpRequested do_parse(size_t argc, const char *args[], bool has_additional,
330  const CPluginHandlerBase *additional_help)
331  __attribute__((warn_unused_result));
332  int handle_shortargs(const char *arg, size_t argc, const char *args[]);
333  struct CCmdOptionListData *m_impl;
334 };
335 
336 
337 // implementation of template classes and functions
338 
351 template <typename T>
352 struct __dispatch_opt {
356  static void init(T& /*value*/){
357  }
358 
364  static bool apply(const char *svalue, T& value) {
365  std::istringstream sval(svalue);
366 
367  sval >> value;
368  while (isspace(sval.peek())) {
369  char c;
370  sval >> c;
371  }
372  return sval.eof();
373  }
375  static size_t size(const T /*value*/) {
376  return 1;
377  }
378 
384  static void apply(std::ostream& os, const T& value, bool /*required*/) {
385  os << "=" << value << " ";
386  }
387 
393  static const std::string get_as_string(const T& value) {
394  std::ostringstream os;
395  os << value;
396  return os.str();
397  }
398 };
399 
405 template <typename T>
406 struct __dispatch_opt< std::vector<T> > {
407  static void init(std::vector<T>& /*value*/){
408 
409  }
410  static bool apply(const char *svalue, std::vector<T>& value) {
411  std::string h(svalue);
412  unsigned int n = 1;
413  for(std::string::iterator hb = h.begin(); hb != h.end(); ++hb)
414  if (*hb == ',') {
415  *hb = ' ';
416  ++n;
417  }
418 
419 
420  if (!value.empty()) {
421  if (n > value.size()) {
422  throw create_exception<std::invalid_argument>("Expect only ", value.size(),
423  " coma separated values, but '",
424  svalue, "' provides ", n);
425  }
426  }else{
427  value.resize(n);
428  }
429 
430  std::istringstream sval(h);
431  auto i = value.begin();
432  while (!sval.eof()) {
433  sval >> *i;
434  ++i;
435  }
436  return sval.eof();
437  }
438 
439  static size_t size(const std::vector<T>& /*value*/) {
440  return 1;
441  }
442 
443  static void apply(std::ostream& os, const std::vector<T>& value, bool required) {
444 
445  os << "=";
446  if (value.empty() && required)
447  os << "[required] ";
448  else {
449  for (auto i = value.begin(); i != value.end(); ++i) {
450  if (i != value.begin())
451  os << ",";
452  os << *i;
453  }
454  os << " ";
455  }
456  }
457 
458  static const std::string get_as_string(const std::vector<T>& value) {
459  std::ostringstream os;
460  for (auto i = value.begin(); i != value.end(); ++i) {
461  if (i != value.begin())
462  os << ",";
463  os << *i;
464  }
465  return os.str();
466  }
467 };
468 
477 template <>
478 struct __dispatch_opt<bool> {
479  static void init(bool& value) {
480  value = false;
481  }
482  static bool apply(const char */*svalue*/, bool& value) {
483  value = true;
484  return true;
485  }
486  static size_t size(bool /*value*/) {
487  return 0;
488  }
489  static void apply(std::ostream& /*os*/, bool /*value*/, bool /*required*/) {
490  }
491  static const std::string get_as_string(const bool& value) {
492  return value ? "true" : "false";
493  }
494 };
495 
496 
505 template <>
506 struct __dispatch_opt<std::string> {
507  static void init(std::string& /*value*/) {
508  }
509  static bool apply(const char *svalue, std::string& value) {
510  value = std::string(svalue);
511  return true;
512  }
513  static size_t size(std::string /*value*/) {
514  return 1;
515  }
516  static void apply(std::ostream& os, const std::string& value, bool required) {
517  if (value.empty())
518  if (required)
519  os << "[required] ";
520  else
521  os << "=NULL ";
522  else
523  os << "=" << value;
524  }
525  static const std::string get_as_string(const std::string& value) {
526  return value;
527  }
528 };
530 
531 
532 //
533 // Implementation of the standard option that holds a value
534 //
535 template <typename T>
536 TCmdOption<T>::TCmdOption(T& val, char short_opt, const char *long_opt,
537  const char *long_help, const char *short_help, bool flags):
538  CCmdOption(short_opt, long_opt, long_help, short_help, flags),
539  m_value(val)
540 {
541  __dispatch_opt<T>::init(m_value);
542 }
543 
544 template <typename T>
545 bool TCmdOption<T>::do_set_value(const char *svalue)
546 {
547  return __dispatch_opt<T>::apply(svalue, m_value);
548 }
549 
550 template <typename T>
552 {
553  return __dispatch_opt<T>::size(m_value);
554 }
555 
556 template <typename T>
557 void TCmdOption<T>::do_write_value(std::ostream& os) const
558 {
559  __dispatch_opt<T>::apply( os, m_value, is_required());
560 }
561 
562 template <typename T>
563 void TCmdOption<T>::do_get_long_help_xml(std::ostream& os, xmlpp::Element& parent,
564  HandlerHelpMap& /*handler_map*/) const
565 {
566  do_get_long_help(os);
567  parent.set_attribute("type", __type_descr<T>::value);
568 }
569 
570 template <typename T>
571 const std::string TCmdOption<T>::do_get_value_as_string() const
572 {
573  return __dispatch_opt<T>::get_as_string(m_value);
574 }
575 
592 template <typename T>
593 PCmdOption make_opt(T& value, const char *long_opt, char short_opt,
594  const char *help, bool flags = false)
595 {
596  return PCmdOption(new CParamOption( short_opt, long_opt, new CTParameter<T>(value, flags, help)));
597 }
598 
616 template <typename T, typename Tmin, typename Tmax>
617 PCmdOption make_opt(T& value, Tmin min, Tmax max, const char *long_opt, char short_opt,
618  const char *help, bool flags = false)
619 {
620  return PCmdOption(new CParamOption( short_opt, long_opt,
621  new TRangeParameter<T>(value, min, max, flags, help)));
622 }
623 
641 template <typename T>
642 PCmdOption make_opt(std::vector<T>& value, const char *long_opt, char short_opt,
643  const char *help, bool required = false)
644 {
645  return PCmdOption(new TCmdOption<std::vector<T> >(value, short_opt, long_opt, help,
646  long_opt, required ));
647 }
648 
662 PCmdOption make_opt(bool& value, const char *long_opt, char short_opt, const char *help);
663 
679 template <typename T>
680 PCmdOption make_opt(T& value, const TDictMap<T>& map,
681  const char *long_opt, char short_opt, const char *help)
682 {
683  return PCmdOption(new CParamOption( short_opt, long_opt,
684  new CDictParameter<T>(value, map, help)));
685 }
686 
687 
704 PCmdOption make_opt(int& value, const CFlagString& map, const char *long_opt,
705  char short_opt, const char *long_help,
706  const char *short_help,
707  bool flags = false);
708 
709 
725 PCmdOption make_opt(std::string& value, const char *long_opt, char short_opt, const char *long_help,
726  bool required = false, const CPluginHandlerBase *plugin_hint = NULL);
727 
728 
729 
745 template <typename T>
746 PCmdOption make_opt(T& value, const std::set<T>& valid_set,
747  const char *long_opt, char short_opt,
748  const char *help,
749  bool required = false)
750 {
751  return PCmdOption(new CParamOption( short_opt, long_opt,
752  new CSetParameter<T>(value, valid_set, help, required)));
753 }
754 
755 
775 template <typename T>
776 PCmdOption make_opt(typename std::shared_ptr<T>& value, const char *default_value, const char *long_opt,
777  char short_opt, const char *help, bool required = false)
778 {
779  typedef typename FactoryTrait<T>::type F;
780  return PCmdOption(new CParamOption( short_opt, long_opt,
781  new TFactoryParameter<F>(value, default_value, required, help)));
782 }
783 
802 template <typename T>
803 PCmdOption make_opt(typename std::unique_ptr<T>& value, const char *default_value, const char *long_opt,
804  char short_opt, const char *help, bool required = false)
805 {
806  typedef typename FactoryTrait<T>::type F;
807  return PCmdOption(new CParamOption( short_opt, long_opt,
808  new TFactoryParameter<F>(value, default_value, required, help)));
809 }
810 
811 
822 PCmdOption make_help_opt(const char *long_opt, char short_opt,
823  const char *long_help, CHelpOption::Callback* cb);
824 
826 
827 #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:268
A parameter that can only assume values out of a limited set.
Definition: parameter.hh:333
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.
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
PCmdOption make_opt(T &value, const char *long_opt, char short_opt, const char *help, bool flags=false)
Create a standard option that sets a value of the give type.
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...
CCmdFlagOption(int &val, const CFlagString &map, char short_opt, const char *long_opt, const char *long_help, const char *short_help, bool flags=false)
Generic type of a complex paramter.
Definition: parameter.hh:163
Interface for the callback to print the help assositated with the given option.
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:43
std::shared_ptr< CCmdOption > PCmdOption
a shared pointer definition of the Option
Definition: cmdoption.hh:171
Scalar parameter with an expected value range.
Definition: parameter.hh:197
EProgramDescriptionEntry
program description entry identifiers
#define EXPORT_CORE
Macro to manage Visual C++ style dllimport/dllexport.
Definition: defines.hh:111
virtual void do_get_long_help(std::ostream &os) const
const char * long_help() const
Dictionary paramater.
Definition: parameter.hh:231
The class to hold the list of options.
const std::map< EProgramDescriptionEntry, const char * > g_DescriptionEntryNames
TCmdOption(T &val, char short_opt, const char *long_opt, const char *long_help, const char *short_help, bool flags=false)
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