Teuchos_CommandLineProcessor.hpp

Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef TEUCHOS_COMMAND_LINE_PROCESSOR_HPP
00030 #define TEUCHOS_COMMAND_LINE_PROCESSOR_HPP
00031 
00035 #include "Teuchos_map.hpp"
00036 #include "Teuchos_any.hpp"
00037 #include "Teuchos_CompileTimeAssert.hpp"
00038 
00039 namespace Teuchos {
00040 
00054 /* ToDo: RAB: 2003/10/02: Add support for required options as per KRL's suggestion
00055  *
00056  * ToDo:  Finish documentation.
00057  */
00058 
00059 class CommandLineProcessor {
00060 public:
00061 
00065   enum EParseCommandLineReturn {
00066     PARSE_SUCCESSFUL              =  0 
00067     ,PARSE_HELP_PRINTED            =  1 
00068     ,PARSE_UNRECOGNIZED_OPTION     = -1 
00069   };
00070 
00072 
00073 
00082   CommandLineProcessor(
00083     bool    throwExceptions      = true
00084     ,bool   recogniseAllOptions  = true
00085     );
00086 
00088 
00090 
00103   void setOption(
00104     const char     option_true[]
00105     ,const char    option_false[]
00106     ,bool          *option_val
00107     ,const char    documentation[] = NULL
00108     );
00109 
00120   void setOption(
00121     const char     option_name[]
00122     ,int           *option_val
00123     ,const char    documentation[] = NULL
00124     );
00125 
00136   void setOption(
00137     const char     option_name[]
00138     ,double        *option_val
00139     ,const char    documentation[] = NULL
00140     );
00141 
00152   void setOption(
00153     const char     option_name[]
00154     ,std::string   *option_val
00155     ,const char    documentation[] = NULL
00156     );
00157   
00186   template <class EType>
00187   void setOption(
00188     const char    enum_option_name[]
00189     ,EType       *enum_option_val
00190     ,const int    num_enum_opt_values
00191     ,const EType  enum_opt_values[]
00192     ,const char*  enum_opt_names[]
00193     ,const char   documentation[] = NULL
00194     );
00195   
00197 
00199 
00253   EParseCommandLineReturn  parse(
00254     int             argc
00255     ,char*          argv[]
00256     ,std::ostream   *errout    = &std::cerr
00257     ) const;
00258 
00260 
00262 
00271   void printHelpMessage( const char program_name[], std::ostream &out ) const;
00272 
00274 
00276 
00278   void throwExceptions ( const bool & throwExceptions ) { throwExceptions_ = throwExceptions; };
00279   
00281   const bool& throwExceptions() const { return throwExceptions_; };
00282 
00284   void recogniseAllOptions ( const bool & recogniseAllOptions ) { recogniseAllOptions_ = recogniseAllOptions; };
00285 
00287   const bool& recogniseAllOptions() const { return recogniseAllOptions_; };
00288 
00290 
00292 
00294   class ParseError : public std::logic_error
00295   {public: ParseError(const std::string& what_arg) : std::logic_error(what_arg) {}};
00296 
00298   class HelpPrinted : public ParseError
00299   {public: HelpPrinted(const std::string& what_arg) : ParseError(what_arg) {}};
00300 
00302   class UnrecognizedOption : public ParseError
00303   {public: UnrecognizedOption(const std::string& what_arg) : ParseError(what_arg) {}};
00304 
00306 
00307 public:
00308   //
00309   enum EOptType { OPT_NONE, OPT_BOOL_TRUE, OPT_BOOL_FALSE, OPT_INT, OPT_DOUBLE, OPT_STRING, OPT_ENUM_INT };
00310   // RAB: 2003/10/10: Note: I had to move this out of the private section since
00311   // the sun compiler (version 7) complained (rightly it now appears after looking
00312   // up what the ISO/ANSI C++ standard says) about the declaration for opt_val_val_t
00313   // not being able to access a private member of CommandLineProcessor.
00314 
00315 private:
00316 
00317   // /////////////////////////////////
00318   // Private types
00319 
00320   // ToDo: RAB: 2004/05/25: Clean up these data structures and add
00321   // support for a templated enum type.  This will clean up usage
00322   // quite a bit.
00323 
00324   //
00325   struct opt_val_val_t {
00326     opt_val_val_t()
00327       :opt_type(OPT_NONE)
00328       {}
00329     opt_val_val_t( EOptType opt_type_in, const any& opt_val_in )
00330       :opt_type(opt_type_in),opt_val(opt_val_in)
00331       {}
00332     EOptType     opt_type;
00333     any          opt_val; // Will be bool*, int*, double*, string* or a small int (for OPT_ENUM_INT)
00334   };
00335 
00336   //
00337   typedef Teuchos::map<std::string,opt_val_val_t>   options_list_t;
00338 
00339   //
00340   struct opt_doc_t {
00341     opt_doc_t()
00342       :opt_type(OPT_NONE)
00343       {}
00344     opt_doc_t(EOptType opt_type_in, const std::string& opt_name_in, const std::string& opt_name_false_in
00345             ,const std::string &documentation_in, const any &default_val_in )
00346       :opt_type(opt_type_in),opt_name(opt_name_in),opt_name_false(opt_name_false_in)
00347       ,documentation(documentation_in),default_val(default_val_in)
00348       {}
00349     EOptType     opt_type;
00350     std::string  opt_name;
00351     std::string  opt_name_false; // only for bool
00352     std::string  documentation;
00353     any          default_val;
00354   };
00355   
00356   //
00357   typedef std::vector<opt_doc_t>   options_documentation_list_t;
00358 
00359   //
00360   struct enum_opt_data_t {
00361     enum_opt_data_t()
00362       :enum_option_val(NULL), num_enum_opt_values(0)
00363       {}
00364     enum_opt_data_t(
00365       int          *_enum_option_val
00366       ,const int    _num_enum_opt_values
00367       ,const int    _enum_opt_values[]
00368       ,const char*  _enum_opt_names[]
00369       )
00370       :enum_option_val(_enum_option_val)
00371       ,num_enum_opt_values(_num_enum_opt_values)
00372       ,enum_opt_values(_enum_opt_values,_enum_opt_values+_num_enum_opt_values)
00373       {
00374         for( int k = 0; k < num_enum_opt_values; ++k )
00375           enum_opt_names.push_back(std::string(_enum_opt_names[k]));
00376       }
00377     int                  *enum_option_val;
00378     int                  num_enum_opt_values;
00379     std::vector<int>     enum_opt_values;
00380     std::vector<string>  enum_opt_names;
00381   };
00382 
00383   //
00384   typedef std::vector<enum_opt_data_t> enum_opt_data_list_t;
00385 
00386   // /////////////////////////////////
00387   // Private data members
00388 
00389   bool                             throwExceptions_;
00390   bool                             recogniseAllOptions_;
00391   options_list_t                   options_list_;
00392   options_documentation_list_t     options_documentation_list_;
00393   enum_opt_data_list_t             enum_opt_data_list_;
00394 
00395   // /////////////////////////////////
00396   // Private member functions
00397 
00398   // Set an integer enumeration option
00399   void setEnumOption(
00400     const char    enum_option_name[]
00401     ,int          *enum_option_val
00402     ,const int    num_enum_opt_values
00403     ,const int    enum_opt_values[]
00404     ,const char*  enum_opt_names[]
00405     ,const char   documentation[]
00406     );
00407 
00408   // Set an enum int option
00409   bool set_enum_value(
00410     int                  argv_i
00411     ,char*               argv[]
00412     ,const std::string   &enum_opt_name
00413     ,const int           enum_id
00414     ,const std::string   &enum_str_val
00415     ,std::ostream        *errout
00416     ) const;
00417 
00418   // Print the valid enum values
00419   void print_enum_opt_names(
00420     const int            enum_id
00421     ,std::ostream        &out
00422     ) const;
00423 
00424   // Return the name of the default value for an enum
00425   std::string enum_opt_default_val_name(
00426     const std::string    &enum_name
00427     ,const int           enum_id
00428     ,std::ostream        *errout
00429     ) const;
00430   
00431   // Return the index given and option value
00432   int find_enum_opt_index(
00433     const std::string           &enum_opt_name
00434     ,const int                  opt_value
00435     ,const enum_opt_data_t      &enum_data
00436     ,std::ostream               *errout
00437     ) const; 
00438 
00439   // Get the option and the value from an entry in argv[].
00440   // Will return false if entry is not formated properly.
00441   bool get_opt_val(
00442     const char     str[]
00443     ,std::string   *opt_name
00444     ,std::string   *opt_val_str // May be empty on return
00445     ) const;
00446 
00447   // String for option type
00448   std::string opt_type_str( EOptType ) const;
00449 
00450   // Print bad option
00451   void print_bad_opt(
00452     int             argv_i
00453     ,char*          argv[]
00454     ,std::ostream   *errout
00455     ) const;
00456 
00457 }; // end class CommandLineProcessor
00458 
00459 // /////////////////////////
00460 // Inline members
00461 
00462 template <class EType>
00463 inline
00464 void CommandLineProcessor::setOption(
00465   const char    enum_option_name[]
00466   ,EType       *enum_option_val
00467   ,const int    num_enum_opt_values
00468   ,const EType  enum_opt_values[]
00469   ,const char*  enum_opt_names[]
00470   ,const char   documentation[]
00471   )
00472 {
00473   // RAB: 2004/05/25: Every C++ implementation that I know of just
00474   // represents enumerations as int's and therefore this will compile
00475   // just fine.  However, the ISO/ANSI C++ standard says that
00476   // compilers are allowed to use a smaller storage type for an enum
00477   // but must not require storage any larger than an 'int'.  If the
00478   // below compile-time assertion does not compile then we need to do
00479   // something different but it will be a lot of work!
00480   CompileTimeAssert<sizeof(int)-sizeof(EType)>();
00481   //CompileTimeAssert<sizeof(int)-sizeof(EType)-1>(); // Uncomment to see compilation error
00482   setEnumOption(
00483     enum_option_name
00484     ,reinterpret_cast<int*>(enum_option_val)
00485     ,num_enum_opt_values
00486     ,reinterpret_cast<const int*>(enum_opt_values)
00487     ,enum_opt_names
00488     ,documentation
00489     );
00490 }
00491 
00492 inline
00493 std::string CommandLineProcessor::opt_type_str( EOptType opt_type ) const
00494 {
00495   std::string str;
00496   switch( opt_type ) {
00497     case OPT_BOOL_TRUE:
00498       str = "bool";
00499       break;
00500     case OPT_INT:
00501       str = "int";
00502       break;
00503     case OPT_DOUBLE:
00504       str = "double";
00505       break;
00506     case OPT_STRING:
00507       str = "string";
00508       break;
00509     case OPT_ENUM_INT:
00510       str = "enum";
00511       break;
00512     default:
00513       assert(0); // Local programming error only
00514   } 
00515   return str;
00516 }
00517 
00518 } // end namespace Teuchos
00519 
00520 #endif // TEUCHOS_COMMAND_LINE_PROCESSOR_HPP

Generated on Thu Sep 18 12:39:09 2008 for Teuchos - Trilinos Tools Package by doxygen 1.3.9.1