ArgumentParser.h

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                              SOFA :: Framework                              *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 //========================================================
00028 // Yet another command line parser. 
00029 // Francois Faure, iMAGIS-GRAVIR, May 2001
00030 //========================================================
00031 
00032 #ifndef SOFA_HELPER_ARGUMENTPARSER_H
00033 #define SOFA_HELPER_ARGUMENTPARSER_H
00034 
00035 #include <iostream>
00036 #include <stdlib.h>
00037 #include <sstream>
00038 #include <fstream>
00039 #include <string>
00040 #include <vector>
00041 #include <algorithm>
00042 #include <map>
00043 #include <list>
00044 #include <vector>
00045 
00046 namespace sofa
00047 {
00048 
00049 namespace helper
00050 {
00051 
00052 typedef std::istringstream istrstream; 
00053 
00055 class ArgumentBase
00056 {
00057 public:
00059     typedef std::string string;
00060     
00067     ArgumentBase(char s, string l, string h, bool m);
00068     
00070     virtual ~ArgumentBase();
00071 
00073     virtual bool read( std::list<std::string>& str ) = 0;
00074     
00076     virtual void printValue() const =0;
00077     
00079     void print () const;
00080 
00081     char shortName; 
00082     string longName;  
00083     string help;      
00084 
00086     bool mandatory;
00087 
00089     bool isSet;
00090     
00091 };
00092 
00093 
00094 //=========================================================================
00095 
00103 template < class T = void* >
00104 class Argument : public ArgumentBase {
00105 public:
00106     
00114     Argument( T* t, char sn, string ln, string h, bool m )
00115     : ArgumentBase(sn,ln,h,m)
00116     , ptr(t)
00117     {}
00118     
00119     inline void printValue() const ;
00120     
00121 private:
00123     T* ptr;
00124     
00125     
00129     inline bool read( std::list<std::string>& str ) {
00130         if (str.empty()) return false;
00131         std::string s = str.front();
00132         str.pop_front();
00133         istrstream istr( s.c_str() );
00134         if( ! (istr >> *ptr) ) return false;
00135         else {
00136             isSet = true;
00137             return true;
00138         }
00139     }
00140     
00141 };
00142 
00147 /*
00148 template<class TE> inline 
00149 bool Argument< std::vector<TE> >::read( std::list<std::string>& str)
00150 {
00151     if (str.empty()) return false;
00152     std::string s = str.front();
00153     str.pop_front();
00154     TE val;
00155     istrstream istr( s.c_str() );
00156     if( ! (istr >> val) ) return false;
00157     else {
00158         isSet = true;
00159         *ptr.push_back(vak);
00160         return true;
00161     }
00162 }
00163 */
00164 
00165 template<> inline 
00166 bool Argument< std::vector< std::string > >::read( std::list<std::string>& str)
00167 {
00168     if (str.empty()) return false;
00169     std::string s = str.front();
00170     str.pop_front();
00171     isSet = true;
00172     ptr->push_back(s);
00173     return true;
00174 }
00175 
00182 template<> inline 
00183 bool Argument<bool>::read( std::list<std::string>& )
00184 {
00185     *ptr = true;
00186     isSet = true;
00187     return true;
00188 }
00189 
00190 template<> inline 
00191         bool Argument<std::string>::read( std::list<std::string>& str )
00192 {
00193     if (str.empty()) return false;
00194     std::string s = str.front();
00195     str.pop_front();
00196     *ptr = s;
00197     isSet = true;
00198     return true;
00199 }
00200 
00202 template<class T> inline
00203 void Argument<T>::printValue() const {
00204     std::cout << *ptr << " ";
00205 }
00206 
00208 template<> inline
00209 void Argument<std::vector<std::string > >::printValue() const {
00210     for (unsigned int i=0;i<ptr->size();i++)
00211         std::cout << (*ptr)[i] << " ";
00212 }
00213 
00214 
00215 //========================================================================
00216 
00226 class ArgumentParser {
00228     typedef std::string string;
00230     typedef std::map< string, ArgumentBase* > Map;
00232     std::map< char, ArgumentBase* > shortName;
00234     Map longName;
00235     
00237     typedef std::map<ArgumentBase*,bool> SetMap;
00238     
00240     SetMap parameter_set;
00241     
00243     typedef std::vector<ArgumentBase*> ArgVec;
00245     ArgVec commands;
00246     
00248     std::vector<std::string>* files;
00249     
00250     // help stuff
00251     string globalHelp;    
00252     char helpShortName;   
00253     string helpLongName;  
00254 
00255 public:
00256 
00258     ArgumentParser( const string& helpstr="", char hlpShrt='h', const string& hlpLng="help" );
00259 
00261     ArgumentParser( std::vector<std::string>* files, const string& helpstr="", char hlpShrt='h', const string& hlpLng="help" );
00262 
00264     ~ArgumentParser();
00265     
00272     template<class T> inline 
00273     ArgumentParser& option( T* ptr, char sho, const char* lon, const char* help )
00274     {
00275         string sn, ln(lon), h(help); sn += sho;
00276         
00277         if( sho!=0 && shortName.find(sho) != shortName.end() ){
00278             std::cerr << "name " << sn << " already used !" << std::endl;
00279             exit( 1 );
00280         }
00281         
00282         if( ln.size()>0 && longName.find(ln) != longName.end() ){
00283             std::cerr << "name " << ln << " already used !" << std::endl;
00284             exit( 1 );
00285         }
00286         
00287         if( sho!=0 && sho == helpShortName ){
00288             std::cerr << "name " << sho << " reserved for help !" << std::endl;
00289             exit( 1 );
00290         }
00291         if( ln.size()>0 && lon == helpLongName ){
00292             std::cerr << "name " << lon << " reserved for help !" << std::endl;
00293             exit( 1 );
00294         }
00295         
00296         ArgumentBase* c = new Argument<T>(ptr,sho,ln,h,false);
00297         shortName[sho] = c; 
00298         longName[lon] = c; 
00299         commands.push_back(c);
00300         return (*this);
00301     }
00302     
00309     template<class T> inline 
00310     ArgumentParser& parameter( T* ptr, char sho, const char* lon, const char* help )
00311     {
00312         string sn, ln(lon), h(help); sn += sho;
00313         
00314         if( sho!=0 && shortName.find(sho) != shortName.end() ){
00315             std::cerr << "name " << sn << " already used !" << std::endl;
00316             exit( 1 );
00317         }
00318         
00319         if( ln.size()>0 && longName.find(ln) != longName.end() ){
00320             std::cerr << "name " << ln << " already used !" << std::endl;
00321             exit( 1 );
00322         }
00323         
00324         if( sho!=0 && sho == helpShortName ){
00325             std::cerr << "name " << sho << " reserved for help !" << std::endl;
00326             exit( 1 );
00327         }
00328         if( ln.size()>0 && lon == helpLongName ){
00329             std::cerr << "name " << lon << " reserved for help !" << std::endl;
00330             exit( 1 );
00331         }
00332         
00333         ArgumentBase* c = new Argument<T>(ptr,sho,ln,h,true);
00334         shortName[sho] = c; 
00335         longName[lon] = c; 
00336         commands.push_back(c);
00337         return (*this);
00338     }
00339 
00344     void operator () ( int argc, char** argv );
00345 
00346     void operator () ( std::list<std::string> str );
00347 
00348 };
00349 
00356 inline ArgumentParser parse( const std::string& helpstr="", char hs='h', const std::string& hl="help" ){ 
00357     return ArgumentParser(helpstr,hs,hl); 
00358 }
00359 
00360 inline ArgumentParser parse( std::vector<std::string>* files, const std::string& helpstr="", char hs='h', const std::string& hl="help" ){ 
00361     return ArgumentParser(files,helpstr,hs,hl); 
00362 }
00363 
00364 } // namespace helper
00365 
00366 } // namespace sofa
00367 
00368 #endif

Generated on Sun Nov 23 02:29:29 2008 for Sofa by  doxygen 1.5.7.1