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