![]() |
VR-Link API Documentation for HLA 1.3
|
00001 /****************************************************************************** 00002 * 00003 * file: MultiArg.h 00004 * 00005 * Copyright (c) 2003, Michael E. Smoot . 00006 * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 00007 * All rights reverved. 00008 * 00009 * See the file COPYING in the top directory of this distribution for 00010 * more information. 00011 * 00012 * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 00013 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00014 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00015 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00016 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00017 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00018 * DEALINGS IN THE SOFTWARE. 00019 * 00020 *****************************************************************************/ 00021 00022 00023 #ifndef DtCmdLine_MULTIPLE_ARGUMENT_H 00024 #define DtCmdLine_MULTIPLE_ARGUMENT_H 00025 00029 00030 #include <cstdio> 00031 00032 #include <string> 00033 #include <vector> 00034 00035 #include "cmdArg.h" 00036 00037 #ifdef HAVE_CONFIG_H 00038 #include <config.h> 00039 #else 00040 #define HAVE_SSTREAM 00041 00042 #endif 00043 00044 #if defined(HAVE_SSTREAM) 00045 #include <sstream> 00046 #elif defined(HAVE_STRSTREAM) 00047 #include <strstream> 00048 #else 00049 #error "Need a stringstream (sstream or strstream) to compile!" 00050 #endif 00051 00052 #ifdef DtUSE_UTILITIES_NAMESPACE 00053 namespace DtUSE_UTILITIES_NAMESPACE 00054 { 00055 #endif 00056 00057 namespace DtCmdLine { 00058 00059 template<class T> class MultiArg; 00060 00061 namespace MULTI_ARG_HELPER { 00062 00063 enum Error_e { EXTRACT_FAILURE = 1000, EXTRACT_TOO_MANY }; 00064 00074 00075 template<class T> 00076 class ValueExtractor 00077 { 00078 friend class MultiArg<T>; 00079 00080 private: 00081 00086 std::vector<T> &_values; 00087 00092 ValueExtractor(std::vector<T> &values) : _values(values) {} 00093 00099 int extractValue( const std::string& val ) 00100 { 00101 T temp; 00102 00103 #if defined(HAVE_SSTREAM) 00104 std::istringstream is(val); 00105 #elif defined(HAVE_STRSTREAM) 00106 std::istrstream is(val.c_str()); 00107 #else 00108 #error "Need a stringstream (sstream or strstream) to compile!" 00109 #endif 00110 00111 int valuesRead = 0; 00112 00113 while ( is.good() ) 00114 { 00115 if ( is.peek() != EOF ) 00116 is >> temp; 00117 else 00118 break; 00119 00120 valuesRead++; 00121 } 00122 00123 if ( is.fail() ) 00124 return EXTRACT_FAILURE; 00125 00126 if ( valuesRead > 1 ) 00127 return EXTRACT_TOO_MANY; 00128 00129 _values.push_back(temp); 00130 00131 return 0; 00132 } 00133 }; 00134 00140 template<> 00141 class ValueExtractor<std::string> 00142 { 00143 friend class MultiArg<std::string>; 00144 00145 private: 00146 00151 std::vector<std::string> &_values; 00152 00157 ValueExtractor(std::vector<std::string> &values) : _values(values) {} 00158 00164 int extractValue( const std::string& val ) 00165 { 00166 _values.push_back( val ); 00167 return 0; 00168 } 00169 }; 00170 00171 } //namespace MULTI_ARG_HELPER 00172 00178 00179 template<class T> 00180 class MultiArg : public Arg 00181 { 00182 protected: 00183 00187 std::vector<T> _values; 00188 00195 std::vector<T> _allowed; 00196 00200 std::string _typeDesc; 00201 00208 void _extractValue( const std::string& val ); 00209 00214 void _checkAllowed( const std::string& val ); 00215 00216 public: 00217 00235 MultiArg( const std::string& flag, 00236 const std::string& name, 00237 const std::string& desc, 00238 bool req, 00239 const std::string& typeDesc, 00240 Visitor* v = NULL); 00241 00260 MultiArg( const std::string& flag, 00261 const std::string& name, 00262 const std::string& desc, 00263 bool req, 00264 const std::string& typeDesc, 00265 CmdLineInterface& parser, 00266 Visitor* v = NULL ); 00267 00283 MultiArg( const std::string& flag, 00284 const std::string& name, 00285 const std::string& desc, 00286 bool req, 00287 const std::vector<T>& allowed, 00288 Visitor* v = NULL ); 00289 00306 MultiArg( const std::string& flag, 00307 const std::string& name, 00308 const std::string& desc, 00309 bool req, 00310 const std::vector<T>& allowed, 00311 CmdLineInterface& parser, 00312 Visitor* v = NULL ); 00313 00322 virtual bool processArg(int* i, std::vector<std::string>& args); 00323 00328 const std::vector<T>& getValue() const; 00329 00334 virtual std::string shortID(const std::string& val="val") const; 00335 00340 virtual std::string longID(const std::string& val="val") const; 00341 00346 virtual bool isRequired() const; 00347 00348 private: 00349 00353 void allowedInit(); 00354 }; 00355 00359 template<class T> 00360 void MultiArg<T>::allowedInit() 00361 { 00362 for ( unsigned int i = 0; i < _allowed.size(); i++ ) 00363 { 00364 00365 #if defined(HAVE_SSTREAM) 00366 std::ostringstream os; 00367 #elif defined(HAVE_STRSTREAM) 00368 std::ostrstream os; 00369 #else 00370 #error "Need a stringstream (sstream or strstream) to compile!" 00371 #endif 00372 00373 os << _allowed[i]; 00374 00375 std::string temp( os.str() ); 00376 00377 if ( i > 0 ) 00378 _typeDesc += "|"; 00379 00380 _typeDesc += temp; 00381 } 00382 } 00383 00387 template<class T> 00388 MultiArg<T>::MultiArg(const std::string& flag, 00389 const std::string& name, 00390 const std::string& desc, 00391 bool req, 00392 const std::string& typeDesc, 00393 Visitor* v) 00394 : Arg( flag, name, desc, req, true, v ), 00395 _typeDesc( typeDesc ) 00396 { } 00397 00398 template<class T> 00399 MultiArg<T>::MultiArg(const std::string& flag, 00400 const std::string& name, 00401 const std::string& desc, 00402 bool req, 00403 const std::string& typeDesc, 00404 CmdLineInterface& parser, 00405 Visitor* v) 00406 : Arg( flag, name, desc, req, true, v ), 00407 _typeDesc( typeDesc ) 00408 { 00409 parser.add( this ); 00410 } 00411 00415 template<class T> 00416 MultiArg<T>::MultiArg(const std::string& flag, 00417 const std::string& name, 00418 const std::string& desc, 00419 bool req, 00420 const std::vector<T>& allowed, 00421 Visitor* v) 00422 : Arg( flag, name, desc, req, true, v ), 00423 _allowed( allowed ) 00424 { 00425 allowedInit(); 00426 } 00427 00428 template<class T> 00429 MultiArg<T>::MultiArg(const std::string& flag, 00430 const std::string& name, 00431 const std::string& desc, 00432 bool req, 00433 const std::vector<T>& allowed, 00434 CmdLineInterface& parser, 00435 Visitor* v) 00436 : Arg( flag, name, desc, req, true, v ), 00437 _allowed( allowed ) 00438 { 00439 allowedInit(); 00440 parser.add( this ); 00441 } 00442 00446 template<class T> 00447 const std::vector<T>& MultiArg<T>::getValue() const { return _values; } 00448 00452 template<class T> 00453 bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args) 00454 { 00455 if ( _ignoreable && Arg::ignoreRest() ) 00456 return false; 00457 00458 if ( _hasBlanks( args[*i] ) ) 00459 return false; 00460 00461 std::string flag = args[*i]; 00462 std::string value = ""; 00463 00464 trimFlag( flag, value ); 00465 00466 if ( argMatches( flag ) ) 00467 { 00468 if ( Arg::delimiter() != ' ' && value == "" ) 00469 throw( ArgParseException( 00470 "Couldn't find delimiter for this argument!", 00471 toString() ) ); 00472 00473 if ( value == "" ) 00474 { 00475 (*i)++; 00476 if ( (unsigned int)*i < args.size() ) 00477 _extractValue( args[*i] ); 00478 else 00479 throw( ArgParseException("Missing a value for this argument!", 00480 toString() ) ); 00481 } 00482 else 00483 _extractValue( value ); 00484 00485 _checkWithVisitor(); 00486 00487 return true; 00488 } 00489 else 00490 return false; 00491 } 00492 00496 template<class T> 00497 void MultiArg<T>::_checkAllowed( const std::string& val ) 00498 { 00499 if ( _allowed.size() > 0 ) 00500 if ( std::find(_allowed.begin(),_allowed.end(),_values.back()) 00501 == _allowed.end() ) 00502 throw( CmdLineParseException( "Couldn't find '" + val + 00503 "' in allowed list.", toString() ) ); 00504 } 00505 00509 template<class T> 00510 std::string MultiArg<T>::shortID(const std::string& val) const 00511 { 00512 std::string id = Arg::shortID(_typeDesc) + " ... "; 00513 00514 return id; 00515 } 00516 00520 template<class T> 00521 std::string MultiArg<T>::longID(const std::string& val) const 00522 { 00523 std::string id = Arg::longID(_typeDesc) + " (accepted multiple times)"; 00524 00525 return id; 00526 } 00527 00532 template<class T> 00533 bool MultiArg<T>::isRequired() const 00534 { 00535 if ( _required ) 00536 { 00537 if ( _values.size() > 1 ) 00538 return false; 00539 else 00540 return true; 00541 } 00542 else 00543 return false; 00544 00545 } 00546 00547 template<class T> 00548 void MultiArg<T>::_extractValue( const std::string& val ) 00549 { 00550 MULTI_ARG_HELPER::ValueExtractor<T> ve(_values); 00551 00552 int err = ve.extractValue(val); 00553 00554 if ( err == MULTI_ARG_HELPER::EXTRACT_FAILURE ) 00555 throw( ArgParseException("Couldn't read argument value " 00556 "from string '" + val + "'", toString() ) ); 00557 00558 if(err == MULTI_ARG_HELPER::EXTRACT_TOO_MANY) 00559 throw( ArgParseException("More than one valid value " 00560 "parsed from string '" + val + "'", 00561 toString() ) ); 00562 _checkAllowed( val ); 00563 } 00564 00565 00566 } 00567 00568 #ifdef DtUSE_UTILITIES_NAMESPACE 00569 } 00570 #endif 00571 00572 #endif