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 ANIMAL_command_line_parser________
00033 #define ANIMAL_command_line_parser________
00034
00035 #include <iostream>
00036 #include <stdlib.h>
00037
00038 #include <sstream>
00039 #include <fstream>
00040 #include <string>
00041 #include <vector>
00042 #include <algorithm>
00043 #include <map>
00044 #include <list>
00045
00046 typedef std::istringstream istrstream;
00047
00049 struct ArgumentBase
00050 {
00052 typedef std::string string;
00053
00060 ArgumentBase(char s, string l, string h, bool m)
00061 : shortName(s)
00062 , longName(l)
00063 , help(h)
00064 , mandatory(m)
00065 , isSet(false)
00066 {}
00067
00069 virtual ~ArgumentBase(){}
00070
00072 virtual bool read( std::list<std::string>& str ) = 0;
00073
00075 virtual void printValue() const =0;
00076
00077 char shortName;
00078 string longName;
00079 string help;
00080
00082 inline void print () const
00083 {
00084 std::cout << "-" << shortName <<",\t--"<< longName <<":\t" << help;
00085 if( mandatory ) std::cout<< " (required) ";
00086 std::cout << " (default: "; printValue();
00087 std::cout << ")" << std::endl;
00088 }
00089
00091 bool mandatory;
00092
00094 bool isSet;
00095
00096
00097 };
00098
00099
00100
00101
00109 template < class T = void* >
00110 struct Argument : public ArgumentBase {
00111
00112
00120 Argument( T* t, char sn, string ln, string h, bool m )
00121 : ArgumentBase(sn,ln,h,m)
00122 , ptr(t)
00123 {}
00124
00125 inline void printValue() const ;
00126
00127 private:
00129 T* ptr;
00130
00131
00135 inline bool read( std::list<std::string>& str ) {
00136 if (str.empty()) return false;
00137 std::string s = str.front();
00138 str.pop_front();
00139 istrstream istr( s.c_str() );
00140 if( ! (istr >> *ptr) ) return false;
00141 else {
00142 isSet = true;
00143 return true;
00144 }
00145 }
00146
00147 };
00148
00155 template<> inline
00156 bool Argument<bool>::read( std::list<std::string>& )
00157 {
00158 *ptr = true;
00159 isSet = true;
00160 return true;
00161 }
00162
00163 template<> inline
00164 bool Argument<std::string>::read( std::list<std::string>& str )
00165 {
00166 if (str.empty()) return false;
00167 std::string s = str.front();
00168 str.pop_front();
00169 *ptr = s;
00170 isSet = true;
00171 return true;
00172 }
00173
00175 template<class T> inline
00176 void Argument<T>::printValue() const {
00177 std::cout << *ptr << " ";
00178 }
00179
00180
00181
00182
00192 class ArgumentParser {
00194 typedef std::string string;
00196 typedef std::map< string, ArgumentBase* > Map;
00198 std::map< char, ArgumentBase* > shortName;
00200 Map longName;
00201
00203 typedef std::map<ArgumentBase*,bool> SetMap;
00204
00206 SetMap parameter_set;
00207
00209 typedef std::vector<ArgumentBase*> ArgVec;
00211 ArgVec commands;
00212
00213
00214 string globalHelp;
00215 char helpShortName;
00216 string helpLongName;
00217
00218 public:
00219
00221 ArgumentParser( const string& helpstr="", char hlpShrt='h', const string& hlpLng="help" )
00222 : globalHelp( helpstr )
00223 , helpShortName(hlpShrt)
00224 , helpLongName(hlpLng)
00225 {}
00226
00233 template<class T> inline
00234 ArgumentParser& option( T* ptr, char sho, char* lon, char* help )
00235 {
00236 string sn, ln(lon), h(help); sn += sho;
00237
00238 if( sho!=0 && shortName.find(sho) != shortName.end() ){
00239 std::cerr << "name " << sn << " already used !" << std::endl;
00240 exit( 1 );
00241 }
00242
00243 if( ln.size()>0 && longName.find(ln) != longName.end() ){
00244 std::cerr << "name " << ln << " already used !" << std::endl;
00245 exit( 1 );
00246 }
00247
00248 if( sho!=0 && sho == helpShortName ){
00249 std::cerr << "name " << sho << " reserved for help !" << std::endl;
00250 exit( 1 );
00251 }
00252 if( ln.size()>0 && lon == helpLongName ){
00253 std::cerr << "name " << lon << " reserved for help !" << std::endl;
00254 exit( 1 );
00255 }
00256
00257 ArgumentBase* c = new Argument<T>(ptr,sho,ln,h,false);
00258 shortName[sho] = c;
00259 longName[lon] = c;
00260 commands.push_back(c);
00261 return (*this);
00262 }
00263
00270 template<class T> inline
00271 ArgumentParser& parameter( T* ptr, char sho, char* lon, char* help )
00272 {
00273 string sn, ln(lon), h(help); sn += sho;
00274
00275 if( sho!=0 && shortName.find(sho) != shortName.end() ){
00276 std::cerr << "name " << sn << " already used !" << std::endl;
00277 exit( 1 );
00278 }
00279
00280 if( ln.size()>0 && longName.find(ln) != longName.end() ){
00281 std::cerr << "name " << ln << " already used !" << std::endl;
00282 exit( 1 );
00283 }
00284
00285 if( sho!=0 && sho == helpShortName ){
00286 std::cerr << "name " << sho << " reserved for help !" << std::endl;
00287 exit( 1 );
00288 }
00289 if( ln.size()>0 && lon == helpLongName ){
00290 std::cerr << "name " << lon << " reserved for help !" << std::endl;
00291 exit( 1 );
00292 }
00293
00294 ArgumentBase* c = new Argument<T>(ptr,sho,ln,h,true);
00295 shortName[sho] = c;
00296 longName[lon] = c;
00297 commands.push_back(c);
00298 return (*this);
00299 }
00300
00301
00306 inline void operator () ( int argc, char** argv )
00307 {
00308 std::list<std::string> str;
00309 for (int i=1;i<argc;++i)
00310 str.push_back(std::string(argv[i]));
00311 (*this)(str);
00312 }
00313
00314 inline void operator () ( std::list<std::string> str )
00315 {
00316 string shHelp("-"); shHelp.push_back( helpShortName );
00317 string lgHelp("--"); lgHelp.append( helpLongName );
00318 string name;
00319 while( !str.empty() ){
00320 name = str.front();
00321 str.pop_front();
00322
00323
00324
00325
00326
00327 if( name == shHelp || name == lgHelp )
00328 {
00329 if( globalHelp.size()>0 ) std::cout<< globalHelp <<std::endl;
00330 std::cout << "(short name, long name, description, default value)\n-h,\t--help: this help" << std::endl;
00331 for( ArgVec::const_iterator a=commands.begin(), aend=commands.end(); a!=aend; ++a )
00332 (*a)->print();
00333 exit(1);
00334 }
00335
00336
00337 else if( name.length() > 1 && name[0]=='-' && name[1]=='-' ){
00338 string a;
00339 for( unsigned int i=2; i<name.length(); ++i ){
00340 a += name[i];
00341 }
00342 if( longName.find(a) != longName.end() ){
00343 if( !(longName[ a ]->read( str )))
00344 std::cerr<< "\ncould not read value for option " << name << std::endl << std::endl;
00345 else parameter_set[longName[ a ]] = true;
00346 }
00347 else std::cerr << "\nUnknown option " << name << std::endl << std::endl;
00348 }
00349
00350
00351 else if( name.length() > 1 && name[0]=='-' && name[1]!='-' ){
00352 for( unsigned int i=1; i<name.length(); ++i ){
00353 char a = name[i];
00354 if( shortName.find(a) != shortName.end() ){
00355 if( !(shortName[ a ]->read( str )))
00356 std::cerr<< "\ncould not read value for option " << name << std::endl << std::endl;
00357 else parameter_set[shortName[ a ]] = true;
00358 }
00359 else std::cerr << "\nUnknown option " << name[i] << std::endl << std::endl;
00360 }
00361 }
00362
00363
00364 else std::cerr << "Unknown option " << name << std::endl;
00365 }
00366
00367
00368 bool unset = false;
00369 for( ArgVec::const_iterator cm = commands.begin(), cmend=commands.end(); cm != cmend; ++cm )
00370 {
00371 if( (*cm)->mandatory && !(*cm)->isSet ){
00372 if( !unset )
00373 {
00374 std::cout << "Please set the following parameters: (short name, long name, description)" << std::endl;
00375 unset = true;
00376 }
00377 (*cm)->print();
00378 }
00379 }
00380 if( unset ) exit(1);
00381 }
00382
00383 };
00384
00391 inline ArgumentParser parse( const std::string& helpstr="", char hs='h', const std::string& hl="help" ){
00392 return ArgumentParser(helpstr,hs,hl);
00393 }
00394
00395
00396
00397
00398 #endif
00399