new library for arguments - namespace mrw added; refs #6
This commit is contained in:
		@@ -21,57 +21,66 @@ int main(int argc, char** argv) try {
 | 
			
		||||
 | 
			
		||||
  // bind and evaluate options
 | 
			
		||||
#ifdef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
  args::list options;
 | 
			
		||||
  std::vector<std::shared_ptr<args::abstract_parameter> > params;
 | 
			
		||||
  params.push_back(args::help());
 | 
			
		||||
  params.push_back(args::exit());
 | 
			
		||||
  options.push_back(args::declaration("h", "help", "show this help", params));
 | 
			
		||||
  mrw::args::list options;
 | 
			
		||||
  std::vector<std::shared_ptr<mrw::args::abstract_parameter> > params;
 | 
			
		||||
  params.push_back(mrw::args::help());
 | 
			
		||||
  params.push_back(mrw::args::exit());
 | 
			
		||||
  options.push_back(mrw::args::declaration("h", "help", "show this help",
 | 
			
		||||
                                           params));
 | 
			
		||||
  params.clear();
 | 
			
		||||
  params.push_back(args::param(r, "number"));
 | 
			
		||||
  options.push_back(args::declaration("r", "repeat", "number of repetitions",
 | 
			
		||||
                                      params));
 | 
			
		||||
  params.push_back(mrw::args::param(r, "number"));
 | 
			
		||||
  options.push_back(mrw::args::declaration("r", "repeat",
 | 
			
		||||
                                           "number of repetitions",
 | 
			
		||||
                                           params));
 | 
			
		||||
  params.clear();
 | 
			
		||||
  params.push_back(args::param(flag));
 | 
			
		||||
  options.push_back(args::declaration("f", "flag", "check a flag", params));
 | 
			
		||||
  params.push_back(mrw::args::param(flag));
 | 
			
		||||
  options.push_back(mrw::args::declaration("f", "flag", "check a flag",
 | 
			
		||||
                                           params));
 | 
			
		||||
  params.clear();
 | 
			
		||||
  params.push_back(args::param(txt, "text"));
 | 
			
		||||
  options.push_back(args::declaration("t", "text", "pass a text", params));
 | 
			
		||||
  params.push_back(mrw::args::param(txt, "text"));
 | 
			
		||||
  options.push_back(mrw::args::declaration("t", "text", "pass a text", params));
 | 
			
		||||
  params.clear();
 | 
			
		||||
  params.push_back(args::param(x, "x"));
 | 
			
		||||
  params.push_back(args::param(y, "y"));
 | 
			
		||||
  options.push_back(args::declaration("c", "coord", "add some 2D coordinates",
 | 
			
		||||
                                      params));
 | 
			
		||||
  params.push_back(mrw::args::param(x, "x"));
 | 
			
		||||
  params.push_back(mrw::args::param(y, "y"));
 | 
			
		||||
  options.push_back(mrw::args::declaration("c", "coord",
 | 
			
		||||
                                           "add some 2D coordinates",
 | 
			
		||||
                                           params));
 | 
			
		||||
  params.clear();
 | 
			
		||||
  params.push_back(args::func(test_func));
 | 
			
		||||
  options.push_back(args::declaration("",  "test",
 | 
			
		||||
                                      "call test_func, no shortcut", params));
 | 
			
		||||
  args::init(argc, argv, "This is an example for argument processing.",
 | 
			
		||||
             options);
 | 
			
		||||
  params.push_back(mrw::args::func(test_func));
 | 
			
		||||
  options.push_back(mrw::args::declaration("",  "test",
 | 
			
		||||
                                           "call test_func, no shortcut",
 | 
			
		||||
                                           params));
 | 
			
		||||
  mrw::args::parse(argc, argv, "This is an example for argument processing.",
 | 
			
		||||
                   options);
 | 
			
		||||
#else
 | 
			
		||||
  args::init(argc, argv,
 | 
			
		||||
             "This is an example for argument processing. If the description "
 | 
			
		||||
             "is very long, it is automatically splitted over several lines "
 | 
			
		||||
             "and indented on each new line. Arguments may have several "
 | 
			
		||||
             "parameters. Help is generated automatically from the argument "
 | 
			
		||||
             "declaration. The argument declaration contains long and short "
 | 
			
		||||
             "options and a list of parameters.",
 | 
			
		||||
             {
 | 
			
		||||
               {"h", "help", "show this help", {args::help(), args::exit()}},
 | 
			
		||||
               {"r", "repeat", "number of repetitions",
 | 
			
		||||
                   {args::param(r, "number")}},
 | 
			
		||||
               {"f", "flag",
 | 
			
		||||
                   "check a flag; this is a boolean, so it is false by "
 | 
			
		||||
                   "default and true if the user specifies the flag on "
 | 
			
		||||
                   "the command line", {args::param(flag)}},
 | 
			
		||||
               {"t", "text", "pass a text", {args::param(txt, "text")}},
 | 
			
		||||
               {"c", "coord",
 | 
			
		||||
                   "add some 2D coordinates; this is an example on how "
 | 
			
		||||
                   "you can add more than one parameter",
 | 
			
		||||
                     {args::param(x, "x"), args::param(y, "y")}},
 | 
			
		||||
               {"",  "test", "call test_func, no shortcut",
 | 
			
		||||
                   {args::func(test_func)}},
 | 
			
		||||
             },
 | 
			
		||||
             "Returns a status of 0 on success and 1 on any error.");
 | 
			
		||||
  mrw::args::parse(argc, argv,
 | 
			
		||||
                   "This is an example for argument processing. If the"
 | 
			
		||||
                   " description is very long, it is automatically splitted"
 | 
			
		||||
                   " over several lines and indented on each new line."
 | 
			
		||||
                   " Arguments may have several parameters. Help is"
 | 
			
		||||
                   " generated automatically from the argument declaration."
 | 
			
		||||
                   " The argument declaration contains long and short options"
 | 
			
		||||
                   " and a list of parameters.",
 | 
			
		||||
                   {
 | 
			
		||||
                     {"h", "help", "show this help",
 | 
			
		||||
                         {mrw::args::help(), mrw::args::exit()}},
 | 
			
		||||
                     {"r", "repeat", "number of repetitions",
 | 
			
		||||
                         {mrw::args::param(r, "number")}},
 | 
			
		||||
                     {"f", "flag",
 | 
			
		||||
                         "check a flag; this is a boolean, so it is false by "
 | 
			
		||||
                         "default and true if the user specifies the flag on "
 | 
			
		||||
                         "the command line", {mrw::args::param(flag)}},
 | 
			
		||||
                     {"t", "text", "pass a text",
 | 
			
		||||
                         {mrw::args::param(txt, "text")}},
 | 
			
		||||
                     {"c", "coord",
 | 
			
		||||
                         "add some 2D coordinates; this is an example on how "
 | 
			
		||||
                         "you can add more than one parameter",
 | 
			
		||||
                           {mrw::args::param(x, "x"),
 | 
			
		||||
                            mrw::args::param(y, "y")}},
 | 
			
		||||
                     {"",  "test", "call test_func, no shortcut",
 | 
			
		||||
                         {mrw::args::func(test_func)}},
 | 
			
		||||
                   },
 | 
			
		||||
                   "Returns a status of 0 on success and 1 on any error.");
 | 
			
		||||
#endif
 | 
			
		||||
  
 | 
			
		||||
  // show the result
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										702
									
								
								src/mrw/args
									
									
									
									
									
								
							
							
						
						
									
										702
									
								
								src/mrw/args
									
									
									
									
									
								
							@@ -7,6 +7,8 @@
 | 
			
		||||
#ifndef __ARGS__
 | 
			
		||||
#define __ARGS__
 | 
			
		||||
 | 
			
		||||
#include <mrw/iomanip>
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <memory>
 | 
			
		||||
@@ -15,10 +17,11 @@
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#include <numeric>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <cstdlib> // exit()
 | 
			
		||||
 | 
			
		||||
// check if code is compiled with a new C++11 compiler
 | 
			
		||||
// otherwise there is a fallback wich makes everything much more compliacted
 | 
			
		||||
#ifndef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
#if __cplusplus < 201103L
 | 
			
		||||
/// Code is compiled with an old non C++11 standard compliant compiler
 | 
			
		||||
/** There are workarounds for old non C++11 compatible
 | 
			
		||||
@@ -33,6 +36,13 @@
 | 
			
		||||
#warning this is deprecated and will be removed in future releases
 | 
			
		||||
#warning refere to the library documentation for more details
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @page oldcompiler Workaround for old non C++11 compilers
 | 
			
		||||
    ... to be documented
 | 
			
		||||
    @note Old compilers are automatically detected and the flag
 | 
			
		||||
          @refs ARGS__OLD_PRE11_COMPILER is set.
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
#ifdef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
#include <boost/shared_ptr.hpp>
 | 
			
		||||
@@ -46,393 +56,333 @@ namespace std {
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @page oldcompiler Workaround for old non C++11 compilers
 | 
			
		||||
    ... to be documented
 | 
			
		||||
    @note Old compilers are automatically detected and the flag
 | 
			
		||||
          @refs ARGS__OLD_PRE11_COMPILER is set.
 | 
			
		||||
    */
 | 
			
		||||
namespace mrw {
 | 
			
		||||
  /// Cool and easy evaluation of commandline arguments in C++11.
 | 
			
		||||
  /** Evaluating command line arguments is extremely easy with this library:
 | 
			
		||||
      @begincode
 | 
			
		||||
        void test_func();                // bound to option --test
 | 
			
		||||
      
 | 
			
		||||
        int main(int argc, char** argv) try {
 | 
			
		||||
      
 | 
			
		||||
          // option variables
 | 
			
		||||
          bool flag;                      // bound to option --flag
 | 
			
		||||
          int r(5);                       // bound to option --repeat
 | 
			
		||||
          std::string txt("Hello World"); // bound to option --text
 | 
			
		||||
          int x(0), y(0);                 // bound to option --coord
 | 
			
		||||
 | 
			
		||||
/// Cool and easy evaluation of commandline arguments in C++11.
 | 
			
		||||
/** Evaluating command line arguments is extremely easy with this library:
 | 
			
		||||
    @begincode
 | 
			
		||||
    void test_func();                // bound to option --test
 | 
			
		||||
    
 | 
			
		||||
    int main(int argc, char** argv) try {
 | 
			
		||||
    
 | 
			
		||||
      // option variables
 | 
			
		||||
      bool flag;                      // bound to option --flag
 | 
			
		||||
      int r(5);                       // bound to option --repeat
 | 
			
		||||
      std::string txt("Hello World"); // bound to option --text
 | 
			
		||||
      int x(0), y(0);                 // bound to option --coord
 | 
			
		||||
          // bind and evaluate options
 | 
			
		||||
          args::parse(argc, argv, "This is an example for argument processing.",
 | 
			
		||||
                      {
 | 
			
		||||
            {"h", "help", "show this help", {args::help(), args::exit()}},
 | 
			
		||||
            {"r", "repeat", "number of repetitions",
 | 
			
		||||
             {args::param(r, "number")}},
 | 
			
		||||
            {"f", "flag", "check a flag", {args::param(flag)}},
 | 
			
		||||
            {"t", "text", "pass a text", {args::param(txt, "text")}},
 | 
			
		||||
            {"c", "coord", "add some 2D coordinates", {args::param(x, "x"),
 | 
			
		||||
                                                       args::param(y, "y")}},
 | 
			
		||||
            {"",  "test", "call test_func, no shortcut",
 | 
			
		||||
             {args::func(test_func)}},
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
      // bind and evaluate options
 | 
			
		||||
      args::init(argc, argv, "This is an example for argument processing.", {
 | 
			
		||||
        {"h", "help", "show this help", {args::help(), args::exit()}},
 | 
			
		||||
        {"r", "repeat", "number of repetitions", {args::param(r, "number")}},
 | 
			
		||||
        {"f", "flag", "check a flag", {args::param(flag)}},
 | 
			
		||||
        {"t", "text", "pass a text", {args::param(txt, "text")}},
 | 
			
		||||
        {"c", "coord", "add some 2D coordinates", {args::param(x, "x"),
 | 
			
		||||
                                                   args::param(y, "y")}},
 | 
			
		||||
        {"",  "test", "call test_func, no shortcut", {args::func(test_func)}},
 | 
			
		||||
      });
 | 
			
		||||
          // [...] now the variables are setup according to the user's choice
 | 
			
		||||
 | 
			
		||||
      // [...] now the variables are setup according to the user's choice
 | 
			
		||||
 | 
			
		||||
      return 0;
 | 
			
		||||
    } catch (const std::exception& x) { // error in commandline options
 | 
			
		||||
      std::cerr<<"**** ERROR: "<<x.what()<<std::endl;
 | 
			
		||||
      args::show_help(); // display help
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
    @endcode
 | 
			
		||||
    @note This library requires C++11, but there is also a fallback
 | 
			
		||||
          for old compilers. But the calling syntax is much worse on
 | 
			
		||||
          non C++11 compliant compilers, so the use of a modern
 | 
			
		||||
          compiler is strongly recommended. On GNU GCC, you may have
 | 
			
		||||
          to add the commandline option @c -std=c++11
 | 
			
		||||
    @note I suggest to take this library into the next C++ standard.
 | 
			
		||||
    */
 | 
			
		||||
namespace args {
 | 
			
		||||
  /// Parent for holding a reference to a parameter variable.
 | 
			
		||||
  /** This class ist used only as parent for instances of template
 | 
			
		||||
      parameters.  It represents one parameter that is evaluated when
 | 
			
		||||
      a commandline option is given. The derived classes hold a
 | 
			
		||||
      reference to a variable that is set in method @ref evaluate when
 | 
			
		||||
      the specific commandline parameter is given. */
 | 
			
		||||
  class abstract_parameter {
 | 
			
		||||
    public:
 | 
			
		||||
      /// Called when the user specifies the related commandline option.
 | 
			
		||||
      /** Method must be implemented according to the specific type in
 | 
			
		||||
          the child classes. */
 | 
			
		||||
      virtual void evaluate(char**& a, char** max) = 0;
 | 
			
		||||
      /// Convert the actual value to a string.
 | 
			
		||||
      /** Defaults to empty string, can be overwritten in child
 | 
			
		||||
          classes. Used by the help function to show the default
 | 
			
		||||
          value. */
 | 
			
		||||
      virtual operator std::string() {
 | 
			
		||||
        return std::string();
 | 
			
		||||
      }
 | 
			
		||||
      virtual std::string type() {
 | 
			
		||||
        return std::string();
 | 
			
		||||
      }
 | 
			
		||||
  };
 | 
			
		||||
  // default implementation for all types
 | 
			
		||||
  template<typename T> class parameter: public abstract_parameter {
 | 
			
		||||
    public:
 | 
			
		||||
      parameter(T& ref, const std::string& s = std::string()):
 | 
			
		||||
          _ref(ref), _type(s) {}
 | 
			
		||||
      virtual void evaluate(char**& a, char** max) {
 | 
			
		||||
        if (max<a+1)
 | 
			
		||||
          throw std::runtime_error("missing parameter for: "+std::string(*a));
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
        ss<<*++a;
 | 
			
		||||
        ss>>_ref;
 | 
			
		||||
      }
 | 
			
		||||
      virtual operator std::string() {
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
        ss<<_ref;
 | 
			
		||||
        return ss.str();
 | 
			
		||||
      }
 | 
			
		||||
      virtual std::string type() {
 | 
			
		||||
        return _type.size()?" <"+_type+">":"";
 | 
			
		||||
      }
 | 
			
		||||
    private:
 | 
			
		||||
      T& _ref;
 | 
			
		||||
      std::string _type;
 | 
			
		||||
  };
 | 
			
		||||
  // special case: boolean has no parameter
 | 
			
		||||
  template<> class parameter<bool>: public abstract_parameter {
 | 
			
		||||
    public:
 | 
			
		||||
      parameter(bool& ref, const std::string& = std::string()): _ref(ref=false) {}
 | 
			
		||||
      virtual void evaluate(char**&, char**) {
 | 
			
		||||
        _ref = true;
 | 
			
		||||
      }
 | 
			
		||||
    private:
 | 
			
		||||
      bool& _ref;
 | 
			
		||||
  };
 | 
			
		||||
  // special case: string cannot easily be shifted
 | 
			
		||||
  template<typename T> class parameter<std::basic_string<T> >: public abstract_parameter {
 | 
			
		||||
    public:
 | 
			
		||||
      parameter(std::basic_string<T>& ref, const std::string& s = std::string()):
 | 
			
		||||
          _ref(ref), _type(s) {}
 | 
			
		||||
      virtual void evaluate(char**& a, char** max) {
 | 
			
		||||
        if (max<a+1)
 | 
			
		||||
          throw std::runtime_error("missing parameter for: "+std::string(*a));
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
        ss<<*++a;
 | 
			
		||||
        _ref = std::basic_string<T>(std::istreambuf_iterator<T>(ss),
 | 
			
		||||
                                    std::istreambuf_iterator<T>());
 | 
			
		||||
      }
 | 
			
		||||
      virtual operator std::string() {
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
        ss<<_ref;
 | 
			
		||||
        return ss.str();
 | 
			
		||||
      }
 | 
			
		||||
      virtual std::string type() {
 | 
			
		||||
        return _type.size()?" <"+_type+">":"";
 | 
			
		||||
      }
 | 
			
		||||
    private:
 | 
			
		||||
      std::basic_string<T>& _ref;
 | 
			
		||||
      std::string _type;
 | 
			
		||||
  };
 | 
			
		||||
  // special case: if a function is called
 | 
			
		||||
  template<> class parameter<void(*)()>: public abstract_parameter {
 | 
			
		||||
    public:
 | 
			
		||||
      parameter(void(*ref)(), const std::string& = std::string()): _ref(ref) {}
 | 
			
		||||
      virtual void evaluate(char**&, char**) {
 | 
			
		||||
        _ref();
 | 
			
		||||
      }
 | 
			
		||||
    private:
 | 
			
		||||
      void(*_ref)();
 | 
			
		||||
  };
 | 
			
		||||
  template<typename T>
 | 
			
		||||
      std::shared_ptr<abstract_parameter> param
 | 
			
		||||
      (T& t, const std::string& s = std::string()) {
 | 
			
		||||
    return std::shared_ptr<abstract_parameter>(new args::parameter<T>(t, s));
 | 
			
		||||
  }
 | 
			
		||||
  struct declaration {
 | 
			
		||||
#ifndef ARGS__CPLUSPLUS11
 | 
			
		||||
      declaration(std::string p1, std::string p2, std::string p3,
 | 
			
		||||
                  std::vector<std::shared_ptr<abstract_parameter> > p4):
 | 
			
		||||
          short_arg(p1), long_arg(p2), desc(p3), params(p4) {
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      std::string short_arg;
 | 
			
		||||
      std::string long_arg;
 | 
			
		||||
      std::string desc;
 | 
			
		||||
      std::vector<std::shared_ptr<abstract_parameter> > params;
 | 
			
		||||
  };
 | 
			
		||||
  typedef std::map<std::string,
 | 
			
		||||
                   std::vector<std::shared_ptr<abstract_parameter> > >
 | 
			
		||||
      arg_map;
 | 
			
		||||
  static arg_map& args() {
 | 
			
		||||
    static arg_map a;
 | 
			
		||||
    return a;
 | 
			
		||||
  }
 | 
			
		||||
  typedef std::vector<declaration> list;
 | 
			
		||||
  static list& arg_list() {
 | 
			
		||||
    static list a;
 | 
			
		||||
    return a;
 | 
			
		||||
  }
 | 
			
		||||
  void match(const std::string& arg, char**& a, char** max) {
 | 
			
		||||
#ifndef ARGS__CPLUSPLUS11
 | 
			
		||||
    arg_map::iterator it(args().find(arg));
 | 
			
		||||
#else
 | 
			
		||||
    auto it(args().find(arg));
 | 
			
		||||
#endif
 | 
			
		||||
    if (it==args().end())
 | 
			
		||||
      throw std::runtime_error("unknown argument: "+std::string(*a));
 | 
			
		||||
#ifndef ARGS__CPLUSPLUS11
 | 
			
		||||
    for (std::vector<std::shared_ptr<abstract_parameter> >::iterator
 | 
			
		||||
           it2(it->second.begin()); it2!=it->second.end(); ++it2) {
 | 
			
		||||
#else
 | 
			
		||||
    for (auto it2(it->second.begin()); it2!=it->second.end(); ++it2) {
 | 
			
		||||
#endif
 | 
			
		||||
      (*it2)->evaluate(a, max);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  /// Filename as passed in argv[0].
 | 
			
		||||
  /** Used in the help display.
 | 
			
		||||
      @note This function emulates a global variable using parts of a
 | 
			
		||||
            singleton pattern. */
 | 
			
		||||
  static std::string filename(const std::string& arg0 = std::string()) {
 | 
			
		||||
    static std::string file(arg0);
 | 
			
		||||
    return file;
 | 
			
		||||
  }
 | 
			
		||||
  /// Description of the program.
 | 
			
		||||
  /** Used in the help display.
 | 
			
		||||
      @note This function emulates a global variable using parts of a
 | 
			
		||||
            singleton pattern. */
 | 
			
		||||
  static std::string description(const std::string& desc = std::string()) {
 | 
			
		||||
    static std::string d(desc);
 | 
			
		||||
    return d;
 | 
			
		||||
  }
 | 
			
		||||
  /// Return values of the program.
 | 
			
		||||
  /** Used in the help display.
 | 
			
		||||
      @note This function emulates a global variable using parts of a
 | 
			
		||||
            singleton pattern. */
 | 
			
		||||
  static std::string returns(const std::string& ret = std::string()) {
 | 
			
		||||
    static std::string r(ret);
 | 
			
		||||
    return r;
 | 
			
		||||
  }
 | 
			
		||||
  /// Initialize all parameters according to the commandline options.
 | 
			
		||||
  /** Sets up the parser from the @ref list of parameters
 | 
			
		||||
      @param argc  the argument count as given in C++ @c main function
 | 
			
		||||
      @param argv  the array of arguments as given in C++ @c main function
 | 
			
		||||
      @param descr a string describing what the program does,
 | 
			
		||||
                   used in @ref show_help
 | 
			
		||||
      @param l     list of options and parameters to be parsed
 | 
			
		||||
      @raram ret   documentation of the return values of the program */
 | 
			
		||||
  static void init(int argc, char** argv, const std::string& desc, list l,
 | 
			
		||||
                   const std::string& ret = std::string()) {
 | 
			
		||||
    filename(argv[0]); // store filename for later use in help
 | 
			
		||||
    description(desc); // store program description for later use in help
 | 
			
		||||
    returns(ret);      // store return values description for later use in help
 | 
			
		||||
    arg_list() = l;    // store options and parameters for later use in help
 | 
			
		||||
    // setup the argument mapping table
 | 
			
		||||
#ifndef ARGS__CPLUSPLUS11
 | 
			
		||||
    for (list::iterator it(l.begin()); it!=l.end(); ++it) {
 | 
			
		||||
#else
 | 
			
		||||
    for (auto it(l.begin()); it!=l.end(); ++it) {
 | 
			
		||||
#endif
 | 
			
		||||
      if (it->short_arg.size()==1) args()[it->short_arg] = it->params;
 | 
			
		||||
      if (it->long_arg.size()) args()["--"+it->long_arg] = it->params;
 | 
			
		||||
    }
 | 
			
		||||
    // parse commandline and evaluate the arguments
 | 
			
		||||
#ifndef ARGS__CPLUSPLUS11
 | 
			
		||||
    for (char** a(argv+1); a<argv+argc; ++a) {
 | 
			
		||||
#else
 | 
			
		||||
    for (auto a(argv+1); a<argv+argc; ++a) {
 | 
			
		||||
#endif
 | 
			
		||||
      std::string arg(*a);
 | 
			
		||||
      if (arg.size()>1&&arg[0]=='-'&&arg[1]!='-') { // short argument
 | 
			
		||||
#ifndef ARGS__CPLUSPLUS11
 | 
			
		||||
        for (std::string::iterator it(arg.begin()+1); it!=arg.end(); ++it)
 | 
			
		||||
#else
 | 
			
		||||
        for (auto it(arg.begin()+1); it!=arg.end(); ++it)
 | 
			
		||||
#endif
 | 
			
		||||
          match(std::string(1, *it), a, argv+argc);
 | 
			
		||||
      } else { // long argument or wrong argument
 | 
			
		||||
        match(arg, a, argv+argc);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  //! IO-Manipulator to split long lines into several shorter lines.
 | 
			
		||||
  template <class _CharT = char, class _Traits = std::char_traits<_CharT> >
 | 
			
		||||
    class basic_split /*: public std::basic_ostream<_CharT, _Traits>*/ {
 | 
			
		||||
    public:
 | 
			
		||||
      basic_split(int width=80, int indent=0, char fill=' '):
 | 
			
		||||
          _width(width), _indent(indent), _fill(fill), _os(0) {
 | 
			
		||||
        if (_width<_indent)
 | 
			
		||||
#ifndef ARGS__CPLUSPLUS11
 | 
			
		||||
          throw std::runtime_error(((std::stringstream&)
 | 
			
		||||
                                    (std::stringstream()
 | 
			
		||||
                                     <<"wrong use of split: width is "<<_width
 | 
			
		||||
                                     <<" but should be larger than indent,"
 | 
			
		||||
                                     <<" which is "<<_indent)).str());
 | 
			
		||||
#else
 | 
			
		||||
          throw std::runtime_error("wrong use of split: width is "+
 | 
			
		||||
                                   std::to_string(_width)+
 | 
			
		||||
                                   " but should be larger than indent,"
 | 
			
		||||
                                   " which is "+std::to_string(_indent));
 | 
			
		||||
#endif
 | 
			
		||||
      }
 | 
			
		||||
      virtual ~basic_split() {
 | 
			
		||||
        flush();
 | 
			
		||||
      }
 | 
			
		||||
      friend basic_split& operator<<(std::basic_ostream<_CharT, _Traits>& os,
 | 
			
		||||
                               const basic_split& s) {
 | 
			
		||||
        if (s._os!=&os) {
 | 
			
		||||
          const_cast<basic_split&>(s).flush();
 | 
			
		||||
          const_cast<basic_split&>(s)._os = &os;
 | 
			
		||||
          return 0;
 | 
			
		||||
        } catch (const std::exception& x) { // error in commandline options
 | 
			
		||||
          std::cerr<<"**** ERROR: "<<x.what()<<std::endl;
 | 
			
		||||
          args::show_help(); // display help
 | 
			
		||||
          return 1;
 | 
			
		||||
        }
 | 
			
		||||
        return const_cast<basic_split&>(s);
 | 
			
		||||
      }
 | 
			
		||||
      template <typename T> basic_split& operator<<(T t) {
 | 
			
		||||
        if (!_os)
 | 
			
		||||
          throw std::runtime_error("wrong use of split, it is an io manipulator"
 | 
			
		||||
                                   " and must be used within a stream");
 | 
			
		||||
        _buffer<<t;
 | 
			
		||||
        while (_buffer.str().size()>=_width-_indent) {
 | 
			
		||||
          if (_indent) *_os<<std::setw(_indent)<<std::setfill(_fill)<<_fill;
 | 
			
		||||
          std::string::size_type pos
 | 
			
		||||
            (_buffer.str().find_last_of(' ', _width-_indent));
 | 
			
		||||
          std::string::size_type next(pos+1);
 | 
			
		||||
          if (pos==std::string::npos) {
 | 
			
		||||
            pos=_width-_indent;
 | 
			
		||||
            next=pos;
 | 
			
		||||
          }
 | 
			
		||||
          *_os<<_buffer.str().substr(0, pos)<<std::endl;
 | 
			
		||||
          _buffer.str(_buffer.str().substr(next));
 | 
			
		||||
      @endcode
 | 
			
		||||
      @note This library requires C++11, but there is also a fallback
 | 
			
		||||
            for old compilers. But the calling syntax is much worse on
 | 
			
		||||
            non C++11 compliant compilers, so the use of a modern
 | 
			
		||||
            compiler is strongly recommended. On GNU GCC, you may have
 | 
			
		||||
            to add the commandline option @c -std=c++11
 | 
			
		||||
      @note I suggest to take this library into the next C++ standard. */
 | 
			
		||||
  namespace args {
 | 
			
		||||
    /// Parent for holding a reference to a parameter variable.
 | 
			
		||||
    /** This class ist used only as parent for instances of template
 | 
			
		||||
        parameters.  It represents one parameter that is evaluated when
 | 
			
		||||
        a commandline option is given. The derived classes hold a
 | 
			
		||||
        reference to a variable that is set in method @ref evaluate when
 | 
			
		||||
        the specific commandline parameter is given. */
 | 
			
		||||
    class abstract_parameter {
 | 
			
		||||
      public:
 | 
			
		||||
        /// Called when the user specifies the related commandline option.
 | 
			
		||||
        /** Method must be implemented according to the specific type in
 | 
			
		||||
            the child classes. */
 | 
			
		||||
        virtual void evaluate(char**& a, char** max) = 0;
 | 
			
		||||
        /// Convert the actual value to a string.
 | 
			
		||||
        /** Defaults to empty string, can be overwritten in child
 | 
			
		||||
            classes. Used by the help function to show the default
 | 
			
		||||
            value. */
 | 
			
		||||
        virtual operator std::string() {
 | 
			
		||||
          return std::string();
 | 
			
		||||
        }
 | 
			
		||||
        return *this;
 | 
			
		||||
      }
 | 
			
		||||
    private:
 | 
			
		||||
      void flush() {
 | 
			
		||||
        if (_os) {
 | 
			
		||||
          if (_indent) *_os<<std::setw(_indent)<<std::setfill(_fill)<<_fill;
 | 
			
		||||
          *_os<<_buffer.str();
 | 
			
		||||
          _buffer.clear();
 | 
			
		||||
        virtual std::string type() {
 | 
			
		||||
          return std::string();
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    // default implementation for all types
 | 
			
		||||
    template<typename T> class parameter: public abstract_parameter {
 | 
			
		||||
      public:
 | 
			
		||||
        parameter(T& ref, const std::string& s = std::string()):
 | 
			
		||||
            _ref(ref), _type(s) {}
 | 
			
		||||
        virtual void evaluate(char**& a, char** max) {
 | 
			
		||||
          if (max<a+1)
 | 
			
		||||
            throw std::runtime_error("missing parameter for: "+std::string(*a));
 | 
			
		||||
          std::stringstream ss;
 | 
			
		||||
          ss<<*++a;
 | 
			
		||||
          ss>>_ref;
 | 
			
		||||
        }
 | 
			
		||||
        virtual operator std::string() {
 | 
			
		||||
          std::stringstream ss;
 | 
			
		||||
          ss<<_ref;
 | 
			
		||||
          return ss.str();
 | 
			
		||||
        }
 | 
			
		||||
        virtual std::string type() {
 | 
			
		||||
          return _type.size()?" <"+_type+">":"";
 | 
			
		||||
        }
 | 
			
		||||
      private:
 | 
			
		||||
        T& _ref;
 | 
			
		||||
        std::string _type;
 | 
			
		||||
    };
 | 
			
		||||
    // special case: boolean has no parameter
 | 
			
		||||
    template<> class parameter<bool>: public abstract_parameter {
 | 
			
		||||
      public:
 | 
			
		||||
        parameter(bool& ref, const std::string& = std::string()):
 | 
			
		||||
            _ref(ref=false) {
 | 
			
		||||
        }
 | 
			
		||||
        virtual void evaluate(char**&, char**) {
 | 
			
		||||
          _ref = true;
 | 
			
		||||
        }
 | 
			
		||||
      private:
 | 
			
		||||
        bool& _ref;
 | 
			
		||||
    };
 | 
			
		||||
    // special case: string cannot easily be shifted
 | 
			
		||||
    template<typename T> class parameter<std::basic_string<T> >:
 | 
			
		||||
        public abstract_parameter {
 | 
			
		||||
      public:
 | 
			
		||||
        parameter(std::basic_string<T>& ref,
 | 
			
		||||
                  const std::string& s = std::string()):
 | 
			
		||||
            _ref(ref), _type(s) {}
 | 
			
		||||
        virtual void evaluate(char**& a, char** max) {
 | 
			
		||||
          if (max<a+1)
 | 
			
		||||
            throw std::runtime_error("missing parameter for: "+std::string(*a));
 | 
			
		||||
          std::stringstream ss;
 | 
			
		||||
          ss<<*++a;
 | 
			
		||||
          _ref = std::basic_string<T>(std::istreambuf_iterator<T>(ss),
 | 
			
		||||
                                      std::istreambuf_iterator<T>());
 | 
			
		||||
        }
 | 
			
		||||
        virtual operator std::string() {
 | 
			
		||||
          std::stringstream ss;
 | 
			
		||||
          ss<<_ref;
 | 
			
		||||
          return ss.str();
 | 
			
		||||
        }
 | 
			
		||||
        virtual std::string type() {
 | 
			
		||||
          return _type.size()?" <"+_type+">":"";
 | 
			
		||||
        }
 | 
			
		||||
      private:
 | 
			
		||||
        std::basic_string<T>& _ref;
 | 
			
		||||
        std::string _type;
 | 
			
		||||
    };
 | 
			
		||||
    // special case: if a function is called
 | 
			
		||||
    template<> class parameter<void(*)()>: public abstract_parameter {
 | 
			
		||||
      public:
 | 
			
		||||
        parameter(void(*ref)(), const std::string& = std::string()):
 | 
			
		||||
            _ref(ref) {
 | 
			
		||||
        }
 | 
			
		||||
        virtual void evaluate(char**&, char**) {
 | 
			
		||||
          _ref();
 | 
			
		||||
        }
 | 
			
		||||
      private:
 | 
			
		||||
        void(*_ref)();
 | 
			
		||||
    };
 | 
			
		||||
    template<typename T>
 | 
			
		||||
        std::shared_ptr<abstract_parameter> param
 | 
			
		||||
        (T& t, const std::string& s = std::string()) {
 | 
			
		||||
      return std::shared_ptr<abstract_parameter>(new args::parameter<T>(t, s));
 | 
			
		||||
    }
 | 
			
		||||
    struct declaration {
 | 
			
		||||
#ifdef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
        declaration(std::string p1, std::string p2, std::string p3,
 | 
			
		||||
                    std::vector<std::shared_ptr<abstract_parameter> > p4):
 | 
			
		||||
            short_arg(p1), long_arg(p2), desc(p3), params(p4) {
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    private:
 | 
			
		||||
      int _width;
 | 
			
		||||
      int _indent;
 | 
			
		||||
      char _fill;
 | 
			
		||||
      std::stringstream _buffer;
 | 
			
		||||
      std::basic_ostream<_CharT, _Traits>* _os;
 | 
			
		||||
  };
 | 
			
		||||
  typedef basic_split<char> split;
 | 
			
		||||
  void show_help(const std::string& synopsis_txt="SYNOPSIS",
 | 
			
		||||
                 const std::string& description_txt="DESCRIPTION",
 | 
			
		||||
                 const std::string& options_txt="OPTIONS",
 | 
			
		||||
                 const std::string& returns_txt="RETURNS",
 | 
			
		||||
                 int max_line=80, int indent=2, int long_indent=4,
 | 
			
		||||
                 int option_len=16, int param_len=21) {
 | 
			
		||||
    std::cout<<synopsis_txt<<std::endl<<std::endl
 | 
			
		||||
             <<"  "<<filename()<<" ["<<options_txt<<"]"<<std::endl<<std::endl
 | 
			
		||||
             <<description_txt<<std::endl<<std::endl
 | 
			
		||||
             <<split(max_line, indent)<<description(); //! @bug
 | 
			
		||||
    std::cout<<std::endl<<std::endl
 | 
			
		||||
             <<options_txt<<std::endl;
 | 
			
		||||
#ifndef ARGS__CPLUSPLUS11
 | 
			
		||||
    for (list::iterator arg(arg_list().begin()); arg!=arg_list().end(); ++arg) {
 | 
			
		||||
#else
 | 
			
		||||
    for (auto arg(arg_list().begin()); arg!=arg_list().end(); ++arg) {
 | 
			
		||||
#endif
 | 
			
		||||
      std::string o((arg->short_arg.size()?"-"+arg->short_arg:"")+
 | 
			
		||||
                    (arg->short_arg.size()&&arg->long_arg.size()?", ":"")+
 | 
			
		||||
                    (arg->long_arg.size()?"--"+arg->long_arg:""));
 | 
			
		||||
#ifndef ARGS__CPLUSPLUS11
 | 
			
		||||
      std::string a;
 | 
			
		||||
        std::string short_arg;
 | 
			
		||||
        std::string long_arg;
 | 
			
		||||
        std::string desc;
 | 
			
		||||
        std::vector<std::shared_ptr<abstract_parameter> > params;
 | 
			
		||||
    };
 | 
			
		||||
    typedef std::map<std::string,
 | 
			
		||||
        std::vector<std::shared_ptr<abstract_parameter> > >
 | 
			
		||||
        arg_map;
 | 
			
		||||
    static arg_map& args() {
 | 
			
		||||
      static arg_map a;
 | 
			
		||||
      return a;
 | 
			
		||||
    }
 | 
			
		||||
    typedef std::vector<declaration> list;
 | 
			
		||||
    static list& arg_list() {
 | 
			
		||||
      static list a;
 | 
			
		||||
      return a;
 | 
			
		||||
    }
 | 
			
		||||
    void match(const std::string& arg, char**& a, char** max) {
 | 
			
		||||
#ifdef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
      arg_map::iterator it(args().find(arg));
 | 
			
		||||
#else
 | 
			
		||||
      auto it(args().find(arg));
 | 
			
		||||
#endif
 | 
			
		||||
      if (it==args().end())
 | 
			
		||||
        throw std::runtime_error("unknown argument: "+std::string(*a));
 | 
			
		||||
#ifdef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
      for (std::vector<std::shared_ptr<abstract_parameter> >::iterator
 | 
			
		||||
             p(arg->params.begin());
 | 
			
		||||
           p!=arg->params.end(); ++p) {
 | 
			
		||||
        std::string def(**p);
 | 
			
		||||
        a+=(*p)->type()+(def.size()?"="+def:"");
 | 
			
		||||
      }
 | 
			
		||||
             it2(it->second.begin()); it2!=it->second.end(); ++it2)
 | 
			
		||||
#else
 | 
			
		||||
      std::string a(std::accumulate(arg->params.begin(), arg->params.end(),
 | 
			
		||||
                                    std::string(),
 | 
			
		||||
                                    [](const std::string& s,
 | 
			
		||||
                                       std::shared_ptr<abstract_parameter> p)
 | 
			
		||||
                                    -> std::string {
 | 
			
		||||
                      std::string def(**p);
 | 
			
		||||
                      return s+p->type()+(def.size()?"="+def:"");
 | 
			
		||||
                    }));
 | 
			
		||||
      for (auto it2(it->second.begin()); it2!=it->second.end(); ++it2)
 | 
			
		||||
#endif
 | 
			
		||||
      std::cout<<std::endl<<"  "
 | 
			
		||||
               <<o<<std::setw(option_len-o.size())<<' '
 | 
			
		||||
               <<a;
 | 
			
		||||
      if (arg->desc.size()>max_line-indent-option_len-param_len)
 | 
			
		||||
        std::cout<<std::endl<<std::endl<<split(max_line, long_indent)
 | 
			
		||||
                 <<arg->desc;
 | 
			
		||||
      else
 | 
			
		||||
        std::cout<<std::setw(param_len-a.size())<<' '<<arg->desc;
 | 
			
		||||
      std::cout<<std::endl;
 | 
			
		||||
        (*it2)->evaluate(a, max);
 | 
			
		||||
    }
 | 
			
		||||
    if (returns().size()) {
 | 
			
		||||
      std::cout<<std::endl<<returns_txt<<std::endl<<std::endl
 | 
			
		||||
               <<split(max_line, indent)<<returns();
 | 
			
		||||
      std::cout<<std::endl;
 | 
			
		||||
    /// Filename as passed in argv[0].
 | 
			
		||||
    /** Used in the help display.
 | 
			
		||||
        @note This function emulates a global variable using parts of a
 | 
			
		||||
              singleton pattern. */
 | 
			
		||||
    static std::string filename(const std::string& arg0 = std::string()) {
 | 
			
		||||
      static std::string file(arg0);
 | 
			
		||||
      return file;
 | 
			
		||||
    }
 | 
			
		||||
    /// Description of the program.
 | 
			
		||||
    /** Used in the help display.
 | 
			
		||||
        @note This function emulates a global variable using parts of a
 | 
			
		||||
              singleton pattern. */
 | 
			
		||||
    static std::string description(const std::string& desc = std::string()) {
 | 
			
		||||
      static std::string d(desc);
 | 
			
		||||
      return d;
 | 
			
		||||
    }
 | 
			
		||||
    /// Return values of the program.
 | 
			
		||||
    /** Used in the help display.
 | 
			
		||||
        @note This function emulates a global variable using parts of a
 | 
			
		||||
              singleton pattern. */
 | 
			
		||||
    static std::string returns(const std::string& ret = std::string()) {
 | 
			
		||||
      static std::string r(ret);
 | 
			
		||||
      return r;
 | 
			
		||||
    }
 | 
			
		||||
    /// Initialize all parameters according to the commandline options.
 | 
			
		||||
    /** Sets up the parser from the @ref list of parameters
 | 
			
		||||
        @param argc  the argument count as given in C++ @c main function
 | 
			
		||||
        @param argv  the array of arguments as given in C++ @c main function
 | 
			
		||||
        @param descr a string describing what the program does,
 | 
			
		||||
                     used in @ref show_help
 | 
			
		||||
        @param l     list of options and parameters to be parsed
 | 
			
		||||
        @raram ret   documentation of the return values of the program */
 | 
			
		||||
    static void parse(int argc, char** argv, const std::string& desc, list l,
 | 
			
		||||
                      const std::string& ret = std::string()) {
 | 
			
		||||
      filename(argv[0]); // store filename for later use in help
 | 
			
		||||
      description(desc); // store program description for later use in help
 | 
			
		||||
      returns(ret);      // store return documentation for later use in help
 | 
			
		||||
      arg_list() = l;    // store options and parameters for later use in help
 | 
			
		||||
      // setup the argument mapping table
 | 
			
		||||
#ifdef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
      for (list::iterator it(l.begin()); it!=l.end(); ++it)
 | 
			
		||||
#else
 | 
			
		||||
      for (auto it(l.begin()); it!=l.end(); ++it)
 | 
			
		||||
#endif
 | 
			
		||||
        {
 | 
			
		||||
          if (it->short_arg.size()==1) args()[it->short_arg] = it->params;
 | 
			
		||||
          if (it->long_arg.size()) args()["--"+it->long_arg] = it->params;
 | 
			
		||||
        }
 | 
			
		||||
      // parse commandline and evaluate the arguments
 | 
			
		||||
#ifdef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
      for (char** a(argv+1); a<argv+argc; ++a)
 | 
			
		||||
#else
 | 
			
		||||
      for (auto a(argv+1); a<argv+argc; ++a)
 | 
			
		||||
#endif
 | 
			
		||||
        {
 | 
			
		||||
          std::string arg(*a);
 | 
			
		||||
          if (arg.size()>1&&arg[0]=='-'&&arg[1]!='-') { // short argument
 | 
			
		||||
#ifdef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
            for (std::string::iterator it(arg.begin()+1); it!=arg.end(); ++it)
 | 
			
		||||
#else
 | 
			
		||||
            for (auto it(arg.begin()+1); it!=arg.end(); ++it)
 | 
			
		||||
#endif
 | 
			
		||||
              match(std::string(1, *it), a, argv+argc);
 | 
			
		||||
          } else { // long argument or wrong argument
 | 
			
		||||
            match(arg, a, argv+argc);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    void show_help(const std::string& synopsis_txt="SYNOPSIS",
 | 
			
		||||
                   const std::string& description_txt="DESCRIPTION",
 | 
			
		||||
                   const std::string& options_txt="OPTIONS",
 | 
			
		||||
                   const std::string& returns_txt="RETURNS",
 | 
			
		||||
                   int max_line=80, int indent=2, int long_indent=4,
 | 
			
		||||
                   int option_len=16, int param_len=21) {
 | 
			
		||||
      std::cout<<synopsis_txt<<std::endl<<std::endl
 | 
			
		||||
               <<"  "<<filename()<<" ["<<options_txt<<"]"<<std::endl<<std::endl
 | 
			
		||||
               <<description_txt<<std::endl<<std::endl
 | 
			
		||||
               <<split(max_line, indent)<<description(); //! @bug
 | 
			
		||||
      std::cout<<std::endl<<std::endl
 | 
			
		||||
               <<options_txt<<std::endl;
 | 
			
		||||
#ifdef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
      for (list::iterator arg(arg_list().begin()); arg!=arg_list().end(); ++arg)
 | 
			
		||||
#else
 | 
			
		||||
      for (auto arg(arg_list().begin()); arg!=arg_list().end(); ++arg)
 | 
			
		||||
#endif
 | 
			
		||||
        {
 | 
			
		||||
          std::string o((arg->short_arg.size()?"-"+arg->short_arg:"")+
 | 
			
		||||
                        (arg->short_arg.size()&&arg->long_arg.size()?", ":"")+
 | 
			
		||||
                        (arg->long_arg.size()?"--"+arg->long_arg:""));
 | 
			
		||||
#ifdef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
          std::string a;
 | 
			
		||||
          for (std::vector<std::shared_ptr<abstract_parameter> >::iterator
 | 
			
		||||
                 p(arg->params.begin());
 | 
			
		||||
               p!=arg->params.end(); ++p) {
 | 
			
		||||
            std::string def(**p);
 | 
			
		||||
            a+=(*p)->type()+(def.size()?"="+def:"");
 | 
			
		||||
          }
 | 
			
		||||
#else
 | 
			
		||||
          std::string a(std::accumulate(arg->params.begin(), arg->params.end(),
 | 
			
		||||
                                        std::string(),
 | 
			
		||||
                                        [](const std::string& s,
 | 
			
		||||
                                           std::shared_ptr<abstract_parameter> p)
 | 
			
		||||
                                        -> std::string {
 | 
			
		||||
                                          std::string def(**p);
 | 
			
		||||
                                          return s+p->type()+(def.size()?"="+def:"");
 | 
			
		||||
                                        }));
 | 
			
		||||
#endif
 | 
			
		||||
        std::cout<<std::endl<<"  "
 | 
			
		||||
                 <<o<<std::setw(option_len-o.size())<<' '
 | 
			
		||||
                 <<a;
 | 
			
		||||
        if (arg->desc.size()>max_line-indent-option_len-param_len)
 | 
			
		||||
          std::cout<<std::endl<<std::endl<<split(max_line, long_indent)
 | 
			
		||||
                   <<arg->desc;
 | 
			
		||||
        else
 | 
			
		||||
          std::cout<<std::setw(param_len-a.size())<<' '<<arg->desc;
 | 
			
		||||
        std::cout<<std::endl;
 | 
			
		||||
        }
 | 
			
		||||
      if (returns().size()) {
 | 
			
		||||
        std::cout<<std::endl<<returns_txt<<std::endl<<std::endl
 | 
			
		||||
                 <<split(max_line, indent)<<returns();
 | 
			
		||||
        std::cout<<std::endl;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    void help_no_arg() {
 | 
			
		||||
      show_help();
 | 
			
		||||
    }
 | 
			
		||||
    void do_exit() {
 | 
			
		||||
      exit(1);
 | 
			
		||||
    }
 | 
			
		||||
    std::shared_ptr<args::abstract_parameter> func(void(*fn)()) {
 | 
			
		||||
      return
 | 
			
		||||
        std::shared_ptr<args::abstract_parameter>
 | 
			
		||||
        (new args::parameter<void(*)()>(fn));
 | 
			
		||||
    }
 | 
			
		||||
    std::shared_ptr<args::abstract_parameter> help() {
 | 
			
		||||
      return func(args::help_no_arg);
 | 
			
		||||
    }
 | 
			
		||||
    std::shared_ptr<args::abstract_parameter> exit() {
 | 
			
		||||
      return func(args::do_exit);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  void help_no_arg() {
 | 
			
		||||
    show_help();
 | 
			
		||||
  }
 | 
			
		||||
  void do_exit() {
 | 
			
		||||
    exit(1);
 | 
			
		||||
  }
 | 
			
		||||
  std::shared_ptr<args::abstract_parameter> func(void(*fn)()) {
 | 
			
		||||
    return
 | 
			
		||||
      std::shared_ptr<args::abstract_parameter>
 | 
			
		||||
      (new args::parameter<void(*)()>(fn));
 | 
			
		||||
  }
 | 
			
		||||
  std::shared_ptr<args::abstract_parameter> help() {
 | 
			
		||||
    return func(args::help_no_arg);
 | 
			
		||||
  }
 | 
			
		||||
  std::shared_ptr<args::abstract_parameter> exit() {
 | 
			
		||||
    return func(args::do_exit);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										105
									
								
								src/mrw/iomanip
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/mrw/iomanip
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
/*! @file
 | 
			
		||||
 | 
			
		||||
    @id $Id$
 | 
			
		||||
*/
 | 
			
		||||
//       1         2         3         4         5         6         7         8
 | 
			
		||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
 | 
			
		||||
 | 
			
		||||
#ifndef __MRW__IOMANIP__
 | 
			
		||||
#define __MRW__IOMANIP__
 | 
			
		||||
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
 | 
			
		||||
// check if code is compiled with a new C++11 compiler
 | 
			
		||||
// otherwise there is a fallback wich makes everything much more compliacted
 | 
			
		||||
#ifndef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
#if __cplusplus < 201103L
 | 
			
		||||
/// Code is compiled with an old non C++11 standard compliant compiler
 | 
			
		||||
/** There are workarounds for old non C++11 compatible
 | 
			
		||||
    compilers. These workarounds are deprecated, but will remain until
 | 
			
		||||
    most compilers fully support C++11. So this workaround will be
 | 
			
		||||
    removed in future releases, when support for C++11 is more
 | 
			
		||||
    common. Only rely on this workaround, if you really have to.
 | 
			
		||||
    @see oldcompiler for details on usage */
 | 
			
		||||
#define ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
#warning You need a C++11 compliant compiler, on gcc use option -std=c++11
 | 
			
		||||
#warning emulating C++11 - this changes the way you use the library
 | 
			
		||||
#warning this is deprecated and will be removed in future releases
 | 
			
		||||
#warning refere to the library documentation for more details
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace mrw {
 | 
			
		||||
  //! IO-Manipulator to split long lines into several shorter lines.
 | 
			
		||||
  template <class _CharT = char, class _Traits = std::char_traits<_CharT> >
 | 
			
		||||
      class basic_split /*: public std::basic_ostream<_CharT, _Traits>*/ {
 | 
			
		||||
    public:
 | 
			
		||||
      basic_split(int width=80, int indent=0, char fill=' '):
 | 
			
		||||
          _width(width), _indent(indent), _fill(fill), _os(0) {
 | 
			
		||||
        if (_width<_indent)
 | 
			
		||||
#ifdef ARGS__OLD_PRE11_COMPILER
 | 
			
		||||
          throw std::runtime_error(((std::stringstream&)
 | 
			
		||||
                                    (std::stringstream()
 | 
			
		||||
                                     <<"wrong use of split: width is "<<_width
 | 
			
		||||
                                     <<" but should be larger than indent,"
 | 
			
		||||
                                     <<" which is "<<_indent)).str());
 | 
			
		||||
#else
 | 
			
		||||
        throw std::runtime_error("wrong use of split: width is "+
 | 
			
		||||
                                 std::to_string(_width)+
 | 
			
		||||
                                 " but should be larger than indent,"
 | 
			
		||||
                                 " which is "+std::to_string(_indent));
 | 
			
		||||
#endif
 | 
			
		||||
      }
 | 
			
		||||
      virtual ~basic_split() {
 | 
			
		||||
        flush();
 | 
			
		||||
      }
 | 
			
		||||
      friend basic_split& operator<<(std::basic_ostream<_CharT, _Traits>& os,
 | 
			
		||||
                                     const basic_split& s) {
 | 
			
		||||
        if (s._os!=&os) {
 | 
			
		||||
          const_cast<basic_split&>(s).flush();
 | 
			
		||||
          const_cast<basic_split&>(s)._os = &os;
 | 
			
		||||
        }
 | 
			
		||||
        return const_cast<basic_split&>(s);
 | 
			
		||||
      }
 | 
			
		||||
      template <typename T> basic_split& operator<<(T t) {
 | 
			
		||||
        if (!_os)
 | 
			
		||||
          throw std::runtime_error("wrong use of split, it is an io"
 | 
			
		||||
                                   " manipulator and must be used within"
 | 
			
		||||
                                   " a stream");
 | 
			
		||||
        _buffer<<t;
 | 
			
		||||
        while (_buffer.str().size()>=_width-_indent) {
 | 
			
		||||
          if (_indent) *_os<<std::setw(_indent)<<std::setfill(_fill)<<_fill;
 | 
			
		||||
          std::string::size_type pos
 | 
			
		||||
            (_buffer.str().find_last_of(' ', _width-_indent));
 | 
			
		||||
          std::string::size_type next(pos+1);
 | 
			
		||||
          if (pos==std::string::npos) {
 | 
			
		||||
            pos=_width-_indent;
 | 
			
		||||
            next=pos;
 | 
			
		||||
          }
 | 
			
		||||
          *_os<<_buffer.str().substr(0, pos)<<std::endl;
 | 
			
		||||
          _buffer.str(_buffer.str().substr(next));
 | 
			
		||||
        }
 | 
			
		||||
        return *this;
 | 
			
		||||
      }
 | 
			
		||||
    private:
 | 
			
		||||
      void flush() {
 | 
			
		||||
        if (_os) {
 | 
			
		||||
          if (_indent) *_os<<std::setw(_indent)<<std::setfill(_fill)<<_fill;
 | 
			
		||||
          *_os<<_buffer.str();
 | 
			
		||||
          _buffer.clear();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    private:
 | 
			
		||||
      int _width;
 | 
			
		||||
      int _indent;
 | 
			
		||||
      char _fill;
 | 
			
		||||
      std::stringstream _buffer;
 | 
			
		||||
      std::basic_ostream<_CharT, _Traits>* _os;
 | 
			
		||||
  };
 | 
			
		||||
  typedef basic_split<char> split;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
		Reference in New Issue
	
	Block a user