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 */
|