LCOV - code coverage report
Current view: top level - src/moab - ProgOptions.hpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 3 3 100.0 %
Date: 2020-12-16 07:07:30 Functions: 2 2 100.0 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : #ifndef MOAB_PROGRAM_OPTIONS_H
       2                 :            : #define MOAB_PROGRAM_OPTIONS_H
       3                 :            : 
       4                 :            : #include <vector>
       5                 :            : #include <map>
       6                 :            : #include <string>
       7                 :            : #include <iostream>
       8                 :            : 
       9                 :            : class ProgOpt;
      10                 :            : 
      11                 :            : /** A simple command-line option parser and help utility
      12                 :            :  *
      13                 :            :  * Utility class to specify a program's command-line options arguments, produce a help message
      14                 :            :  * explaining how they work, and parse user's command line input (producing useful errors messages
      15                 :            :  * if any problems arise).  Loosely (okay, very loosely) inspired by boost program_options.
      16                 :            :  *
      17                 :            :  * Options are specified by a comma-separated namestring.  An option named "foo,f" can be specified
      18                 :            :  * three ways on the command line: "-f val", "--foo val", or "--foo=val".  The types of options
      19                 :            :  * and arguments are specified by function templates.  Valid template values for positional argument
      20                 :            :  * and options are int, double, and std::string.  void may also be used in options, and it indicates
      21                 :            :  * a command line option that does not take an argument.
      22                 :            :  *
      23                 :            :  * Example usage:
      24                 :            :  * ProgOptions po( "Example usage of ProgOptions" );
      25                 :            :  * po.addOpt<void>( "verbose,v", "Turn on verbose messages" );
      26                 :            :  * po.addOpt<std::string> ("foo", "Specify the foo string" );
      27                 :            :  * int x = 0;
      28                 :            :  * po.addOpt<int>( ",x", "Specify the x number", &x ); // x will be automatically set when options
      29                 :            :  * parsed po.parseCommandLine( argc, argv ); bool verbose = po.numOptSet("verbose") > 0; std::string
      30                 :            :  * foo; if( !po.getOpt( "foo", &foo ) ) foo = "default";
      31                 :            :  * ...
      32                 :            :  *
      33                 :            :  * See the file dagmc_preproc.cpp in the dagmc directory for a real-world example.
      34                 :            :  */
      35                 :            : class ProgOptions
      36                 :            : {
      37                 :            : 
      38                 :            :   public:
      39                 :            :     /**
      40                 :            :      * Flags for addOpt and addRequiredArg functions; may be combined with bitwise arithmetic
      41                 :            :      * (though not all combinations make sense!)
      42                 :            :      **/
      43                 :            : 
      44                 :            :     /// Set for a flag that, when detected, prints help text and halts program.
      45                 :            :     /// Constructor creates such a flag by default, so the user shouldn't need to use this directly.
      46                 :            :     static const int help_flag = 1 << 0;
      47                 :            : 
      48                 :            :     /// Flag indicating that an option should be given a "cancel" flag.
      49                 :            :     /// This creates, for option --foo, an additional option --no-foo that
      50                 :            :     /// clears all previously read instances of the foo option
      51                 :            :     static const int add_cancel_opt = 1 << 1;
      52                 :            : 
      53                 :            :     /// When applied to a flag argument (one with template type void), indicate that the
      54                 :            :     /// value 'false' should be stored into the pointer that was given at option creation time.
      55                 :            :     /// This overrides the default behavior, which is to store the value 'true'.
      56                 :            :     static const int store_false = 1 << 2;
      57                 :            : 
      58                 :            :     /// Specify a numerical flag where any positive integer is an acceptable
      59                 :            :     /// value.  E.g. --dimension=3 is equivalent to -3.  Only values in the
      60                 :            :     /// range [0,9] are accepted and the flag type must be integer.
      61                 :            :     static const int int_flag = 1 << 3;
      62                 :            : 
      63                 :            :     /** Substitue any occurance of the '%' symbol in a string with
      64                 :            :      *  the the MPI rank of this process in MPI_COMM_WORLD.  This
      65                 :            :      *  option has no effect if not compiled with MPI.  This flag
      66                 :            :      *  has no effect for non-string options.
      67                 :            :      */
      68                 :            :     static const int rank_subst = 1 << 4;
      69                 :            : 
      70                 :            :     /// Set for a flag that, when detected, will call printVersion() and halt the program.
      71                 :            :     static const int version_flag = 1 << 5;
      72                 :            : 
      73                 :            :     /// unimplemented flag for required arguments that may be given multiple times
      74                 :            :     // const static int accept_multiple;
      75                 :            : 
      76                 :            :     /**
      77                 :            :      * @param helptext A brief summary of the program's function, to be printed
      78                 :            :      *        when the help flag is detected
      79                 :            :      */
      80                 :            :     ProgOptions( const std::string& helptext = "", const std::string& briefdesc = "" );
      81                 :            :     ~ProgOptions();
      82                 :            : 
      83                 :            :     /** Specify the program version
      84                 :            :      *
      85                 :            :      * Set the program version to a given string.  This will be printed when printVersion()
      86                 :            :      * is called.
      87                 :            :      * @param version_string The version string
      88                 :            :      * @param addflag If true, a default '--version' option will be added.  If false,
      89                 :            :      *        the version will be set, but no option will be added to the parser.
      90                 :            :      */
      91                 :            :     void setVersion( const std::string& version_string, bool addFlag = true );
      92                 :            : 
      93                 :            :     /** Specify a new command-line option
      94                 :            :      *
      95                 :            :      * Instruct the parser to accept a new command-line argument, as well as specifying
      96                 :            :      * how the argument should be handled.  The template parameter indicates the type of
      97                 :            :      * command-line option being specified: acceptable types are void (indicating a flag
      98                 :            :      * without an argument), int, double, and std::string.
      99                 :            :      *
     100                 :            :      * @param namestring The command-line options name(s).  Format is longname,shortname.
     101                 :            :      *        If the comma is omitted, or appears only at the end, this option will have
     102                 :            :      *        no shortname; if the comma is the first letter of the namestring, the option
     103                 :            :      *        has no longname.
     104                 :            :      * @param helpstring The help information displayed for the option when the program is
     105                 :            :      *        invoked with --help
     106                 :            :      * @param value A pointer to memory in which to store the parsed value for this option.
     107                 :            :      *        If NULL, then the value of the option must be queried using the getOpt function.
     108                 :            :      *        If the template parameter is void and value is non-NULL, treat value as a bool*
     109                 :            :      *        and store 'true' into it when the flag is encountered.  (See also store_false, above)
     110                 :            :      * @param flags Option behavior flags, which should come from static vars in the ProgOptions
     111                 :            :      *        class
     112                 :            :      */
     113                 :            :     template < typename T >
     114                 :            :     void addOpt( const std::string& namestring, const std::string& helpstring, T* value, int flags = 0 );
     115                 :            : 
     116                 :            :     /** Specify a new command-line option
     117                 :            :      *
     118                 :            :      * This funtion is identical to the 4-arg version, but omits the value parameter, which
     119                 :            :      * is assumed to be NULL
     120                 :            :      */
     121                 :            :     template < typename T >
     122                 :         26 :     void addOpt( const std::string& namestring, const std::string& helpstring, int flags = 0 )
     123                 :            :     {
     124                 :         26 :         addOpt< T >( namestring, helpstring, NULL, flags );
     125                 :         26 :     }
     126                 :            : 
     127                 :            :     /** Add a new line of help text to the option help printout
     128                 :            :      *
     129                 :            :      * Add a line of text to the option-related help.  Called between calls to addOpt(),
     130                 :            :      * this function can be used to divide the option list into groups of related options
     131                 :            :      * to make the help text more convenient.
     132                 :            :      */
     133                 :            :     void addOptionHelpHeading( const std::string& );
     134                 :            : 
     135                 :            :     /** Add required positional argument
     136                 :            :      *
     137                 :            :      * Add a new required positional argument.  The order in which arguments are specified
     138                 :            :      * is the order in which they will be expected on the command line.
     139                 :            :      * The template parameter may be int, double, or std::string (but not void)
     140                 :            :      * @param helpname The name to give the argument in the help text
     141                 :            :      * @param helpstring The help text for the argument
     142                 :            :      * @param value Pointer to where parsed value from command line should be stored.
     143                 :            :      *        If NULL, the value must be queried using getReqArg()
     144                 :            :      */
     145                 :            :     template < typename T >
     146                 :            :     void addRequiredArg( const std::string& helpname, const std::string& helpstring, T* value = NULL, int flags = 0 );
     147                 :            : 
     148                 :            :     /** Add optional positional arguments
     149                 :            :      *
     150                 :            :      * Specify location in ordered argument list at which optional arguments
     151                 :            :      * may occur.  Optional arguments are allowed at only one location
     152                 :            :      * it argument list (this function may not be called more than once.).
     153                 :            :      * The template parameter may be int, double, or std::string (but not void)
     154                 :            :      * @param count The maximum number of optional arguments.  Specify zero for unlimited.
     155                 :            :      * @param helpname The name to give the argument in the help text
     156                 :            :      * @param helpstring The help text for the arguments
     157                 :            :      */
     158                 :            :     template < typename T >
     159                 :            :     void addOptionalArgs( unsigned max_count, const std::string& helpname, const std::string& helpstring,
     160                 :            :                           int flags = 0 );
     161                 :            : 
     162                 :            :     /**
     163                 :            :      * Print the full help to the given stream
     164                 :            :      */
     165                 :            :     void printHelp( std::ostream& str = std::cout );
     166                 :            : 
     167                 :            :     /**
     168                 :            :      * Print only the usage message to the given stream
     169                 :            :      */
     170                 :            :     void printUsage( std::ostream& str = std::cout );
     171                 :            : 
     172                 :            :     /**
     173                 :            :      * Print the version string to the given stream
     174                 :            :      */
     175                 :            :     void printVersion( std::ostream& str = std::cout );
     176                 :            : 
     177                 :            :     /**
     178                 :            :      * Parse command-line inputs as given to main()
     179                 :            :      */
     180                 :            :     void parseCommandLine( int argc, char* argv[] );
     181                 :            : 
     182                 :            :     /**
     183                 :            :      *
     184                 :            :      * Get the value of the named option.
     185                 :            :      * @param namestring The name string given when the option was created.  This need not be
     186                 :            :      *        idential to the created name; only the longname, or the shortname (with comma prefix),
     187                 :            :      *        will also work.
     188                 :            :      * @param value Pointer to location to store option argument, if any is found
     189                 :            :      * @return True if the option was set and its argument was stored into value; false otherwise.
     190                 :            :      */
     191                 :            :     template < typename T >
     192                 :            :     bool getOpt( const std::string& namestring, T* value );
     193                 :            : 
     194                 :            :     /**
     195                 :            :      * Get a list of values for the named option-- one value for each time it was
     196                 :            :      * given on the command line.
     197                 :            :      *
     198                 :            :      * This function cannot be called with void as the template parameter;
     199                 :            :      * compilers will reject vector<void> as a type.  This means it cannot be
     200                 :            :      * called for flag-type options.  To count the number of times a given flag
     201                 :            :      * was specified, use numOptSet()
     202                 :            :      * @param namestring See similar argument to getOpt()
     203                 :            :      * @param values Reference to list to store values into.  Will have as many entries
     204                 :            :      *        as there were instances of this option on the command line
     205                 :            :      */
     206                 :            :     template < typename T >
     207                 :            :     void getOptAllArgs( const std::string& namestring, std::vector< T >& values );
     208                 :            : 
     209                 :            :     /**
     210                 :            :      * @param namestring See similar argument to getOpt()
     211                 :            :      * @return The number of times the named option appeared on the command line.
     212                 :            :      */
     213                 :            :     int numOptSet( const std::string& namestring );
     214                 :            : 
     215                 :            :     /**
     216                 :            :      * Retrieve the value of a required command-line argument by name
     217                 :            :      * @param namestring The helpname that was given to addRequiredArg when the
     218                 :            :      *        desired argument was created
     219                 :            :      */
     220                 :            :     template < typename T >
     221                 :            :     T getReqArg( const std::string& namestring );
     222                 :            : 
     223                 :            :     /**
     224                 :            :      * Append the values of any required or optional arguments
     225                 :            :      * @param namestring The helpname that was given to addRequiredArg or
     226                 :            :      *                   addOptionalArgs.
     227                 :            :      */
     228                 :            :     template < typename T >
     229                 :            :     void getArgs( const std::string& namestring, std::vector< T >& values );
     230                 :            : 
     231                 :            :     /**
     232                 :            :      * Prints an error message to std::cerr, along with a brief usage message,
     233                 :            :      * then halts the program.  Used throughout ProgramOptions implementation.
     234                 :            :      * Users may call this directly if they detect an incorrect usage of program
     235                 :            :      * options that the ProgramOptions wasn't able to detect itself.
     236                 :            :      * @param message The error message to print before program halt.
     237                 :            :      */
     238                 :            :     void error( const std::string& message );
     239                 :            : 
     240                 :            :     /**
     241                 :            :      * Write help data formatted for use as a unix man page.
     242                 :            :      */
     243                 :            :     void write_man_page( std::ostream& to_this_stream );
     244                 :            : 
     245                 :            :   protected:
     246                 :            :     std::string get_option_usage_prefix( const ProgOpt& option );
     247                 :            : 
     248                 :            :     void get_namestrings( const std::string& input, std::string* l, std::string* s );
     249                 :            : 
     250                 :            :     ProgOpt* lookup( const std::map< std::string, ProgOpt* >&, const std::string& );
     251                 :            :     ProgOpt* lookup_option( const std::string& );
     252                 :            : 
     253                 :            :     bool evaluate( const ProgOpt& opt, void* target, const std::string& option, unsigned* arg_idx = NULL );
     254                 :            :     bool process_option( ProgOpt* opt, std::string arg, const char* value = 0 );
     255                 :            : 
     256                 :            :     std::map< std::string, ProgOpt* > long_names;
     257                 :            :     std::map< std::string, ProgOpt* > short_names;
     258                 :            :     std::map< std::string, ProgOpt* > required_args;
     259                 :            : 
     260                 :            :     typedef std::pair< ProgOpt*, std::string > help_line;
     261                 :            :     std::vector< help_line > option_help_strings;
     262                 :            :     std::vector< help_line > arg_help_strings;
     263                 :            :     std::vector< std::string > main_help;
     264                 :            :     std::string brief_help;
     265                 :            : 
     266                 :            :     bool expect_optional_args;
     267                 :            :     unsigned optional_args_position, max_optional_args;
     268                 :            : 
     269                 :            :     std::string progname;
     270                 :            :     std::string progversion;
     271                 :            : 
     272                 :            :     // if an option was specified with the int_flag, this
     273                 :            :     // will contain the long name of the option
     274                 :            :     std::string number_option_name;
     275                 :            : };
     276                 :            : 
     277                 :            : #endif /* MOAB_PROGRAM_OPTIONS_H */

Generated by: LCOV version 1.11