MOAB: Mesh Oriented datABase  (version 5.4.1)
CLArgs.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines