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 // //////////////////////////////////////////////////
00030 // Teuchos_CommandLineProcessor.hpp
00031 
00032 #ifndef TEUCHOS_COMMAND_LINE_PROCESSOR_HPP
00033 #define TEUCHOS_COMMAND_LINE_PROCESSOR_HPP
00034 
00038 #include "Teuchos_map.hpp"
00039 #include "Teuchos_any.hpp"
00040 #include "Teuchos_CompileTimeAssert.hpp"
00041 
00042 namespace Teuchos {
00043 
00045 
00058 /* ToDo: RAB: 2003/10/02: Add support for required options as per KRL's suggestion
00059  *
00060  * ToDo:  Finish documentation.
00061  */
00062 
00063 class CommandLineProcessor {
00064 public:
00065 
00069   enum EParseCommandLineReturn {
00070     PARSE_SUCCESSFUL              =  0 
00071     ,PARSE_HELP_PRINTED            =  1 
00072     ,PARSE_UNRECOGNIZED_OPTION     = -1 
00073   };
00074 
00076 
00077 
00086   CommandLineProcessor(
00087     bool    throwExceptions      = true
00088     ,bool   recogniseAllOptions  = true
00089     );
00090 
00092 
00094 
00096 
00108   void setOption(
00109     const char     option_true[]
00110     ,const char    option_false[]
00111     ,bool          *option_val
00112     ,const char    documentation[] = NULL
00113     );
00114 
00116 
00126   void setOption(
00127     const char     option_name[]
00128     ,int           *option_val
00129     ,const char    documentation[] = NULL
00130     );
00131 
00133 
00143   void setOption(
00144     const char     option_name[]
00145     ,double        *option_val
00146     ,const char    documentation[] = NULL
00147     );
00148 
00150 
00160   void setOption(
00161     const char     option_name[]
00162     ,std::string   *option_val
00163     ,const char    documentation[] = NULL
00164     );
00165   
00167 
00195   template <class EType>
00196   void setOption(
00197     const char    enum_option_name[]
00198     ,EType       *enum_option_val
00199     ,const int    num_enum_opt_values
00200     ,const EType  enum_opt_values[]
00201     ,const char*  enum_opt_names[]
00202     ,const char   documentation[] = NULL
00203     );
00204   
00206 
00208 
00210 
00263   EParseCommandLineReturn  parse(
00264     int             argc
00265     ,char*          argv[]
00266     ,std::ostream   *errout    = &std::cerr
00267     ) const;
00268 
00270 
00272 
00274 
00282   void printHelpMessage( const char program_name[], std::ostream &out ) const;
00283 
00285 
00287 
00289   void throwExceptions ( const bool & throwExceptions ) { throwExceptions_ = throwExceptions; };
00290   
00292   const bool& throwExceptions() const { return throwExceptions_; };
00293 
00295   void recogniseAllOptions ( const bool & recogniseAllOptions ) { recogniseAllOptions_ = recogniseAllOptions; };
00296 
00298   const bool& recogniseAllOptions() const { return recogniseAllOptions_; };
00299 
00301 
00303 
00305   class ParseError : public std::logic_error
00306   {public: ParseError(const std::string& what_arg) : std::logic_error(what_arg) {}};
00307 
00309   class HelpPrinted : public ParseError
00310   {public: HelpPrinted(const std::string& what_arg) : ParseError(what_arg) {}};
00311 
00313   class UnrecognizedOption : public ParseError
00314   {public: UnrecognizedOption(const std::string& what_arg) : ParseError(what_arg) {}};
00315 
00317 
00318 public:
00319   //
00320   enum EOptType { OPT_NONE, OPT_BOOL_TRUE, OPT_BOOL_FALSE, OPT_INT, OPT_DOUBLE, OPT_STRING, OPT_ENUM_INT };
00321   // RAB: 2003/10/10: Note: I had to move this out of the private section since
00322   // the sun compiler (version 7) complained (rightly it now appears after looking
00323   // up what the ISO/ANSI C++ standard says) about the declaration for opt_val_val_t
00324   // not being able to access a private member of CommandLineProcessor.
00325 
00326 private:
00327 
00328   // /////////////////////////////////
00329   // Private types
00330 
00331   // ToDo: RAB: 2004/05/25: Clean up these data structures and add
00332   // support for a templated enum type.  This will clean up usage
00333   // quite a bit.
00334 
00335   //
00336   struct opt_val_val_t {
00337     opt_val_val_t()
00338       :opt_type(OPT_NONE)
00339       {}
00340     opt_val_val_t( EOptType opt_type_in, const any& opt_val_in )
00341       :opt_type(opt_type_in),opt_val(opt_val_in)
00342       {}
00343     EOptType     opt_type;
00344     any          opt_val; // Will be bool*, int*, double*, string* or a small int (for OPT_ENUM_INT)
00345   };
00346 
00347   //
00348   typedef Teuchos::map<std::string,opt_val_val_t>   options_list_t;
00349 
00350   //
00351   struct opt_doc_t {
00352     opt_doc_t()
00353       :opt_type(OPT_NONE)
00354       {}
00355     opt_doc_t(EOptType opt_type_in, const std::string& opt_name_in, const std::string& opt_name_false_in
00356             ,const std::string &documentation_in, const any &default_val_in )
00357       :opt_type(opt_type_in),opt_name(opt_name_in),opt_name_false(opt_name_false_in)
00358       ,documentation(documentation_in),default_val(default_val_in)
00359       {}
00360     EOptType     opt_type;
00361     std::string  opt_name;
00362     std::string  opt_name_false; // only for bool
00363     std::string  documentation;
00364     any          default_val;
00365   };
00366   
00367   //
00368   typedef std::vector<opt_doc_t>   options_documentation_list_t;
00369 
00370   //
00371   struct enum_opt_data_t {
00372     enum_opt_data_t()
00373       :enum_option_val(NULL), num_enum_opt_values(0)
00374       {}
00375     enum_opt_data_t(
00376       int          *_enum_option_val
00377       ,const int    _num_enum_opt_values
00378       ,const int    _enum_opt_values[]
00379       ,const char*  _enum_opt_names[]
00380       )
00381       :enum_option_val(_enum_option_val)
00382       ,num_enum_opt_values(_num_enum_opt_values)
00383       ,enum_opt_values(_enum_opt_values,_enum_opt_values+_num_enum_opt_values)
00384       {
00385         for( int k = 0; k < num_enum_opt_values; ++k )
00386           enum_opt_names.push_back(std::string(_enum_opt_names[k]));
00387       }
00388     int                  *enum_option_val;
00389     int                  num_enum_opt_values;
00390     std::vector<int>     enum_opt_values;
00391     std::vector<string>  enum_opt_names;
00392   };
00393 
00394   //
00395   typedef std::vector<enum_opt_data_t> enum_opt_data_list_t;
00396 
00397   // /////////////////////////////////
00398   // Private data members
00399 
00400   bool                             throwExceptions_;
00401   bool                             recogniseAllOptions_;
00402   options_list_t                   options_list_;
00403   options_documentation_list_t     options_documentation_list_;
00404   enum_opt_data_list_t             enum_opt_data_list_;
00405 
00406   // /////////////////////////////////
00407   // Private member functions
00408 
00409   // Set an integer enumeration option
00410   void setEnumOption(
00411     const char    enum_option_name[]
00412     ,int          *enum_option_val
00413     ,const int    num_enum_opt_values
00414     ,const int    enum_opt_values[]
00415     ,const char*  enum_opt_names[]
00416     ,const char   documentation[]
00417     );
00418 
00419   // Set an enum int option
00420   bool set_enum_value(
00421     int                  argv_i
00422     ,char*               argv[]
00423     ,const std::string   &enum_opt_name
00424     ,const int           enum_id
00425     ,const std::string   &enum_str_val
00426     ,std::ostream        *errout
00427     ) const;
00428 
00429   // Print the valid enum values
00430   void print_enum_opt_names(
00431     const int            enum_id
00432     ,std::ostream        &out
00433     ) const;
00434 
00435   // Return the name of the default value for an enum
00436   std::string enum_opt_default_val_name(
00437     const std::string    &enum_name
00438     ,const int           enum_id
00439     ,std::ostream        *errout
00440     ) const;
00441   
00442   // Return the index given and option value
00443   int find_enum_opt_index(
00444     const std::string           &enum_opt_name
00445     ,const int                  opt_value
00446     ,const enum_opt_data_t      &enum_data
00447     ,std::ostream               *errout
00448     ) const; 
00449 
00450   // Get the option and the value from an entry in argv[].
00451   // Will return false if entry is not formated properly.
00452   bool get_opt_val(
00453     const char     str[]
00454     ,std::string   *opt_name
00455     ,std::string   *opt_val_str // May be empty on return
00456     ) const;
00457 
00458   // String for option type
00459   std::string opt_type_str( EOptType ) const;
00460 
00461   // Print bad option
00462   void print_bad_opt(
00463     int             argv_i
00464     ,char*          argv[]
00465     ,std::ostream   *errout
00466     ) const;
00467 
00468 }; // end class CommandLineProcessor
00469 
00470 // /////////////////////////
00471 // Inline members
00472 
00473 template <class EType>
00474 inline
00475 void CommandLineProcessor::setOption(
00476   const char    enum_option_name[]
00477   ,EType       *enum_option_val
00478   ,const int    num_enum_opt_values
00479   ,const EType  enum_opt_values[]
00480   ,const char*  enum_opt_names[]
00481   ,const char   documentation[]
00482   )
00483 {
00484   // RAB: 2004/05/25: Every C++ implementation that I know of just
00485   // represents enumerations as int's and therefore this will compile
00486   // just fine.  However, the ISO/ANSI C++ standard says that
00487   // compilers are allowed to use a smaller storage type for an enum
00488   // but must not require storage any larger than an 'int'.  If the
00489   // below compile-time assertion does not compile then we need to do
00490   // something different but it will be a lot of work!
00491   CompileTimeAssert<sizeof(int)-sizeof(EType)>();
00492   //CompileTimeAssert<sizeof(int)-sizeof(EType)-1>(); // Uncomment to see compilation error
00493   setEnumOption(
00494     enum_option_name
00495     ,reinterpret_cast<int*>(enum_option_val)
00496     ,num_enum_opt_values
00497     ,reinterpret_cast<const int*>(enum_opt_values)
00498     ,enum_opt_names
00499     ,documentation
00500     );
00501 }
00502 
00503 inline
00504 std::string CommandLineProcessor::opt_type_str( EOptType opt_type ) const
00505 {
00506   std::string str;
00507   switch( opt_type ) {
00508     case OPT_BOOL_TRUE:
00509       str = "bool";
00510       break;
00511     case OPT_INT:
00512       str = "int";
00513       break;
00514     case OPT_DOUBLE:
00515       str = "double";
00516       break;
00517     case OPT_STRING:
00518       str = "string";
00519       break;
00520     case OPT_ENUM_INT:
00521       str = "enum";
00522       break;
00523     default:
00524       assert(0); // Local programming error only
00525   } 
00526   return str;
00527 }
00528 
00529 } // end namespace Teuchos
00530 
00531 #endif // TEUCHOS_COMMAND_LINE_PROCESSOR_HPP

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