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-2015 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/typedescr.hh>
34 #include <mia/core/paramoption.hh>
35 #include <mia/core/dictmap.hh>
36 #include <mia/core/flagstring.hh>
37 #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, CXMLElement& 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 
169 public:
170 
175  hr_no = 0,
181  hr_selftest
182  };
183 
191 
193  ~CCmdOptionList();
194 
198  void add(PCmdOption opt);
199 
204  void add(const std::string& group, PCmdOption opt);
205 
215  void add_selftest(int& test_result, CSelftestCallback *callback);
216 
227  EHelpRequested parse(size_t argc, char *args[], const std::string& additional_type,
228  const CPluginHandlerBase *additional_help = NULL)
229  __attribute__((warn_unused_result));
230 
242  EHelpRequested parse(size_t argc, const char *args[], const std::string& additional_type,
243  const CPluginHandlerBase *additional_help = NULL)
244  __attribute__((warn_unused_result));
245 
251  EHelpRequested parse(size_t argc, char *args[]) __attribute__((warn_unused_result));
252 
258  EHelpRequested parse(size_t argc, const char *args[]) __attribute__((warn_unused_result));
259 
261  const std::vector<std::string>& get_remaining() const;
262 
266  CHistoryRecord get_values() const;
267 
272  void set_group(const std::string& group);
273 
278  void set_logstream(std::ostream& os);
279 
280 
283  void set_stdout_is_result();
284 private:
285  EHelpRequested do_parse(size_t argc, const char *args[], bool has_additional,
286  const CPluginHandlerBase *additional_help)
287  __attribute__((warn_unused_result));
288  int handle_shortargs(const char *arg, size_t argc, const char *args[]);
289  struct CCmdOptionListData *m_impl;
290 };
291 
292 
293 // implementation of template classes and functions
294 
307 template <typename T>
308 struct __dispatch_opt {
312  static void init(T& /*value*/){
313  }
314 
320  static bool apply(const char *svalue, T& value) {
321  std::istringstream sval(svalue);
322 
323  sval >> value;
324  while (isspace(sval.peek())) {
325  char c;
326  sval >> c;
327  }
328  return sval.eof();
329  }
331  static size_t size(const T /*value*/) {
332  return 1;
333  }
334 
340  static void apply(std::ostream& os, const T& value, bool /*required*/) {
341  os << "=" << value << " ";
342  }
343 
349  static const std::string get_as_string(const T& value) {
350  std::ostringstream os;
351  os << value;
352  return os.str();
353  }
354 };
355 
361 template <typename T>
362 struct __dispatch_opt< std::vector<T> > {
363  static void init(std::vector<T>& /*value*/){
364 
365  }
366  static bool apply(const char *svalue, std::vector<T>& value) {
367  std::string h(svalue);
368  unsigned int n = 1;
369  for(std::string::iterator hb = h.begin(); hb != h.end(); ++hb)
370  if (*hb == ',') {
371  *hb = ' ';
372  ++n;
373  }
374 
375 
376  if (!value.empty()) {
377  if (n > value.size()) {
378  throw create_exception<std::invalid_argument>("Expect only ", value.size(),
379  " coma separated values, but '",
380  svalue, "' provides ", n);
381  }
382  }else{
383  value.resize(n);
384  }
385 
386  std::istringstream sval(h);
387  auto i = value.begin();
388  while (!sval.eof()) {
389  sval >> *i;
390  ++i;
391  }
392  return sval.eof();
393  }
394 
395  static size_t size(const std::vector<T>& /*value*/) {
396  return 1;
397  }
398 
399  static void apply(std::ostream& os, const std::vector<T>& value, bool required) {
400 
401  os << "=";
402  if (value.empty() && required)
403  os << "[required] ";
404  else {
405  for (auto i = value.begin(); i != value.end(); ++i) {
406  if (i != value.begin())
407  os << ",";
408  os << *i;
409  }
410  os << " ";
411  }
412  }
413 
414  static const std::string get_as_string(const std::vector<T>& value) {
415  std::ostringstream os;
416  for (auto i = value.begin(); i != value.end(); ++i) {
417  if (i != value.begin())
418  os << ",";
419  os << *i;
420  }
421  return os.str();
422  }
423 };
424 
433 template <>
434 struct __dispatch_opt<bool> {
435  static void init(bool& value) {
436  value = false;
437  }
438  static bool apply(const char */*svalue*/, bool& value) {
439  value = true;
440  return true;
441  }
442  static size_t size(bool /*value*/) {
443  return 0;
444  }
445  static void apply(std::ostream& /*os*/, bool /*value*/, bool /*required*/) {
446  }
447  static const std::string get_as_string(const bool& value) {
448  return value ? "true" : "false";
449  }
450 };
451 
452 
461 template <>
462 struct __dispatch_opt<std::string> {
463  static void init(std::string& /*value*/) {
464  }
465  static bool apply(const char *svalue, std::string& value) {
466  value = std::string(svalue);
467  return true;
468  }
469  static size_t size(std::string /*value*/) {
470  return 1;
471  }
472  static void apply(std::ostream& os, const std::string& value, bool required) {
473  if (value.empty())
474  if (required)
475  os << "[required] ";
476  else
477  os << "=NULL ";
478  else
479  os << "=" << value;
480  }
481  static const std::string get_as_string(const std::string& value) {
482  return value;
483  }
484 };
486 
487 
488 //
489 // Implementation of the standard option that holds a value
490 //
491 template <typename T>
492 TCmdOption<T>::TCmdOption(T& val, char short_opt, const char *long_opt,
493  const char *long_help, const char *short_help,
494  CCmdOptionFlags flags):
495  CCmdOption(short_opt, long_opt, long_help, short_help, flags),
496  m_value(val)
497 {
498  __dispatch_opt<T>::init(m_value);
499 }
500 
501 template <typename T>
502 bool TCmdOption<T>::do_set_value(const char *svalue)
503 {
504  return __dispatch_opt<T>::apply(svalue, m_value);
505 }
506 
507 template <typename T>
509 {
510  return __dispatch_opt<T>::size(m_value);
511 }
512 
513 template <typename T>
514 void TCmdOption<T>::do_write_value(std::ostream& os) const
515 {
516  __dispatch_opt<T>::apply( os, m_value, is_required());
517 }
518 
519 template <typename T>
520 void TCmdOption<T>::do_get_long_help_xml(std::ostream& os, CXMLElement& parent,
521  HandlerHelpMap& /*handler_map*/) const
522 {
523  do_get_long_help(os);
524  parent.set_attribute("type", __type_descr<T>::value);
525 }
526 
527 template <typename T>
528 const std::string TCmdOption<T>::do_get_value_as_string() const
529 {
530  return __dispatch_opt<T>::get_as_string(m_value);
531 }
532 
549 template <typename T>
550 PCmdOption make_opt(T& value, const char *long_opt, char short_opt,
551  const char *help, CCmdOptionFlags flags = CCmdOptionFlags::none)
552 {
553  bool required = has_flag(flags, CCmdOptionFlags::required);
554  return PCmdOption(new CParamOption( short_opt, long_opt, new CTParameter<T>(value, required, help)));
555 }
556 
572 template <typename T>
573 PCmdOption make_opt(T& value, EParameterBounds bflags, const std::vector<T>& bounds,
574  const char *long_opt, char short_opt,
575  const char *help, CCmdOptionFlags flags = CCmdOptionFlags::none)
576 {
577  bool required = has_flag(flags, CCmdOptionFlags::required);
578  return PCmdOption(new CParamOption( short_opt, long_opt,
579  new TBoundedParameter<T>(value, bflags, bounds, required, help)));
580 }
581 
599 template <typename T>
600 PCmdOption make_opt(std::vector<T>& value, const char *long_opt, char short_opt,
601  const char *help, CCmdOptionFlags flags = CCmdOptionFlags::none)
602 {
603  return PCmdOption(new TCmdOption<std::vector<T> >(value, short_opt, long_opt, help,
604  long_opt, flags ));
605 }
606 
621 PCmdOption make_opt(bool& value, const char *long_opt, char short_opt, const char *help,
623 
639 template <typename T>
640 PCmdOption make_opt(T& value, const TDictMap<T>& map,
641  const char *long_opt, char short_opt, const char *help)
642 {
643  return PCmdOption(new CParamOption( short_opt, long_opt,
644  new CDictParameter<T>(value, map, help)));
645 }
646 
647 
664 PCmdOption make_opt(int& value, const CFlagString& map, const char *long_opt,
665  char short_opt, const char *long_help,
666  const char *short_help,
668 
669 
685 PCmdOption make_opt(std::string& value, const char *long_opt, char short_opt, const char *long_help,
686  CCmdOptionFlags flags = CCmdOptionFlags::none, const CPluginHandlerBase *plugin_hint = NULL);
687 
688 
689 
705 template <typename T>
706 PCmdOption make_opt(T& value, const std::set<T>& valid_set,
707  const char *long_opt, char short_opt,
708  const char *help,
710 {
711  bool required = has_flag(flags, CCmdOptionFlags::required);
712  return PCmdOption(new CParamOption( short_opt, long_opt,
713  new CSetParameter<T>(value, valid_set, help, required)));
714 }
715 
716 
736 template <typename T>
737 PCmdOption make_opt(typename std::shared_ptr<T>& value, const char *default_value, const char *long_opt,
738  char short_opt, const char *help,
740 {
741  bool required = has_flag(flags, CCmdOptionFlags::required);
742  typedef typename FactoryTrait<T>::type F;
743  return PCmdOption(new CParamOption( short_opt, long_opt,
744  new TFactoryParameter<F>(value, default_value, required, help)));
745 }
746 
765 template <typename T>
766 PCmdOption make_opt(typename std::unique_ptr<T>& value, const char *default_value, const char *long_opt,
767  char short_opt, const char *help, CCmdOptionFlags flags = CCmdOptionFlags::none)
768 {
769  bool required = has_flag(flags, CCmdOptionFlags::required);
770  typedef typename FactoryTrait<T>::type F;
771  return PCmdOption(new CParamOption( short_opt, long_opt,
772  new TFactoryParameter<F>(value, default_value, required, help)));
773 }
774 
775 
777 
778 #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
void set_attribute(const char *name, const std::string &value)
Set an attribute of the node.
A parameter that get's initialized by a factory to a shared or unique pointer.
Definition: parameter.hh:380
A parameter that can only assume values out of a limited set.
Definition: parameter.hh:445
The base class for all command line options.
Definition: cmdoption.hh:50
class EXPORT_CORE CMeans private
#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
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:163
EParameterBounds
Scalar parameter with an expected value range.
Definition: parameter.hh:208
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)
CCmdOptionFlags
command line option that handles a parameter
Definition: paramoption.hh:36
This class implements a facade for the xml Element.
Definition: xmlinterface.hh:42
const mia::SProgramDescription description
Definition: autotest.hh:44
std::shared_ptr< CCmdOption > PCmdOption
a shared pointer definition of the Option
Definition: cmdoption.hh:178
EProgramDescriptionEntry
program description entry identifiers
#define EXPORT_CORE
Macro to manage Visual C++ style dllimport/dllexport.
Definition: defines.hh:110
const char * long_help() const
Dictionary parameter.
Definition: parameter.hh:343
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