tclap  1.2.1
Arg.h
Go to the documentation of this file.
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 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #else
00031 #define HAVE_SSTREAM
00032 #endif
00033 
00034 #include <string>
00035 #include <vector>
00036 #include <list>
00037 #include <iostream>
00038 #include <iomanip>
00039 #include <cstdio>
00040 
00041 #if defined(HAVE_SSTREAM)
00042 #include <sstream>
00043 typedef std::istringstream istringstream;
00044 #elif defined(HAVE_STRSTREAM)
00045 #include <strstream>
00046 typedef std::istrstream istringstream;
00047 #else
00048 #error "Need a stringstream (sstream or strstream) to compile!"
00049 #endif
00050 
00051 #include <tclap/ArgException.h>
00052 #include <tclap/Visitor.h>
00053 #include <tclap/CmdLineInterface.h>
00054 #include <tclap/ArgTraits.h>
00055 #include <tclap/StandardTraits.h>
00056 
00057 namespace TCLAP {
00058 
00064 class Arg
00065 {
00066     private:
00070         Arg(const Arg& rhs);
00071 
00075         Arg& operator=(const Arg& rhs);
00076 
00080         static bool& ignoreRestRef() { static bool ign = false; return ign; }
00081 
00086         static char& delimiterRef() { static char delim = ' '; return delim; }
00087 
00088     protected:
00089 
00098         std::string _flag;
00099 
00107         std::string _name;
00108 
00112         std::string _description;
00113 
00117         bool _required;
00118 
00123         std::string _requireLabel;
00124 
00130         bool _valueRequired;
00131 
00137         bool _alreadySet;
00138 
00145         Visitor* _visitor;
00146 
00150         bool _ignoreable;
00151 
00156         bool _xorSet;
00157 
00158         bool _acceptsMultipleValues;
00159 
00163         void _checkWithVisitor() const;
00164 
00178         Arg( const std::string& flag,
00179              const std::string& name,
00180              const std::string& desc,
00181              bool req,
00182              bool valreq,
00183              Visitor* v = NULL );
00184 
00185     public:
00189         virtual ~Arg();
00190 
00195         virtual void addToList( std::list<Arg*>& argList ) const;
00196 
00200         static void beginIgnoring() { ignoreRestRef() = true; }
00201 
00205         static bool ignoreRest() { return ignoreRestRef(); }
00206 
00211         static char delimiter() { return delimiterRef(); }
00212 
00217         static char blankChar() { return (char)7; }
00218 
00223 #ifndef TCLAP_FLAGSTARTCHAR
00224 #define TCLAP_FLAGSTARTCHAR '-'
00225 #endif
00226         static char flagStartChar() { return TCLAP_FLAGSTARTCHAR; }
00227 
00233 #ifndef TCLAP_FLAGSTARTSTRING
00234 #define TCLAP_FLAGSTARTSTRING "-"
00235 #endif
00236         static const std::string flagStartString() { return TCLAP_FLAGSTARTSTRING; }
00237 
00242 #ifndef TCLAP_NAMESTARTSTRING
00243 #define TCLAP_NAMESTARTSTRING "--"
00244 #endif
00245         static const std::string nameStartString() { return TCLAP_NAMESTARTSTRING; }
00246 
00250         static const std::string ignoreNameString() { return "ignore_rest"; }
00251 
00256         static void setDelimiter( char c ) { delimiterRef() = c; }
00257 
00265         virtual bool processArg(int *i, std::vector<std::string>& args) = 0;
00266 
00272         virtual bool operator==(const Arg& a) const;
00273 
00277         const std::string& getFlag() const;
00278 
00282         const std::string& getName() const;
00283 
00287         std::string getDescription() const;
00288 
00292         virtual bool isRequired() const;
00293 
00298         void forceRequired();
00299 
00304         void xorSet();
00305 
00309         bool isValueRequired() const;
00310 
00315         bool isSet() const;
00316 
00320         bool isIgnoreable() const;
00321 
00330         virtual bool argMatches( const std::string& s ) const;
00331 
00336         virtual std::string toString() const;
00337 
00342         virtual std::string shortID( const std::string& valueId = "val" ) const;
00343 
00348         virtual std::string longID( const std::string& valueId = "val" ) const;
00349 
00357         virtual void trimFlag( std::string& flag, std::string& value ) const;
00358 
00365         bool _hasBlanks( const std::string& s ) const;
00366 
00372         void setRequireLabel( const std::string& s );
00373 
00378         virtual bool allowMore();
00379 
00384         virtual bool acceptsMultipleValues();
00385 
00390          virtual void reset();
00391 };
00392 
00396 typedef std::list<Arg*>::iterator ArgListIterator;
00397 
00401 typedef std::vector<Arg*>::iterator ArgVectorIterator;
00402 
00406 typedef std::list<Visitor*>::iterator VisitorListIterator;
00407 
00408 /*
00409  * Extract a value of type T from it's string representation contained
00410  * in strVal. The ValueLike parameter used to select the correct
00411  * specialization of ExtractValue depending on the value traits of T.
00412  * ValueLike traits use operator>> to assign the value from strVal.
00413  */
00414 template<typename T> void
00415 ExtractValue(T &destVal, const std::string& strVal, ValueLike vl)
00416 {
00417     static_cast<void>(vl); // Avoid warning about unused vl
00418     std::istringstream is(strVal);
00419 
00420     int valuesRead = 0;
00421     while ( is.good() ) {
00422     if ( is.peek() != EOF )
00423 #ifdef TCLAP_SETBASE_ZERO
00424         is >> std::setbase(0) >> destVal;
00425 #else
00426         is >> destVal;
00427 #endif
00428     else
00429         break;
00430 
00431     valuesRead++;
00432     }
00433 
00434     if ( is.fail() )
00435     throw( ArgParseException("Couldn't read argument value "
00436                  "from string '" + strVal + "'"));
00437 
00438 
00439     if ( valuesRead > 1 )
00440     throw( ArgParseException("More than one valid value parsed from "
00441                  "string '" + strVal + "'"));
00442 
00443 }
00444 
00445 /*
00446  * Extract a value of type T from it's string representation contained
00447  * in strVal. The ValueLike parameter used to select the correct
00448  * specialization of ExtractValue depending on the value traits of T.
00449  * StringLike uses assignment (operator=) to assign from strVal.
00450  */
00451 template<typename T> void
00452 ExtractValue(T &destVal, const std::string& strVal, StringLike sl)
00453 {
00454     static_cast<void>(sl); // Avoid warning about unused sl
00455     SetString(destVal, strVal);
00456 }
00457 
00459 //BEGIN Arg.cpp
00461 
00462 inline Arg::Arg(const std::string& flag,
00463          const std::string& name,
00464          const std::string& desc,
00465          bool req,
00466          bool valreq,
00467          Visitor* v) :
00468   _flag(flag),
00469   _name(name),
00470   _description(desc),
00471   _required(req),
00472   _requireLabel("required"),
00473   _valueRequired(valreq),
00474   _alreadySet(false),
00475   _visitor( v ),
00476   _ignoreable(true),
00477   _xorSet(false),
00478   _acceptsMultipleValues(false)
00479 {
00480     if ( _flag.length() > 1 )
00481         throw(SpecificationException(
00482                 "Argument flag can only be one character long", toString() ) );
00483 
00484     if ( _name != ignoreNameString() &&
00485          ( _flag == Arg::flagStartString() ||
00486            _flag == Arg::nameStartString() ||
00487            _flag == " " ) )
00488         throw(SpecificationException("Argument flag cannot be either '" +
00489                             Arg::flagStartString() + "' or '" +
00490                             Arg::nameStartString() + "' or a space.",
00491                             toString() ) );
00492 
00493     if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) ||
00494          ( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) ||
00495          ( _name.find( " ", 0 ) != std::string::npos ) )
00496         throw(SpecificationException("Argument name begin with either '" +
00497                             Arg::flagStartString() + "' or '" +
00498                             Arg::nameStartString() + "' or space.",
00499                             toString() ) );
00500 
00501 }
00502 
00503 inline Arg::~Arg() { }
00504 
00505 inline std::string Arg::shortID( const std::string& valueId ) const
00506 {
00507     std::string id = "";
00508 
00509     if ( _flag != "" )
00510         id = Arg::flagStartString() + _flag;
00511     else
00512         id = Arg::nameStartString() + _name;
00513 
00514     if ( _valueRequired )
00515         id += std::string( 1, Arg::delimiter() ) + "<" + valueId  + ">";
00516 
00517     if ( !_required )
00518         id = "[" + id + "]";
00519 
00520     return id;
00521 }
00522 
00523 inline std::string Arg::longID( const std::string& valueId ) const
00524 {
00525     std::string id = "";
00526 
00527     if ( _flag != "" )
00528     {
00529         id += Arg::flagStartString() + _flag;
00530 
00531         if ( _valueRequired )
00532             id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
00533 
00534         id += ",  ";
00535     }
00536 
00537     id += Arg::nameStartString() + _name;
00538 
00539     if ( _valueRequired )
00540         id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
00541 
00542     return id;
00543 
00544 }
00545 
00546 inline bool Arg::operator==(const Arg& a) const
00547 {
00548     if ( ( _flag != "" && _flag == a._flag ) || _name == a._name)
00549         return true;
00550     else
00551         return false;
00552 }
00553 
00554 inline std::string Arg::getDescription() const
00555 {
00556     std::string desc = "";
00557     if ( _required )
00558         desc = "(" + _requireLabel + ")  ";
00559 
00560 //  if ( _valueRequired )
00561 //      desc += "(value required)  ";
00562 
00563     desc += _description;
00564     return desc;
00565 }
00566 
00567 inline const std::string& Arg::getFlag() const { return _flag; }
00568 
00569 inline const std::string& Arg::getName() const { return _name; }
00570 
00571 inline bool Arg::isRequired() const { return _required; }
00572 
00573 inline bool Arg::isValueRequired() const { return _valueRequired; }
00574 
00575 inline bool Arg::isSet() const
00576 {
00577     if ( _alreadySet && !_xorSet )
00578         return true;
00579     else
00580         return false;
00581 }
00582 
00583 inline bool Arg::isIgnoreable() const { return _ignoreable; }
00584 
00585 inline void Arg::setRequireLabel( const std::string& s)
00586 {
00587     _requireLabel = s;
00588 }
00589 
00590 inline bool Arg::argMatches( const std::string& argFlag ) const
00591 {
00592     if ( ( argFlag == Arg::flagStartString() + _flag && _flag != "" ) ||
00593            argFlag == Arg::nameStartString() + _name )
00594         return true;
00595     else
00596         return false;
00597 }
00598 
00599 inline std::string Arg::toString() const
00600 {
00601     std::string s = "";
00602 
00603     if ( _flag != "" )
00604         s += Arg::flagStartString() + _flag + " ";
00605 
00606     s += "(" + Arg::nameStartString() + _name + ")";
00607 
00608     return s;
00609 }
00610 
00611 inline void Arg::_checkWithVisitor() const
00612 {
00613     if ( _visitor != NULL )
00614         _visitor->visit();
00615 }
00616 
00620 inline void Arg::trimFlag(std::string& flag, std::string& value) const
00621 {
00622     int stop = 0;
00623     for ( int i = 0; static_cast<unsigned int>(i) < flag.length(); i++ )
00624         if ( flag[i] == Arg::delimiter() )
00625         {
00626             stop = i;
00627             break;
00628         }
00629 
00630     if ( stop > 1 )
00631     {
00632         value = flag.substr(stop+1);
00633         flag = flag.substr(0,stop);
00634     }
00635 
00636 }
00637 
00641 inline bool Arg::_hasBlanks( const std::string& s ) const
00642 {
00643     for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
00644         if ( s[i] == Arg::blankChar() )
00645             return true;
00646 
00647     return false;
00648 }
00649 
00650 inline void Arg::forceRequired()
00651 {
00652     _required = true;
00653 }
00654 
00655 inline void Arg::xorSet()
00656 {
00657     _alreadySet = true;
00658     _xorSet = true;
00659 }
00660 
00664 inline void Arg::addToList( std::list<Arg*>& argList ) const
00665 {
00666     argList.push_front( const_cast<Arg*>(this) );
00667 }
00668 
00669 inline bool Arg::allowMore()
00670 {
00671     return false;
00672 }
00673 
00674 inline bool Arg::acceptsMultipleValues()
00675 {
00676     return _acceptsMultipleValues;
00677 }
00678 
00679 inline void Arg::reset()
00680 {
00681     _xorSet = false;
00682     _alreadySet = false;
00683 }
00684 
00686 //END Arg.cpp
00688 
00689 } //namespace TCLAP
00690 
00691 #endif
00692