$search
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