ArgParser can throw exception instead of exit(1) (#332)
authorAlpar Juttner <alpar@cs.elte.hu>
Sun, 14 Feb 2010 19:23:55 +0100
changeset 842c2ff0a365245
parent 831 cc9e0c15d747
child 843 81f7e910060b
ArgParser can throw exception instead of exit(1) (#332)
demo/arg_parser_demo.cc
lemon/arg_parser.cc
lemon/arg_parser.h
     1.1 --- a/demo/arg_parser_demo.cc	Fri Feb 12 22:24:26 2010 +0100
     1.2 +++ b/demo/arg_parser_demo.cc	Sun Feb 14 19:23:55 2010 +0100
     1.3 @@ -65,9 +65,18 @@
     1.4    ap.other("infile", "The input file.")
     1.5      .other("...");
     1.6  
     1.7 +  // Throw an exception when problems occurs. The default behavior is to
     1.8 +  // exit(1) on these cases, but this makes Valgrind falsely warn
     1.9 +  // about memory leaks.
    1.10 +  ap.throwOnProblems();
    1.11 +  
    1.12    // Perform the parsing process
    1.13    // (in case of any error it terminates the program)
    1.14 -  ap.parse();
    1.15 +  // The try {} construct is necessary only if the ap.trowOnProblems()
    1.16 +  // setting is in use.
    1.17 +  try {
    1.18 +    ap.parse();
    1.19 +  } catch (ArgParserException &) { return 1; }
    1.20  
    1.21    // Check each option if it has been given and print its value
    1.22    std::cout << "Parameters of '" << ap.commandName() << "':\n";
     2.1 --- a/lemon/arg_parser.cc	Fri Feb 12 22:24:26 2010 +0100
     2.2 +++ b/lemon/arg_parser.cc	Sun Feb 14 19:23:55 2010 +0100
     2.3 @@ -20,14 +20,23 @@
     2.4  
     2.5  namespace lemon {
     2.6  
     2.7 +  void ArgParser::_terminate(ArgParserException::Reason reason) const
     2.8 +  {
     2.9 +    if(_exit_on_problems)
    2.10 +      exit(1);
    2.11 +    else throw(ArgParserException(reason));
    2.12 +  }
    2.13 +  
    2.14 +  
    2.15    void ArgParser::_showHelp(void *p)
    2.16    {
    2.17      (static_cast<ArgParser*>(p))->showHelp();
    2.18 -    exit(1);
    2.19 +    (static_cast<ArgParser*>(p))->_terminate(ArgParserException::HELP);
    2.20    }
    2.21  
    2.22    ArgParser::ArgParser(int argc, const char * const *argv)
    2.23 -    :_argc(argc), _argv(argv), _command_name(argv[0]) {
    2.24 +    :_argc(argc), _argv(argv), _command_name(argv[0]),
    2.25 +    _exit_on_problems(true) {
    2.26      funcOption("-help","Print a short help message",_showHelp,this);
    2.27      synonym("help","-help");
    2.28      synonym("h","-help");
    2.29 @@ -342,7 +351,7 @@
    2.30      for(std::vector<OtherArg>::const_iterator i=_others_help.begin();
    2.31          i!=_others_help.end();++i) showHelp(i);
    2.32      for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i) showHelp(i);
    2.33 -    exit(1);
    2.34 +    _terminate(ArgParserException::HELP);
    2.35    }
    2.36  
    2.37  
    2.38 @@ -351,7 +360,7 @@
    2.39      std::cerr << "\nUnknown option: " << arg << "\n";
    2.40      std::cerr << "\nType '" << _command_name <<
    2.41        " --help' to obtain a short summary on the usage.\n\n";
    2.42 -    exit(1);
    2.43 +    _terminate(ArgParserException::UNKNOWN_OPT);
    2.44    }
    2.45  
    2.46    void ArgParser::requiresValue(std::string arg, OptType t) const
    2.47 @@ -414,7 +423,7 @@
    2.48      if(!ok) {
    2.49        std::cerr << "\nType '" << _command_name <<
    2.50          " --help' to obtain a short summary on the usage.\n\n";
    2.51 -      exit(1);
    2.52 +      _terminate(ArgParserException::INVALID_OPT);
    2.53      }
    2.54    }
    2.55  
     3.1 --- a/lemon/arg_parser.h	Fri Feb 12 22:24:26 2010 +0100
     3.2 +++ b/lemon/arg_parser.h	Sun Feb 14 19:23:55 2010 +0100
     3.3 @@ -34,6 +34,44 @@
     3.4  
     3.5  namespace lemon {
     3.6  
     3.7 +  ///Exception used by ArgParser
     3.8 +  class ArgParserException : public Exception {
     3.9 +  public:
    3.10 +    enum Reason {
    3.11 +      HELP,         /// <tt>--help</tt> option was given
    3.12 +      UNKNOWN_OPT,  /// Unknown option was given
    3.13 +      INVALID_OPT   /// Invalid combination of options
    3.14 +    };
    3.15 +    
    3.16 +  private:
    3.17 +    Reason _reason;
    3.18 +    
    3.19 +  public:
    3.20 +    ///Constructor
    3.21 +    ArgParserException(Reason r) throw() : _reason(r) {}
    3.22 +    ///Virtual destructor
    3.23 +    virtual ~ArgParserException() throw() {}
    3.24 +    ///A short description of the exception
    3.25 +    virtual const char* what() const throw() {
    3.26 +      switch(_reason)
    3.27 +        {
    3.28 +        case HELP:
    3.29 +          return "lemon::ArgParseException: ask for help";
    3.30 +          break;
    3.31 +        case UNKNOWN_OPT:
    3.32 +          return "lemon::ArgParseException: unknown option";
    3.33 +          break;
    3.34 +        case INVALID_OPT:
    3.35 +          return "lemon::ArgParseException: invalid combination of options";
    3.36 +          break;
    3.37 +        }
    3.38 +      return "";
    3.39 +    }
    3.40 +    ///Return the reason for the failure
    3.41 +    Reason reason() const {return _reason; }
    3.42 +  };
    3.43 +
    3.44 +
    3.45    ///Command line arguments parser
    3.46  
    3.47    ///\ingroup misc
    3.48 @@ -103,7 +141,7 @@
    3.49      std::vector<std::string> _file_args;
    3.50      std::string _command_name;
    3.51  
    3.52 -
    3.53 +    
    3.54    private:
    3.55      //Bind a function to an option.
    3.56  
    3.57 @@ -116,6 +154,10 @@
    3.58                      const std::string &help,
    3.59                      void (*func)(void *),void *data);
    3.60  
    3.61 +    bool _exit_on_problems;
    3.62 +    
    3.63 +    void _terminate(ArgParserException::Reason reason) const;
    3.64 +
    3.65    public:
    3.66  
    3.67      ///Constructor
    3.68 @@ -380,6 +422,11 @@
    3.69      ///not starting with a '-' character.
    3.70      const std::vector<std::string> &files() const { return _file_args; }
    3.71  
    3.72 +    ///Throw instead of exit in case of problems
    3.73 +    void throwOnProblems() 
    3.74 +    {
    3.75 +      _exit_on_problems=false;
    3.76 +    }
    3.77    };
    3.78  }
    3.79