BASIS  version 1.2.3 (revision 2104)
Arg.h
00001 // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
00002 
00003 /******************************************************************************
00004  *
00005  *  file:  Arg.h
00006  *
00007  *  Copyright (c) 2003, Michael E. Smoot .
00008  *  Copyright (c) 2004, Michael E. Smoot, Daniel Aarno .
00009  *  All rights reverved.
00010  *
00011  *  See the file COPYING in the top directory of this distribution for
00012  *  more information.
00013  *
00014  *  THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015  *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00017  *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00019  *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00020  *  DEALINGS IN THE SOFTWARE.
00021  *
00022  *****************************************************************************/
00023 
00024 
00025 #ifndef TCLAP_ARGUMENT_H
00026 #define TCLAP_ARGUMENT_H
00027 
00028 #include <sbia/basis/config.h>
00029 
00030 #include <string>
00031 #include <vector>
00032 #include <list>
00033 #include <iostream>
00034 #include <iomanip>
00035 #include <cstdio>
00036 
00037 #if defined(HAVE_SSTREAM)
00038 #include <sstream>
00039 typedef std::istringstream istringstream;
00040 #elif defined(HAVE_STRSTREAM)
00041 #include <strstream>
00042 typedef std::istrstream istringstream;
00043 #else
00044 #error "Need a stringstream (sstream or strstream) to compile!"
00045 #endif
00046 
00047 #include <sbia/tclap/ArgException.h>
00048 #include <sbia/tclap/Visitor.h>
00049 #include <sbia/tclap/CmdLineInterface.h>
00050 #include <sbia/tclap/ArgTraits.h>
00051 #include <sbia/tclap/StandardTraits.h>
00052 
00053 namespace TCLAP {
00054 
00055 /**
00056  * A virtual base class that defines the essential data for all arguments.
00057  * This class, or one of its existing children, must be subclassed to do
00058  * anything.
00059  */
00060 class Arg
00061 {
00062     private:
00063         /**
00064          * Prevent accidental copying.
00065          */
00066         Arg(const Arg& rhs);
00067 
00068         /**
00069          * Prevent accidental copying.
00070          */
00071         Arg& operator=(const Arg& rhs);
00072 
00073         /**
00074          * Indicates whether the rest of the arguments should be ignored.
00075          */
00076         static bool& ignoreRestRef() { static bool ign = false; return ign; }
00077 
00078         /**
00079          * The delimiter that separates an argument flag/name from the
00080          * value.
00081          */
00082         static char& delimiterRef() { static char delim = ' '; return delim; }
00083 
00084     protected:
00085 
00086         /**
00087          * The single char flag used to identify the argument.
00088          * This value (preceded by a dash {-}), can be used to identify
00089          * an argument on the command line.  The _flag can be blank,
00090          * in fact this is how unlabeled args work.  Unlabeled args must
00091          * override appropriate functions to get correct handling. Note
00092          * that the _flag does NOT include the dash as part of the flag.
00093          */
00094         std::string _flag;
00095 
00096         /**
00097          * A single work namd indentifying the argument.
00098          * This value (preceded by two dashed {--}) can also be used
00099          * to identify an argument on the command line.  Note that the
00100          * _name does NOT include the two dashes as part of the _name. The
00101          * _name cannot be blank.
00102          */
00103         std::string _name;
00104 
00105         /**
00106          * Description of the argument.
00107          */
00108         std::string _description;
00109 
00110         /**
00111          * Indicating whether the argument is required.
00112          */
00113         bool _required;
00114 
00115         /**
00116          * Label to be used in usage description.  Normally set to
00117          * "required", but can be changed when necessary.
00118          */
00119         std::string _requireLabel;
00120 
00121         /**
00122          * Indicates whether a value is required for the argument.
00123          * Note that the value may be required but the argument/value
00124          * combination may not be, as specified by _required.
00125          */
00126         bool _valueRequired;
00127 
00128         /**
00129          * Indicates whether the argument has been set.
00130          * Indicates that a value on the command line has matched the
00131          * name/flag of this argument and the values have been set accordingly.
00132          */
00133         bool _alreadySet;
00134 
00135         /**
00136          * A pointer to a vistitor object.
00137          * The visitor allows special handling to occur as soon as the
00138          * argument is matched.  This defaults to NULL and should not
00139          * be used unless absolutely necessary.
00140          */
00141         Visitor* _visitor;
00142 
00143         /**
00144          * Whether this argument can be ignored, if desired.
00145          */
00146         bool _ignoreable;
00147 
00148         /**
00149          * Indicates that the arg was set as part of an XOR and not on the
00150          * command line.
00151          */
00152         bool _xorSet;
00153 
00154         bool _acceptsMultipleValues;
00155 
00156         /**
00157          * Performs the special handling described by the Vistitor.
00158          */
00159         void _checkWithVisitor() const;
00160 
00161         /**
00162          * Primary constructor. YOU (yes you) should NEVER construct an Arg
00163          * directly, this is a base class that is extended by various children
00164          * that are meant to be used.  Use SwitchArg, ValueArg, MultiArg,
00165          * UnlabeledValueArg, or UnlabeledMultiArg instead.
00166          *
00167          * \param flag - The flag identifying the argument.
00168          * \param name - The name identifying the argument.
00169          * \param desc - The description of the argument, used in the usage.
00170          * \param req - Whether the argument is required.
00171          * \param valreq - Whether the a value is required for the argument.
00172          * \param v - The visitor checked by the argument. Defaults to NULL.
00173          */
00174         Arg( const std::string& flag,
00175              const std::string& name,
00176              const std::string& desc,
00177              bool req,
00178              bool valreq,
00179              Visitor* v = NULL );
00180 
00181     public:
00182         /**
00183          * Destructor.
00184          */
00185         virtual ~Arg();
00186 
00187         /**
00188          * Adds this to the specified list of Args.
00189          * \param argList - The list to add this to.
00190          */
00191         virtual void addToList( std::list<Arg*>& argList ) const;
00192 
00193         /**
00194          * Begin ignoring arguments since the "--" argument was specified.
00195          */
00196         static void beginIgnoring() { ignoreRestRef() = true; }
00197 
00198         /**
00199          * Stop ignoring arguments. Required by the BASIS test driver!
00200          */
00201         static void stopIgnoring() { ignoreRestRef() = false; }
00202 
00203         /**
00204          * Whether to ignore the rest.
00205          */
00206         static bool ignoreRest() { return ignoreRestRef(); }
00207 
00208         /**
00209          * The delimiter that separates an argument flag/name from the
00210          * value.
00211          */
00212         static char delimiter() { return delimiterRef(); }
00213 
00214         /**
00215          * The char used as a place holder when SwitchArgs are combined.
00216          * Currently set to the bell char (ASCII 7).
00217          */
00218         static char blankChar() { return (char)7; }
00219 
00220         /**
00221          * The char that indicates the beginning of a flag.  Defaults to '-', but
00222          * clients can define TCLAP_FLAGSTARTCHAR to override.
00223          */
00224 #ifndef TCLAP_FLAGSTARTCHAR
00225 #define TCLAP_FLAGSTARTCHAR '-'
00226 #endif
00227         static char flagStartChar() { return TCLAP_FLAGSTARTCHAR; }
00228 
00229         /**
00230          * The sting that indicates the beginning of a flag.  Defaults to "-", but
00231          * clients can define TCLAP_FLAGSTARTSTRING to override. Should be the same
00232          * as TCLAP_FLAGSTARTCHAR.
00233          */
00234 #ifndef TCLAP_FLAGSTARTSTRING
00235 #define TCLAP_FLAGSTARTSTRING "-"
00236 #endif
00237         static const std::string flagStartString() { return TCLAP_FLAGSTARTSTRING; }
00238 
00239         /**
00240          * The sting that indicates the beginning of a name.  Defaults to "--", but
00241          *  clients can define TCLAP_NAMESTARTSTRING to override.
00242          */
00243 #ifndef TCLAP_NAMESTARTSTRING
00244 #define TCLAP_NAMESTARTSTRING "--"
00245 #endif
00246         static const std::string nameStartString() { return TCLAP_NAMESTARTSTRING; }
00247 
00248         /**
00249          * The name used to identify the ignore rest argument.
00250          */
00251         static const std::string ignoreNameString() { return "ignore_rest"; }
00252 
00253         /**
00254          * Sets the delimiter for all arguments.
00255          * \param c - The character that delimits flags/names from values.
00256          */
00257         static void setDelimiter( char c ) { delimiterRef() = c; }
00258 
00259         /**
00260          * Pure virtual method meant to handle the parsing and value assignment
00261          * of the string on the command line.
00262          * \param i - Pointer the the current argument in the list.
00263          * \param args - Mutable list of strings. What is
00264          * passed in from main.
00265          */
00266         virtual bool processArg(int *i, std::vector<std::string>& args) = 0;
00267 
00268         /**
00269          * Operator ==.
00270          * Equality operator. Must be virtual to handle unlabeled args.
00271          * \param a - The Arg to be compared to this.
00272          */
00273         virtual bool operator==(const Arg& a) const;
00274 
00275         /**
00276          * Returns the argument flag.
00277          */
00278         const std::string& getFlag() const;
00279 
00280         /**
00281          * Returns the argument name.
00282          */
00283         const std::string& getName() const;
00284 
00285         /**
00286          * Returns the argument description.
00287          */
00288         std::string getDescription() const;
00289 
00290         /**
00291          * Indicates whether the argument is required.
00292          */
00293         virtual bool isRequired() const;
00294 
00295         /**
00296          * Sets _required to true. This is used by the XorHandler.
00297          * You really have no reason to ever use it.
00298          */
00299         void forceRequired();
00300 
00301         /**
00302          * Sets the _alreadySet value to true.  This is used by the XorHandler.
00303          * You really have no reason to ever use it.
00304          */
00305         void xorSet();
00306 
00307         /**
00308          * Indicates whether a value must be specified for argument.
00309          */
00310         bool isValueRequired() const;
00311 
00312         /**
00313          * Indicates whether the argument has already been set.  Only true
00314          * if the arg has been matched on the command line.
00315          */
00316         bool isSet() const;
00317 
00318         /**
00319          * Indicates whether the argument can be ignored, if desired.
00320          */
00321         bool isIgnoreable() const;
00322 
00323         /**
00324          * A method that tests whether a string matches this argument.
00325          * This is generally called by the processArg() method.  This
00326          * method could be re-implemented by a child to change how
00327          * arguments are specified on the command line.
00328          * \param s - The string to be compared to the flag/name to determine
00329          * whether the arg matches.
00330          */
00331         virtual bool argMatches( const std::string& s ) const;
00332 
00333         /**
00334          * Returns a simple string representation of the argument.
00335          * Primarily for debugging.
00336          */
00337         virtual std::string toString() const;
00338 
00339         /**
00340          * Returns a short ID for the usage.
00341          * \param valueId - The value used in the id.
00342          */
00343         virtual std::string shortID( const std::string& valueId = "val" ) const;
00344 
00345         /**
00346          * Returns a long ID for the usage.
00347          * \param valueId - The value used in the id.
00348          */
00349         virtual std::string longID( const std::string& valueId = "val" ) const;
00350 
00351         /**
00352          * Trims a value off of the flag.
00353          * \param flag - The string from which the flag and value will be
00354          * trimmed. Contains the flag once the value has been trimmed.
00355          * \param value - Where the value trimmed from the string will
00356          * be stored.
00357          */
00358         virtual void trimFlag( std::string& flag, std::string& value ) const;
00359 
00360         /**
00361          * Checks whether a given string has blank chars, indicating that
00362          * it is a combined SwitchArg.  If so, return true, otherwise return
00363          * false.
00364          * \param s - string to be checked.
00365          */
00366         bool _hasBlanks( const std::string& s ) const;
00367 
00368         /**
00369          * Sets the requireLabel. Used by XorHandler.  You shouldn't ever
00370          * use this.
00371          * \param s - Set the requireLabel to this value.
00372          */
00373         void setRequireLabel( const std::string& s );
00374 
00375         /**
00376          * Used for MultiArgs and XorHandler to determine whether args
00377          * can still be set.
00378          */
00379         virtual bool allowMore();
00380 
00381         /**
00382          * Use by output classes to determine whether an Arg accepts
00383          * multiple values.
00384          */
00385         virtual bool acceptsMultipleValues();
00386 
00387         /**
00388          * Clears the Arg object and allows it to be reused by new
00389          * command lines.
00390          */
00391          virtual void reset();
00392 };
00393 
00394 /**
00395  * Typedef of an Arg list iterator.
00396  */
00397 typedef std::list<Arg*>::iterator ArgListIterator;
00398 
00399 /**
00400  * Typedef of an Arg vector iterator.
00401  */
00402 typedef std::vector<Arg*>::iterator ArgVectorIterator;
00403 
00404 /**
00405  * Typedef of a Visitor list iterator.
00406  */
00407 typedef std::list<Visitor*>::iterator VisitorListIterator;
00408 
00409 /*
00410  * Extract a value of type T from it's string representation contained
00411  * in strVal. The ValueLike parameter used to select the correct
00412  * specialization of ExtractValue depending on the value traits of T.
00413  * ValueLike traits use operator>> to assign the value from strVal.
00414  */
00415 template<typename T> void
00416 ExtractValue(T &destVal, const std::string& strVal, ValueLike vl)
00417 {
00418     static_cast<void>(vl); // Avoid warning about unused vl
00419     std::istringstream is(strVal);
00420 
00421     int valuesRead = 0;
00422     while ( is.good() ) {
00423     if ( is.peek() != EOF )
00424 #ifdef TCLAP_SETBASE_ZERO
00425         is >> std::setbase(0) >> destVal;
00426 #else
00427         is >> destVal;
00428 #endif
00429     else
00430         break;
00431 
00432     valuesRead++;
00433     }
00434 
00435     if ( is.fail() )
00436     throw( ArgParseException("Couldn't read argument value "
00437                  "from string '" + strVal + "'"));
00438 
00439 
00440     if ( valuesRead > 1 )
00441     throw( ArgParseException("More than one valid value parsed from "
00442                  "string '" + strVal + "'"));
00443 
00444 }
00445 
00446 /*
00447  * Extract a value of type T from it's string representation contained
00448  * in strVal. The ValueLike parameter used to select the correct
00449  * specialization of ExtractValue depending on the value traits of T.
00450  * StringLike uses assignment (operator=) to assign from strVal.
00451  */
00452 template<typename T> void
00453 ExtractValue(T &destVal, const std::string& strVal, StringLike sl)
00454 {
00455     static_cast<void>(sl); // Avoid warning about unused sl
00456     SetString(destVal, strVal);
00457 }
00458 
00459 //////////////////////////////////////////////////////////////////////
00460 //BEGIN Arg.cpp
00461 //////////////////////////////////////////////////////////////////////
00462 
00463 inline Arg::Arg(const std::string& flag,
00464          const std::string& name,
00465          const std::string& desc,
00466          bool req,
00467          bool valreq,
00468          Visitor* v) :
00469   _flag(flag),
00470   _name(name),
00471   _description(desc),
00472   _required(req),
00473   _requireLabel("required"),
00474   _valueRequired(valreq),
00475   _alreadySet(false),
00476   _visitor( v ),
00477   _ignoreable(true),
00478   _xorSet(false),
00479   _acceptsMultipleValues(false)
00480 {
00481     if ( _flag.length() > 1 )
00482         throw(SpecificationException(
00483                 "Argument flag can only be one character long", toString() ) );
00484 
00485     if ( _name != ignoreNameString() &&
00486          ( _flag == Arg::flagStartString() ||
00487            _flag == Arg::nameStartString() ||
00488            _flag == " " ) )
00489         throw(SpecificationException("Argument flag cannot be either '" +
00490                             Arg::flagStartString() + "' or '" +
00491                             Arg::nameStartString() + "' or a space.",
00492                             toString() ) );
00493 
00494     if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) ||
00495          ( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) ||
00496          ( _name.find( " ", 0 ) != std::string::npos ) )
00497         throw(SpecificationException("Argument name begin with either '" +
00498                             Arg::flagStartString() + "' or '" +
00499                             Arg::nameStartString() + "' or space.",
00500                             toString() ) );
00501 
00502 }
00503 
00504 inline Arg::~Arg() { }
00505 
00506 inline std::string Arg::shortID( const std::string& valueId ) const
00507 {
00508     std::string id = "";
00509 
00510     if ( _flag != "" )
00511         id = Arg::flagStartString() + _flag;
00512     else
00513         id = Arg::nameStartString() + _name;
00514 
00515     if ( _valueRequired )
00516         id += std::string( 1, Arg::delimiter() ) + "<" + valueId  + ">";
00517 
00518     if ( !_required )
00519         id = "[" + id + "]";
00520 
00521     return id;
00522 }
00523 
00524 inline std::string Arg::longID( const std::string& valueId ) const
00525 {
00526     std::string id = "";
00527 
00528     if ( _flag != "" )
00529     {
00530         id += Arg::flagStartString() + _flag;
00531 
00532         if ( _valueRequired )
00533             id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
00534 
00535         id += ",  ";
00536     }
00537 
00538     id += Arg::nameStartString() + _name;
00539 
00540     if ( _valueRequired )
00541         id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
00542 
00543     return id;
00544 
00545 }
00546 
00547 inline bool Arg::operator==(const Arg& a) const
00548 {
00549     if ( ( _flag != "" && _flag == a._flag ) || _name == a._name)
00550         return true;
00551     else
00552         return false;
00553 }
00554 
00555 inline std::string Arg::getDescription() const
00556 {
00557     std::string desc = "";
00558     if ( _required )
00559         desc = "(" + _requireLabel + ")  ";
00560 
00561 //  if ( _valueRequired )
00562 //      desc += "(value required)  ";
00563 
00564     desc += _description;
00565     return desc;
00566 }
00567 
00568 inline const std::string& Arg::getFlag() const { return _flag; }
00569 
00570 inline const std::string& Arg::getName() const { return _name; }
00571 
00572 inline bool Arg::isRequired() const { return _required; }
00573 
00574 inline bool Arg::isValueRequired() const { return _valueRequired; }
00575 
00576 inline bool Arg::isSet() const
00577 {
00578     if ( _alreadySet && !_xorSet )
00579         return true;
00580     else
00581         return false;
00582 }
00583 
00584 inline bool Arg::isIgnoreable() const { return _ignoreable; }
00585 
00586 inline void Arg::setRequireLabel( const std::string& s)
00587 {
00588     _requireLabel = s;
00589 }
00590 
00591 inline bool Arg::argMatches( const std::string& argFlag ) const
00592 {
00593     if ( ( argFlag == Arg::flagStartString() + _flag && _flag != "" ) ||
00594            argFlag == Arg::nameStartString() + _name )
00595         return true;
00596     else
00597         return false;
00598 }
00599 
00600 inline std::string Arg::toString() const
00601 {
00602     std::string s = "";
00603 
00604     if ( _flag != "" )
00605         s += Arg::flagStartString() + _flag + " ";
00606 
00607     s += "(" + Arg::nameStartString() + _name + ")";
00608 
00609     return s;
00610 }
00611 
00612 inline void Arg::_checkWithVisitor() const
00613 {
00614     if ( _visitor != NULL )
00615         _visitor->visit();
00616 }
00617 
00618 /**
00619  * Implementation of trimFlag.
00620  */
00621 inline void Arg::trimFlag(std::string& flag, std::string& value) const
00622 {
00623     int stop = 0;
00624     for ( int i = 0; static_cast<unsigned int>(i) < flag.length(); i++ )
00625         if ( flag[i] == Arg::delimiter() )
00626         {
00627             stop = i;
00628             break;
00629         }
00630 
00631     if ( stop > 1 )
00632     {
00633         value = flag.substr(stop+1);
00634         flag = flag.substr(0,stop);
00635     }
00636 
00637 }
00638 
00639 /**
00640  * Implementation of _hasBlanks.
00641  */
00642 inline bool Arg::_hasBlanks( const std::string& s ) const
00643 {
00644     for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
00645         if ( s[i] == Arg::blankChar() )
00646             return true;
00647 
00648     return false;
00649 }
00650 
00651 inline void Arg::forceRequired()
00652 {
00653     _required = true;
00654 }
00655 
00656 inline void Arg::xorSet()
00657 {
00658     _alreadySet = true;
00659     _xorSet = true;
00660 }
00661 
00662 /**
00663  * Overridden by Args that need to added to the end of the list.
00664  */
00665 inline void Arg::addToList( std::list<Arg*>& argList ) const
00666 {
00667     argList.push_front( const_cast<Arg*>(this) );
00668 }
00669 
00670 inline bool Arg::allowMore()
00671 {
00672     return false;
00673 }
00674 
00675 inline bool Arg::acceptsMultipleValues()
00676 {
00677     return _acceptsMultipleValues;
00678 }
00679 
00680 inline void Arg::reset()
00681 {
00682     _xorSet = false;
00683     _alreadySet = false;
00684 }
00685 
00686 //////////////////////////////////////////////////////////////////////
00687 //END Arg.cpp
00688 //////////////////////////////////////////////////////////////////////
00689 
00690 } //namespace TCLAP
00691 
00692 #endif
00693