MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /* ***************************************************************** 00002 MESQUITE -- The Mesh Quality Improvement Toolkit 00003 00004 Copyright 2008 Sandia National Laboratories. Developed at the 00005 University of Wisconsin--Madison under SNL contract number 00006 624796. The U.S. Government and the University of Wisconsin 00007 retain certain rights to this software. 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License 00020 (lgpl.txt) along with this library; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 (2008) [email protected] 00024 00025 ***************************************************************** */ 00026 00027 /** \file CLArgs.hpp 00028 * \brief 00029 * \author Jason Kraftcheck 00030 */ 00031 00032 #ifndef MSQ_CLARGS_HPP 00033 #define MSQ_CLARGS_HPP 00034 00035 class CLArgImpl; 00036 00037 #include "Mesquite.hpp" 00038 #include <iosfwd> 00039 #include <vector> 00040 #include <string> 00041 #include <sstream> 00042 #include <iterator> 00043 00044 /**\brief Parse command-line arguments 00045 * 00046 * This class provides a mechanism for parsing and to some extend validating 00047 * command-line arguments. Use of this class can be divided into three steps: 00048 * 00049 * 1) Call *_flag and arg methods to define acceptable command line arguments 00050 * 00051 * 2) Call parse_options to parse the command line arguments according to 00052 * acceptable flags defined in step 1. 00053 * 00054 * 3) Check the values in registerd callback class instances. 00055 * 00056 * The '-h' flag is reserved for reqesting a description of the allowable 00057 * arguments (help). If it is encountered inside parse_options, the help 00058 * will be printed and the program will be terminated w/out returning from 00059 * parse_options. 00060 * 00061 * The '-M' flag is similar to '-h', except that the help is written 00062 * in UNIX 'man page' format. 00063 */ 00064 class CLArgs 00065 { 00066 public: 00067 /**\brief Base class for callback interface (type-independent functions) */ 00068 class ArgIBase 00069 { 00070 private: 00071 bool wasSeen; //!< Keep track of whether or not this flag was encountered 00072 public: 00073 ArgIBase() : wasSeen( false ) {} //!< constructor 00074 virtual ~ArgIBase() {} //!< virtual destructor for proper cleanup 00075 /**\brief Get short description string for usage output or empty string for default*/ 00076 virtual std::string brief() const 00077 { 00078 return std::string(); 00079 } 00080 /**\brief Get short description string for UNIX man page output or empty string for default 00081 */ 00082 virtual std::string manstr() const 00083 { 00084 return std::string(); 00085 } 00086 /**\brief Get optional additional info to print with flag description */ 00087 virtual std::string desc_append() const 00088 { 00089 return std::string(); 00090 } 00091 /**\brief Get optional string containing default value for option if not specified by user 00092 */ 00093 virtual std::string default_str() const 00094 { 00095 return std::string(); 00096 } 00097 /**\brief Mark this flag as having been specified by the user */ 00098 void set_seen() 00099 { 00100 wasSeen = true; 00101 } 00102 /**\brief Test if the user specified this flag */ 00103 bool seen() const 00104 { 00105 return wasSeen; 00106 } 00107 }; 00108 00109 /**\brief Interface for type-specific callback classes */ 00110 template < typename T > 00111 class ArgTemplateI : public ArgIBase 00112 { 00113 public: 00114 virtual bool value( const T& val ) = 0; 00115 }; 00116 /**\brief Trivial implementation for type-specific classes */ 00117 template < typename T > 00118 class ArgTemplate : public ArgTemplateI< T > 00119 { 00120 private: 00121 T mValue; //!< The default or user-specified value for an option. 00122 bool haveDefault; //!< True if app. provided default value. 00123 public: 00124 virtual ~ArgTemplate() {} 00125 virtual bool value( const T& val ) //!< Set value 00126 { 00127 mValue = val; 00128 ArgTemplateI< T >::set_seen(); 00129 return true; 00130 } 00131 const T& value() const 00132 { 00133 return mValue; 00134 } //!< get value 00135 /**\brief Initialize with default value */ 00136 ArgTemplate( const T& initial_value ) : mValue( initial_value ), haveDefault( true ) {} 00137 /**\brief Initialize without default value */ 00138 ArgTemplate() : mValue( T() ), haveDefault( false ) {} 00139 /**\brief Get string representation of default value, or empty string of no default value */ 00140 virtual std::string default_str() const 00141 { 00142 std::ostringstream ss; 00143 if( haveDefault ) ss << mValue; 00144 return ss.str(); 00145 } 00146 }; 00147 00148 /**\brief Trivial implementation for type-specific classes */ 00149 template < typename T > 00150 class ArgListTemplate : public ArgTemplateI< std::vector< T > > 00151 { 00152 private: 00153 std::vector< T > mValue; //!< The default or user-specified value for an option. 00154 bool haveDefault; //!< True if app. provided default value. 00155 public: 00156 virtual ~ArgListTemplate() {} 00157 virtual bool value( const std::vector< T >& val ) //!< Set value 00158 { 00159 mValue = val; 00160 ArgTemplateI< std::vector< T > >::set_seen(); 00161 return true; 00162 } 00163 const std::vector< T >& value() const 00164 { 00165 return mValue; 00166 } //!< get value 00167 /**\brief Initialize with default value */ 00168 ArgListTemplate( const std::vector< T >& initial_value ) : mValue( initial_value ), haveDefault( true ) {} 00169 /**\brief Initialize without default value */ 00170 ArgListTemplate() : haveDefault( false ) {} 00171 /**\brief Get string representation of default value, or empty string of no default value */ 00172 virtual std::string default_str() const 00173 { 00174 std::ostringstream ss; 00175 std::copy( mValue.begin(), mValue.end(), std::ostream_iterator< T >( ss, ", " ) ); 00176 return ss.str(); 00177 } 00178 }; 00179 00180 /**\brief Callback API for a string argument */ 00181 typedef ArgTemplateI< std::string > StringArgI; 00182 /**\brief Callback API for an integer argument */ 00183 typedef ArgTemplateI< int > IntArgI; 00184 /**\brief Callback API for a long integer argument */ 00185 typedef ArgTemplateI< long > LongArgI; 00186 /**\brief Callback API for a double-precision floating-point argument */ 00187 typedef ArgTemplateI< double > DoubleArgI; 00188 /**\brief Callback API for a Boolean or toggle argument */ 00189 typedef ArgTemplateI< bool > ToggleArgI; 00190 /**\brief Callback API for an integer list argument */ 00191 typedef ArgTemplateI< std::vector< int > > IntListArgI; 00192 /**\brief Callback API for a double list argument */ 00193 typedef ArgTemplateI< std::vector< double > > DoubleListArgI; 00194 00195 /**\brief Trivial callback implementation for a string argument */ 00196 typedef ArgTemplate< std::string > StringArg; 00197 /**\brief Trivial callback implementation for an integer argument */ 00198 typedef ArgTemplate< int > IntArg; 00199 /**\brief Trivial callback implementation for a long integer argument */ 00200 typedef ArgTemplate< long > LongArg; 00201 /**\brief Trivial callback implementation for a ouble-precision floating-point argument */ 00202 typedef ArgTemplate< double > DoubleArg; 00203 /**\brief Trivial callback implementation for a Boolean or toggle argument */ 00204 typedef ArgTemplate< bool > ToggleArg; 00205 /**\brief Trivial callback implementation for an integer list argument */ 00206 typedef ArgListTemplate< int > IntListArg; 00207 /**\brief Trivial callback implementation for a double list argument */ 00208 typedef ArgListTemplate< double > DoubleListArg; 00209 00210 /**\brief String arugment that is limited to a list of acceptable keywords 00211 * 00212 * A specialized string arugment implementation that limits the 00213 * acceptable string argument to one of a list of keywords. 00214 * A case-insensitive comparison is done with the allowed keywords. 00215 * The "value" has the case of the keyword rather than the case 00216 * used in the literal value specified in the command line argument. 00217 */ 00218 class KeyWordArg : public StringArg 00219 { 00220 private: 00221 std::vector< std::string > mKeyWords; 00222 void initialize( const char* keyword_list[], int list_length ); 00223 00224 public: 00225 KeyWordArg( const char* keyword_list[], int list_length ) 00226 { 00227 initialize( keyword_list, list_length ); 00228 } 00229 KeyWordArg( const char* default_val, const char* keyword_list[], int list_length ) : StringArg( default_val ) 00230 { 00231 initialize( keyword_list, list_length ); 00232 } 00233 virtual bool value( const std::string& val ); 00234 virtual std::string brief() const; 00235 virtual std::string manstr() const; 00236 static bool compare_no_case( const char* s1, const char* s2 ); 00237 }; 00238 00239 class IntRange 00240 { 00241 private: 00242 int mMin, mMax; 00243 00244 public: 00245 IntRange( const int* min, const int* max ); 00246 bool is_valid( int val ) const; 00247 std::string desc_append() const; 00248 }; 00249 00250 /**\brief Integer argument constrained to a range of valid values. */ 00251 class IntRangeArg : public IntArg 00252 { 00253 private: 00254 IntRange mRange; 00255 00256 public: 00257 IntRangeArg( const int* min = 0, const int* max = 0 ) : mRange( min, max ) {} 00258 IntRangeArg( int default_val, const int* min, const int* max ) : IntArg( default_val ), mRange( min, max ) {} 00259 bool value( const int& val ); 00260 const int& value() const 00261 { 00262 return IntArg::value(); 00263 } 00264 std::string desc_append() const 00265 { 00266 return mRange.desc_append(); 00267 } 00268 }; 00269 00270 /**\brief Integer list argument constrained to a range of valid values. */ 00271 class IntListRangeArg : public IntListArg 00272 { 00273 private: 00274 IntRange mRange; 00275 00276 public: 00277 IntListRangeArg( const int* min = 0, const int* max = 0 ) : mRange( min, max ) {} 00278 bool value( const std::vector< int >& val ); 00279 const std::vector< int >& value() const 00280 { 00281 return IntListArg::value(); 00282 } 00283 std::string desc_append() const 00284 { 00285 return mRange.desc_append(); 00286 } 00287 }; 00288 00289 class DoubleRange 00290 { 00291 private: 00292 bool haveMin, haveMax, mInclusive; 00293 double mMin, mMax; 00294 00295 public: 00296 DoubleRange( const double* min, const double* max, bool inclusive ); 00297 bool is_valid( double value ) const; 00298 std::string desc_append() const; 00299 }; 00300 00301 /**\brief Double argument constrained to a range of valid values. */ 00302 class DoubleRangeArg : public DoubleArg 00303 { 00304 private: 00305 DoubleRange mRange; 00306 00307 public: 00308 DoubleRangeArg( const double* min = 0, const double* max = 0, bool inclusive = true ) 00309 : mRange( min, max, inclusive ) 00310 { 00311 } 00312 DoubleRangeArg( double default_val, const double* min = 0, const double* max = 0, bool inclusive = true ) 00313 : DoubleArg( default_val ), mRange( min, max, inclusive ) 00314 { 00315 } 00316 bool value( const double& val ); 00317 const double& value() const 00318 { 00319 return DoubleArg::value(); 00320 } 00321 std::string desc_append() const 00322 { 00323 return mRange.desc_append(); 00324 } 00325 }; 00326 00327 /**\brief Double list argument constrained to a range of valid values. */ 00328 class DoubleListRangeArg : public DoubleListArg 00329 { 00330 private: 00331 DoubleRange mRange; 00332 00333 public: 00334 DoubleListRangeArg( const double* min = 0, const double* max = 0, bool inclusive = true ) 00335 : mRange( min, max, inclusive ) 00336 { 00337 } 00338 bool value( const std::vector< double >& val ); 00339 const std::vector< double >& value() const 00340 { 00341 return DoubleListArg::value(); 00342 } 00343 std::string desc_append() const 00344 { 00345 return mRange.desc_append(); 00346 } 00347 }; 00348 00349 public: 00350 /**\brief Define basic program 00351 * 00352 *\param progname The program name 00353 *\param brief_desc A brief description of the purpose of the program. 00354 *\param desc Program description for documentation. 00355 */ 00356 CLArgs( const char* progname, const char* brief_desc, const char* desc ); 00357 00358 ~CLArgs(); 00359 00360 /**\brief Check if flag is undefined */ 00361 bool is_flag_available( char fl ) const; 00362 00363 /**\brief Register a flag that requires a string argument. 00364 * 00365 * Define a flag of the form "-f <somestring>". 00366 *\param fl The character for the flag. 00367 *\param name The name of the flag argument 00368 *\param desc A description of the purpose of the flag and argument. 00369 *\parma callback Object instance to which to pass the parsed argument value. 00370 *\return false if flag is already in use, true otherwise. 00371 */ 00372 bool str_flag( char fl, const char* name, const char* desc, StringArgI* callback ); 00373 00374 /**\brief Register a flag that requires an integer argument. 00375 * 00376 * Define a flag of the form "-f <int>". 00377 *\param fl The character for the flag. 00378 *\param name The name of the flag argument 00379 *\param desc A description of the purpose of the flag and argument. 00380 *\parma callback Object instance to which to pass the parsed argument value. 00381 *\return false if flag is already in use, true otherwise. 00382 */ 00383 bool int_flag( char fl, const char* name, const char* desc, IntArgI* callback ); 00384 00385 /**\brief Register a flag that requires an integer argument. 00386 * 00387 * Define a flag of the form "-f <int>". 00388 *\param fl The character for the flag. 00389 *\param name The name of the flag argument 00390 *\param desc A description of the purpose of the flag and argument. 00391 *\parma callback Object instance to which to pass the parsed argument value. 00392 *\return false if flag is already in use, true otherwise. 00393 */ 00394 bool long_flag( char fl, const char* name, const char* desc, LongArgI* callback ); 00395 00396 /**\brief Register a flag that requires a real umber argument. 00397 * 00398 * Define a flag of the form "-f <double>". 00399 *\param fl The character for the flag. 00400 *\param name The name of the flag argument 00401 *\param desc A description of the purpose of the flag and argument. 00402 *\parma callback Object instance to which to pass the parsed argument value. 00403 *\param inclusive If true, accept 'min' or 'max': [min,max]. If 00404 * false, reject 'min' and 'max' values: (min,max). 00405 *\return false if flag is already in use, true otherwise. 00406 */ 00407 bool double_flag( char fl, const char* name, const char* desc, DoubleArgI* callback ); 00408 00409 /**\brief Register a pair of flags that accept no arguments and have 00410 * opposing affects. 00411 * 00412 * Regstier a flag of the form [-f|-F], where one implies a true 00413 * state and the other a false state (i.e. enable or disable some 00414 * functionality.) 00415 *\param on_flag Flag corresponding to true or 'on' state. 00416 *\param off_flag Flag corresponding to false or 'off' state. 00417 *\param desc A description of the purpose of the flag and argument. 00418 *\parma callback Object instance to which to pass the parsed argument value. 00419 *\return false if flag is already in use, true otherwise. 00420 */ 00421 bool toggle_flag( char on_flag, char off_flag, const char* desc, ToggleArgI* callback ); 00422 00423 /**\brief Register a flag with no value. 00424 * 00425 * Define a flag such that the state of the option is considered 00426 * to be false unless flag is specified. If the flag is specified, 00427 * the option is considered to be true. 00428 *\param fl The character for the flag. 00429 *\param desc A description of the purpose of the flag and argument. 00430 *\parma callback Object instance to which to pass the parsed argument value. 00431 *\return false if flag is already in use, true otherwise. 00432 */ 00433 bool toggle_flag( char fl, const char* desc, ToggleArgI* callback ); 00434 00435 /**\brief Register a flag that accepts a list of positive integer arguments. 00436 * 00437 * Define a flag that accepts a list of ranges of positive integer values 00438 * separated by commas. A zero value is rejected. Ranges can be either 00439 * a single value or pair of values separated by a dash. For example: 00440 * "-f 1,4-10,2,20-25". 00441 * 00442 * Use 'get_int_list' to query values of flag. 00443 * 00444 *\param fl The character for the flag. 00445 *\param desc A description of the purpose of the flag and argument. 00446 *\parma callback Object instance to which to pass the parsed argument value. 00447 *\return false if flag is already in use, true otherwise. 00448 */ 00449 bool id_list_flag( char fl, const char* desc, IntListArgI* callback ); 00450 00451 /**\brief Register a flag that requires a comma-separated 00452 * list of integer values. 00453 * 00454 * Define a flag that has an integer list for its arguments. The 00455 * integers must be specified as a comma-separated list. 00456 * 00457 * Use 'limit_list_flag' to limit the number of values accepted 00458 * in the argument. If 'limit_list_flag' is never called, any 00459 * number of argument values will be accepted. 00460 * 00461 *\param fl The character for the flag. 00462 *\param desc A description of the purpose of the flag and argument. 00463 *\parma callback Object instance to which to pass the parsed argument value. 00464 *\return false if flag is already in use, true otherwise. 00465 */ 00466 bool int_list_flag( char fl, const char* desc, IntListArgI* callback ); 00467 00468 /**\brief Register a flag that requires a comma-separated 00469 * list of double values. 00470 * 00471 * Define a flag that has an double list for its arguments. The 00472 * values must be specified as a comma-separated list. 00473 * 00474 * Use 'limit_list_flag' to limit the number of values accepted 00475 * in the argument. If 'limit_list_flag' is never called, any 00476 * number of argument values will be accepted. 00477 * 00478 *\param fl The character for the flag. 00479 *\param desc A description of the purpose of the flag and argument. 00480 *\parma callback Object instance to which to pass the parsed argument value. 00481 *\return false if flag is already in use, true otherwise. 00482 */ 00483 bool double_list_flag( char fl, const char* desc, DoubleListArgI* callback ); 00484 00485 /**\brief Set a limit on the number of values accepted for a list-type 00486 * flag. May be called multiple times for a flag. 00487 * 00488 * Add a limit on the number of values accepted for a list-type flag. 00489 * This function may be called multiple times if the flag should 00490 * accept a finite set of different arugment value counts. 00491 * 00492 *\param fl The flag 00493 *\param num_values The number of values to accept 00494 *\param value_names An array of 'num_value' strings specifying the 00495 * name of each value. 00496 *\return false if flag is not defined as a list-type flag or this 00497 * method has already been called with the same flag AND 00498 * number of values. True otherwise. 00499 */ 00500 bool limit_list_flag( char fl, int num_values, const char* const* value_names ); 00501 00502 /**\brief Specify that an argument without a flag is expected. 00503 * 00504 * Arguments are parsed in the order they are added, with the 00505 * exception that all optional args are parsed after all required 00506 * args. 00507 * \param name 'name' of argument to display in help (e.g. "output_file"); 00508 */ 00509 void add_required_arg( const char* name ); 00510 void add_optional_arg( const char* name ); 00511 00512 /**\brief Parse argument list. 00513 * 00514 *\param argc The argument list length passed to the main() routine. 00515 * The first value is assumed to be the executable name. 00516 * This this value must be at least 1. 00517 *\param argv The argument list as passed to main(). 00518 *\param args_out The list of non-flag arguments encountered, as 00519 * defined by the 'args' method. If the 'args' method 00520 * has not been called, no non-flag arguments are accepted 00521 * and this list will be empty. 00522 *\param error_stream stream to which to write error messages. 00523 *\return true if all arguments were accepted. false otherwise. 00524 */ 00525 bool parse_options( int argc, char* argv[], std::vector< std::string >& args_out, std::ostream& error_stream ); 00526 00527 /**\brief Write help 00528 * 00529 * Write help text to passed stream. 00530 */ 00531 void print_help( std::ostream& stream ) const; 00532 00533 /**\brief Write UNIX man page 00534 * 00535 * Write man page to passed stream. 00536 */ 00537 void print_man_page( std::ostream& stream ) const; 00538 00539 /**\brief prinint usage (brief help) 00540 */ 00541 void print_usage( std::ostream& stream ) const; 00542 00543 private: 00544 CLArgImpl* impl; 00545 }; 00546 00547 template < typename T > 00548 std::ostream& operator<<( std::ostream& str, const std::vector< T >& list ) 00549 { 00550 typename std::vector< T >::const_iterator i = list.begin(); 00551 if( i != list.end() ) 00552 { 00553 str << *i; 00554 for( ++i; i != list.end(); ++i ) 00555 str << ',' << *i; 00556 } 00557 return str; 00558 } 00559 00560 #endif