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