Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
ProgOptions.hpp
Go to the documentation of this file.
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  */
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  void addOpt( const std::string& namestring, const std::string& helpstring, int flags = 0 )
123  {
124  addOpt< T >( namestring, helpstring, NULL, flags );
125  }
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,
160  const std::string& helpname,
161  const std::string& helpstring,
162  int flags = 0 );
163 
164  /**
165  * Print the full help to the given stream
166  */
167  void printHelp( std::ostream& str = std::cout );
168 
169  /**
170  * Print only the usage message to the given stream
171  */
172  void printUsage( std::ostream& str = std::cout );
173 
174  /**
175  * Print the version string to the given stream
176  */
177  void printVersion( std::ostream& str = std::cout );
178 
179  /**
180  * Parse command-line inputs as given to main()
181  */
182  void parseCommandLine( int argc, char* argv[] );
183 
184  /**
185  *
186  * Get the value of the named option.
187  * @param namestring The name string given when the option was created. This need not be
188  * idential to the created name; only the longname, or the shortname (with comma prefix),
189  * will also work.
190  * @param value Pointer to location to store option argument, if any is found
191  * @return True if the option was set and its argument was stored into value; false otherwise.
192  */
193  template < typename T >
194  bool getOpt( const std::string& namestring, T* value );
195 
196  /**
197  * Get a list of values for the named option-- one value for each time it was
198  * given on the command line.
199  *
200  * This function cannot be called with void as the template parameter;
201  * compilers will reject vector<void> as a type. This means it cannot be
202  * called for flag-type options. To count the number of times a given flag
203  * was specified, use numOptSet()
204  * @param namestring See similar argument to getOpt()
205  * @param values Reference to list to store values into. Will have as many entries
206  * as there were instances of this option on the command line
207  */
208  template < typename T >
209  void getOptAllArgs( const std::string& namestring, std::vector< T >& values );
210 
211  /**
212  * @param namestring See similar argument to getOpt()
213  * @return The number of times the named option appeared on the command line.
214  */
215  int numOptSet( const std::string& namestring );
216 
217  /**
218  * Retrieve the value of a required command-line argument by name
219  * @param namestring The helpname that was given to addRequiredArg when the
220  * desired argument was created
221  */
222  template < typename T >
223  T getReqArg( const std::string& namestring );
224 
225  /**
226  * Append the values of any required or optional arguments
227  * @param namestring The helpname that was given to addRequiredArg or
228  * addOptionalArgs.
229  */
230  template < typename T >
231  void getArgs( const std::string& namestring, std::vector< T >& values );
232 
233  /**
234  * Prints an error message to std::cerr, along with a brief usage message,
235  * then halts the program. Used throughout ProgramOptions implementation.
236  * Users may call this directly if they detect an incorrect usage of program
237  * options that the ProgramOptions wasn't able to detect itself.
238  * @param message The error message to print before program halt.
239  */
240  void error( const std::string& message );
241 
242  /**
243  * Write help data formatted for use as a unix man page.
244  */
245  void write_man_page( std::ostream& to_this_stream );
246 
247  protected:
248  std::string get_option_usage_prefix( const ProgOpt& option );
249 
250  void get_namestrings( const std::string& input, std::string* l, std::string* s );
251 
252  ProgOpt* lookup( const std::map< std::string, ProgOpt* >&, const std::string& );
253  ProgOpt* lookup_option( const std::string& );
254 
255  bool evaluate( const ProgOpt& opt, void* target, const std::string& option, unsigned* arg_idx = NULL );
256  bool process_option( ProgOpt* opt, std::string arg, const char* value = 0 );
257 
258  std::map< std::string, ProgOpt* > long_names;
259  std::map< std::string, ProgOpt* > short_names;
260  std::map< std::string, ProgOpt* > required_args;
261 
262  typedef std::pair< ProgOpt*, std::string > help_line;
263  std::vector< help_line > option_help_strings;
264  std::vector< help_line > arg_help_strings;
265  std::vector< std::string > main_help;
266  std::string brief_help;
267 
270 
271  std::string progname;
272  std::string progversion;
273 
274  // if an option was specified with the int_flag, this
275  // will contain the long name of the option
276  std::string number_option_name;
277 };
278 
279 #endif /* MOAB_PROGRAM_OPTIONS_H */