00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
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
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 }
00365
00366 }
00367
00368 #endif