MultiArg.h

Go to the documentation of this file.
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 TCLAP_MULTIPLE_ARGUMENT_H
00024 #define TCLAP_MULTIPLE_ARGUMENT_H
00025 
00026 #include <string>
00027 #include <vector>
00028 
00029 #include <tclap/Arg.h>
00030 
00031 #ifdef HAVE_CONFIG_H
00032 #include <config.h>
00033 #else
00034 #define HAVE_SSTREAM
00035 #endif
00036 
00037 #if defined(HAVE_SSTREAM)
00038 #include <sstream>
00039 #elif defined(HAVE_STRSTREAM)
00040 #include <strstream>
00041 #else
00042 #error "Need a stringstream (sstream or strstream) to compile!"
00043 #endif
00044 
00045 namespace TCLAP {
00046 
00047 template<class T> class MultiArg;
00048 
00049 namespace MULTI_ARG_HELPER {
00050 
00051 enum Error_e { EXTRACT_FAILURE = 1000, EXTRACT_TOO_MANY };
00052 
00062 template<class T>
00063 class ValueExtractor 
00064 {
00065      friend class MultiArg<T>;
00066   
00067      private:
00068 
00073           std::vector<T> &_values;
00074   
00079           ValueExtractor(std::vector<T> &values) : _values(values) {}
00080   
00086           int extractValue( const std::string& val ) 
00087           {
00088                T temp;
00089 
00090 #if defined(HAVE_SSTREAM)
00091                std::istringstream is(val);
00092 #elif defined(HAVE_STRSTREAM)
00093                std::istrstream is(val.c_str());
00094 #else
00095 #error "Need a stringstream (sstream or strstream) to compile!"
00096 #endif
00097 
00098                int valuesRead = 0;
00099     
00100                while ( is.good() ) 
00101                {
00102                     if ( is.peek() != EOF )
00103                          is >> temp; 
00104                     else
00105                          break;
00106       
00107                     valuesRead++;
00108                }         
00109     
00110                if ( is.fail() )
00111                     return EXTRACT_FAILURE;
00112     
00113                if ( valuesRead > 1 )
00114                     return EXTRACT_TOO_MANY;
00115     
00116                _values.push_back(temp);
00117     
00118                return 0;
00119           } 
00120 };
00121 
00127 template<>
00128 class ValueExtractor<std::string> 
00129 {
00130      friend class MultiArg<std::string>;
00131 
00132      private:
00133 
00138         std::vector<std::string> &_values;
00139   
00144         ValueExtractor(std::vector<std::string> &values) : _values(values) {}
00145 
00151         int extractValue( const std::string& val ) 
00152           {
00153             _values.push_back( val );
00154             return 0;
00155         }
00156 };
00157 
00158 } //namespace MULTI_ARG_HELPER
00159 
00165 template<class T>
00166 class MultiArg : public Arg
00167 {
00168      protected:
00169 
00173           std::vector<T> _values;
00174 
00181           std::vector<T> _allowed;
00182 
00186           std::string _typeDesc;
00187 
00194           void _extractValue( const std::string& val );
00195 
00200           void _checkAllowed( const std::string& val );
00201 
00202      public:
00203 
00221           MultiArg( const std::string& flag,
00222                   const std::string& name,
00223                   const std::string& desc,
00224                   bool req,
00225                   const std::string& typeDesc,
00226                   Visitor* v = NULL);
00227 
00246           MultiArg( const std::string& flag, 
00247                   const std::string& name,
00248                   const std::string& desc,
00249                   bool req,
00250                   const std::string& typeDesc,
00251                   CmdLineInterface& parser,
00252                   Visitor* v = NULL );
00253 
00269           MultiArg( const std::string& flag,
00270                   const std::string& name,
00271                   const std::string& desc,
00272                   bool req,
00273                   const std::vector<T>& allowed,
00274                   Visitor* v = NULL );
00275             
00292           MultiArg( const std::string& flag, 
00293                   const std::string& name,
00294                   const std::string& desc,
00295                   bool req,
00296                   const std::vector<T>& allowed,
00297                   CmdLineInterface& parser,
00298                   Visitor* v = NULL );
00299             
00308           virtual bool processArg(int* i, std::vector<std::string>& args); 
00309 
00314           const std::vector<T>& getValue();
00315 
00320           virtual std::string shortID(const std::string& val="val") const;
00321 
00326           virtual std::string longID(const std::string& val="val") const;
00327 
00332           virtual bool isRequired() const;
00333 
00334      private:
00335 
00339           void allowedInit();
00340 };
00341 
00345 template<class T>
00346 void MultiArg<T>::allowedInit()
00347 {
00348      for ( unsigned int i = 0; i < _allowed.size(); i++ )
00349      {
00350 
00351 #if defined(HAVE_SSTREAM)
00352           std::ostringstream os;
00353 #elif defined(HAVE_STRSTREAM)
00354           std::ostrstream os;
00355 #else
00356 #error "Need a stringstream (sstream or strstream) to compile!"
00357 #endif
00358 
00359           os << _allowed[i];
00360 
00361           std::string temp( os.str() );
00362 
00363           if ( i > 0 )
00364                _typeDesc += "|";
00365      
00366           _typeDesc += temp;
00367      }
00368 }
00369 
00373 template<class T>
00374 MultiArg<T>::MultiArg(const std::string& flag, 
00375                       const std::string& name,
00376                       const std::string& desc,
00377                       bool req,
00378                       const std::string& typeDesc,
00379                       Visitor* v)
00380 : Arg( flag, name, desc, req, true, v ),
00381   _typeDesc( typeDesc )
00382 { }
00383 
00384 template<class T>
00385 MultiArg<T>::MultiArg(const std::string& flag, 
00386                       const std::string& name,
00387                       const std::string& desc,
00388                       bool req,
00389                       const std::string& typeDesc,
00390                       CmdLineInterface& parser,
00391                       Visitor* v)
00392 : Arg( flag, name, desc, req, true, v ),
00393   _typeDesc( typeDesc )
00394 { 
00395      parser.add( this );
00396 }
00397 
00401 template<class T>
00402 MultiArg<T>::MultiArg(const std::string& flag, 
00403                       const std::string& name,
00404                       const std::string& desc,
00405                       bool req,
00406                       const std::vector<T>& allowed,
00407                       Visitor* v)
00408 : Arg( flag, name, desc, req, true, v ),
00409   _allowed( allowed )
00410 { 
00411      allowedInit();
00412 }
00413 
00414 template<class T>
00415 MultiArg<T>::MultiArg(const std::string& flag, 
00416                       const std::string& name,
00417                       const std::string& desc,
00418                       bool req,
00419                       const std::vector<T>& allowed,
00420                       CmdLineInterface& parser,
00421                       Visitor* v)
00422 : Arg( flag, name, desc, req, true, v ),
00423   _allowed( allowed )
00424 { 
00425      allowedInit();
00426      parser.add( this );
00427 }
00428 
00432 template<class T>
00433 const std::vector<T>& MultiArg<T>::getValue() { return _values; }
00434 
00438 template<class T>
00439 bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args) 
00440 {
00441      if ( _ignoreable && Arg::ignoreRest() )
00442           return false;
00443 
00444      if ( _hasBlanks( args[*i] ) )
00445           return false;
00446 
00447      std::string flag = args[*i];
00448      std::string value = "";
00449 
00450      trimFlag( flag, value );
00451 
00452      if ( argMatches( flag ) )
00453      {
00454           if ( Arg::delimiter() != ' ' && value == "" )
00455                throw( ArgParseException( 
00456                           "Couldn't find delimiter for this argument!",
00457                             toString() ) );
00458 
00459           if ( value == "" )
00460           {
00461                (*i)++;
00462                if ( (unsigned int)*i < args.size() )
00463                     _extractValue( args[*i] );
00464                else
00465                     throw( ArgParseException("Missing a value for this argument!",
00466                                          toString() ) );
00467           }
00468           else
00469                _extractValue( value );
00470 
00471           _checkWithVisitor();
00472 
00473           return true;
00474      }
00475      else
00476           return false;
00477 }
00478 
00482 template<class T>
00483 void MultiArg<T>::_checkAllowed( const std::string& val )
00484 {
00485      if ( _allowed.size() > 0 )
00486           if ( find(_allowed.begin(),_allowed.end(),_values.back()) 
00487                  == _allowed.end() )
00488                throw( CmdLineParseException( "Couldn't find '" + val +
00489                                           "' in allowed list.", toString() ) );
00490 }
00491 
00495 template<class T>
00496 std::string MultiArg<T>::shortID(const std::string& val) const
00497 {
00498      std::string id = Arg::shortID(_typeDesc) + " ... ";
00499 
00500      return id;
00501 }
00502 
00506 template<class T>
00507 std::string MultiArg<T>::longID(const std::string& val) const
00508 {
00509      std::string id = Arg::longID(_typeDesc) + "  (accepted multiple times)";
00510 
00511      return id;
00512 }
00513 
00518 template<class T>
00519 bool MultiArg<T>::isRequired() const
00520 {
00521      if ( _required )
00522      {
00523           if ( _values.size() > 1 )
00524                return false;
00525           else
00526                return true;
00527      }
00528      else
00529           return false;
00530 
00531 }
00532 
00533 template<class T>
00534 void MultiArg<T>::_extractValue( const std::string& val ) 
00535 {
00536      MULTI_ARG_HELPER::ValueExtractor<T> ve(_values);
00537             
00538      int err = ve.extractValue(val);
00539 
00540      if ( err == MULTI_ARG_HELPER::EXTRACT_FAILURE )
00541           throw( ArgParseException("Couldn't read argument value "
00542                                  "from string '" + val + "'", toString() ) );
00543 
00544      if(err == MULTI_ARG_HELPER::EXTRACT_TOO_MANY)
00545          throw( ArgParseException("More than one valid value "
00546                                  "parsed from string '" + val + "'", 
00547                                          toString() ) );             
00548      _checkAllowed( val );
00549 }
00550           
00551 
00552 } // namespace TCLAP
00553 
00554 #endif

Generated on Sun Mar 11 15:33:24 2007 for MetalWarriors by  doxygen 1.4.7