MOAB: Mesh Oriented datABase  (version 5.4.1)
ProgOptions.hpp
Go to the documentation of this file.
00001 #ifndef MOAB_PROGRAM_OPTIONS_H
00002 #define MOAB_PROGRAM_OPTIONS_H
00003 
00004 #include <vector>
00005 #include <map>
00006 #include <string>
00007 #include <iostream>
00008 
00009 class ProgOpt;
00010 
00011 /** A simple command-line option parser and help utility
00012  *
00013  * Utility class to specify a program's command-line options arguments, produce a help message
00014  * explaining how they work, and parse user's command line input (producing useful errors messages
00015  * if any problems arise).  Loosely (okay, very loosely) inspired by boost program_options.
00016  *
00017  * Options are specified by a comma-separated namestring.  An option named "foo,f" can be specified
00018  * three ways on the command line: "-f val", "--foo val", or "--foo=val".  The types of options
00019  * and arguments are specified by function templates.  Valid template values for positional argument
00020  * and options are int, double, and std::string.  void may also be used in options, and it indicates
00021  * a command line option that does not take an argument.
00022  *
00023  * Example usage:
00024  * ProgOptions po( "Example usage of ProgOptions" );
00025  * po.addOpt<void>( "verbose,v", "Turn on verbose messages" );
00026  * po.addOpt<std::string> ("foo", "Specify the foo string" );
00027  * int x = 0;
00028  * po.addOpt<int>( ",x", "Specify the x number", &x ); // x will be automatically set when options
00029  * parsed po.parseCommandLine( argc, argv ); bool verbose = po.numOptSet("verbose") > 0; std::string
00030  * foo; if( !po.getOpt( "foo", &foo ) ) foo = "default";
00031  * ...
00032  *
00033  * See the file dagmc_preproc.cpp in the dagmc directory for a real-world example.
00034  */
00035 class ProgOptions
00036 {
00037 
00038   public:
00039     /**
00040      * Flags for addOpt and addRequiredArg functions; may be combined with bitwise arithmetic
00041      * (though not all combinations make sense!)
00042      **/
00043 
00044     /// Set for a flag that, when detected, prints help text and halts program.
00045     /// Constructor creates such a flag by default, so the user shouldn't need to use this directly.
00046     static const int help_flag = 1 << 0;
00047 
00048     /// Flag indicating that an option should be given a "cancel" flag.
00049     /// This creates, for option --foo, an additional option --no-foo that
00050     /// clears all previously read instances of the foo option
00051     static const int add_cancel_opt = 1 << 1;
00052 
00053     /// When applied to a flag argument (one with template type void), indicate that the
00054     /// value 'false' should be stored into the pointer that was given at option creation time.
00055     /// This overrides the default behavior, which is to store the value 'true'.
00056     static const int store_false = 1 << 2;
00057 
00058     /// Specify a numerical flag where any positive integer is an acceptable
00059     /// value.  E.g. --dimension=3 is equivalent to -3.  Only values in the
00060     /// range [0,9] are accepted and the flag type must be integer.
00061     static const int int_flag = 1 << 3;
00062 
00063     /** Substitue any occurance of the '%' symbol in a string with
00064      *  the the MPI rank of this process in MPI_COMM_WORLD.  This
00065      *  option has no effect if not compiled with MPI.  This flag
00066      *  has no effect for non-string options.
00067      */
00068     static const int rank_subst = 1 << 4;
00069 
00070     /// Set for a flag that, when detected, will call printVersion() and halt the program.
00071     static const int version_flag = 1 << 5;
00072 
00073     /// unimplemented flag for required arguments that may be given multiple times
00074     // const static int accept_multiple;
00075 
00076     /**
00077      * @param helptext A brief summary of the program's function, to be printed
00078      *        when the help flag is detected
00079      */
00080     ProgOptions( const std::string& helptext = "", const std::string& briefdesc = "" );
00081     ~ProgOptions();
00082 
00083     /** Specify the program version
00084      *
00085      * Set the program version to a given string.  This will be printed when printVersion()
00086      * is called.
00087      * @param version_string The version string
00088      * @param addflag If true, a default '--version' option will be added.  If false,
00089      *        the version will be set, but no option will be added to the parser.
00090      */
00091     void setVersion( const std::string& version_string, bool addFlag = true );
00092 
00093     /** Specify a new command-line option
00094      *
00095      * Instruct the parser to accept a new command-line argument, as well as specifying
00096      * how the argument should be handled.  The template parameter indicates the type of
00097      * command-line option being specified: acceptable types are void (indicating a flag
00098      * without an argument), int, double, and std::string.
00099      *
00100      * @param namestring The command-line options name(s).  Format is longname,shortname.
00101      *        If the comma is omitted, or appears only at the end, this option will have
00102      *        no shortname; if the comma is the first letter of the namestring, the option
00103      *        has no longname.
00104      * @param helpstring The help information displayed for the option when the program is
00105      *        invoked with --help
00106      * @param value A pointer to memory in which to store the parsed value for this option.
00107      *        If NULL, then the value of the option must be queried using the getOpt function.
00108      *        If the template parameter is void and value is non-NULL, treat value as a bool*
00109      *        and store 'true' into it when the flag is encountered.  (See also store_false, above)
00110      * @param flags Option behavior flags, which should come from static vars in the ProgOptions
00111      *        class
00112      */
00113     template < typename T >
00114     void addOpt( const std::string& namestring, const std::string& helpstring, T* value, int flags = 0 );
00115 
00116     /** Specify a new command-line option
00117      *
00118      * This funtion is identical to the 4-arg version, but omits the value parameter, which
00119      * is assumed to be NULL
00120      */
00121     template < typename T >
00122     void addOpt( const std::string& namestring, const std::string& helpstring, int flags = 0 )
00123     {
00124         addOpt< T >( namestring, helpstring, NULL, flags );
00125     }
00126 
00127     /** Add a new line of help text to the option help printout
00128      *
00129      * Add a line of text to the option-related help.  Called between calls to addOpt(),
00130      * this function can be used to divide the option list into groups of related options
00131      * to make the help text more convenient.
00132      */
00133     void addOptionHelpHeading( const std::string& );
00134 
00135     /** Add required positional argument
00136      *
00137      * Add a new required positional argument.  The order in which arguments are specified
00138      * is the order in which they will be expected on the command line.
00139      * The template parameter may be int, double, or std::string (but not void)
00140      * @param helpname The name to give the argument in the help text
00141      * @param helpstring The help text for the argument
00142      * @param value Pointer to where parsed value from command line should be stored.
00143      *        If NULL, the value must be queried using getReqArg()
00144      */
00145     template < typename T >
00146     void addRequiredArg( const std::string& helpname, const std::string& helpstring, T* value = NULL, int flags = 0 );
00147 
00148     /** Add optional positional arguments
00149      *
00150      * Specify location in ordered argument list at which optional arguments
00151      * may occur.  Optional arguments are allowed at only one location
00152      * it argument list (this function may not be called more than once.).
00153      * The template parameter may be int, double, or std::string (but not void)
00154      * @param count The maximum number of optional arguments.  Specify zero for unlimited.
00155      * @param helpname The name to give the argument in the help text
00156      * @param helpstring The help text for the arguments
00157      */
00158     template < typename T >
00159     void addOptionalArgs( unsigned max_count,
00160                           const std::string& helpname,
00161                           const std::string& helpstring,
00162                           int flags = 0 );
00163 
00164     /**
00165      * Print the full help to the given stream
00166      */
00167     void printHelp( std::ostream& str = std::cout );
00168 
00169     /**
00170      * Print only the usage message to the given stream
00171      */
00172     void printUsage( std::ostream& str = std::cout );
00173 
00174     /**
00175      * Print the version string to the given stream
00176      */
00177     void printVersion( std::ostream& str = std::cout );
00178 
00179     /**
00180      * Parse command-line inputs as given to main()
00181      */
00182     void parseCommandLine( int argc, char* argv[] );
00183 
00184     /**
00185      *
00186      * Get the value of the named option.
00187      * @param namestring The name string given when the option was created.  This need not be
00188      *        idential to the created name; only the longname, or the shortname (with comma prefix),
00189      *        will also work.
00190      * @param value Pointer to location to store option argument, if any is found
00191      * @return True if the option was set and its argument was stored into value; false otherwise.
00192      */
00193     template < typename T >
00194     bool getOpt( const std::string& namestring, T* value );
00195 
00196     /**
00197      * Get a list of values for the named option-- one value for each time it was
00198      * given on the command line.
00199      *
00200      * This function cannot be called with void as the template parameter;
00201      * compilers will reject vector<void> as a type.  This means it cannot be
00202      * called for flag-type options.  To count the number of times a given flag
00203      * was specified, use numOptSet()
00204      * @param namestring See similar argument to getOpt()
00205      * @param values Reference to list to store values into.  Will have as many entries
00206      *        as there were instances of this option on the command line
00207      */
00208     template < typename T >
00209     void getOptAllArgs( const std::string& namestring, std::vector< T >& values );
00210 
00211     /**
00212      * @param namestring See similar argument to getOpt()
00213      * @return The number of times the named option appeared on the command line.
00214      */
00215     int numOptSet( const std::string& namestring );
00216 
00217     /**
00218      * Retrieve the value of a required command-line argument by name
00219      * @param namestring The helpname that was given to addRequiredArg when the
00220      *        desired argument was created
00221      */
00222     template < typename T >
00223     T getReqArg( const std::string& namestring );
00224 
00225     /**
00226      * Append the values of any required or optional arguments
00227      * @param namestring The helpname that was given to addRequiredArg or
00228      *                   addOptionalArgs.
00229      */
00230     template < typename T >
00231     void getArgs( const std::string& namestring, std::vector< T >& values );
00232 
00233     /**
00234      * Prints an error message to std::cerr, along with a brief usage message,
00235      * then halts the program.  Used throughout ProgramOptions implementation.
00236      * Users may call this directly if they detect an incorrect usage of program
00237      * options that the ProgramOptions wasn't able to detect itself.
00238      * @param message The error message to print before program halt.
00239      */
00240     void error( const std::string& message );
00241 
00242     /**
00243      * Write help data formatted for use as a unix man page.
00244      */
00245     void write_man_page( std::ostream& to_this_stream );
00246 
00247   protected:
00248     std::string get_option_usage_prefix( const ProgOpt& option );
00249 
00250     void get_namestrings( const std::string& input, std::string* l, std::string* s );
00251 
00252     ProgOpt* lookup( const std::map< std::string, ProgOpt* >&, const std::string& );
00253     ProgOpt* lookup_option( const std::string& );
00254 
00255     bool evaluate( const ProgOpt& opt, void* target, const std::string& option, unsigned* arg_idx = NULL );
00256     bool process_option( ProgOpt* opt, std::string arg, const char* value = 0 );
00257 
00258     std::map< std::string, ProgOpt* > long_names;
00259     std::map< std::string, ProgOpt* > short_names;
00260     std::map< std::string, ProgOpt* > required_args;
00261 
00262     typedef std::pair< ProgOpt*, std::string > help_line;
00263     std::vector< help_line > option_help_strings;
00264     std::vector< help_line > arg_help_strings;
00265     std::vector< std::string > main_help;
00266     std::string brief_help;
00267 
00268     bool expect_optional_args;
00269     unsigned optional_args_position, max_optional_args;
00270 
00271     std::string progname;
00272     std::string progversion;
00273 
00274     // if an option was specified with the int_flag, this
00275     // will contain the long name of the option
00276     std::string number_option_name;
00277 };
00278 
00279 #endif /* MOAB_PROGRAM_OPTIONS_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines