inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/args
Go to the documentation of this file.
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
00002 // See the file inlib.license for terms.
00003 
00004 #ifndef inlib_args
00005 #define inlib_args
00006 
00007 #include "sout"
00008 #include "strip"
00009 #include "words"
00010 #include "sto"
00011 
00012 #include <ostream>
00013 
00014 namespace inlib {
00015 
00016 class args {
00017 public:
00018   typedef std::pair<std::string,std::string> arg;
00019 public:
00020   args(){}
00021   args(int a_argc,char* a_argv[]){
00022     for(int index=0;index<a_argc;index++) {
00023       std::string s(a_argv[index]);
00024       std::string::size_type pos = s.find('=');
00025       if(pos==std::string::npos) {
00026         m_args.push_back(arg(s,"")); 
00027       } else {
00028         std::string key = s.substr(0,pos);
00029         pos++;
00030         std::string value = s.substr(pos,s.size()-pos);
00031         m_args.push_back(arg(key,value)); 
00032       }     
00033     }
00034   }
00035   args(const std::vector<std::string>& a_args){add(a_args);}
00036   args(const std::vector<arg>& a_args):m_args(a_args){}
00037   args(const std::string& a_args,const std::string& a_sep = " ",bool a_strip = false){
00038     std::vector<std::string> args;
00039     words(a_args,a_sep,false,args);  
00040     add(args,a_strip);
00041   }
00042   virtual ~args(){}
00043 public:
00044   args(const args& a_from):m_args(a_from.m_args){}
00045   args& operator=(const args& a_from){
00046     m_args = a_from.m_args;
00047     return *this;
00048   }
00049 public:
00050   const std::vector<arg>& get_args() const {return m_args;}
00051 
00052   bool is_arg(const std::string& a_string) const {
00053     for(std::vector<arg>::const_iterator it = m_args.begin();
00054         it!=m_args.end();++it) {
00055       if((*it).first==a_string) return true;
00056     }
00057     return false;
00058   }
00059   unsigned int size() const {return m_args.size();}
00060   unsigned int number() const {return m_args.size();} //back comp.
00061   bool find(const std::string& a_key,std::string& a_value) const {
00062     for(std::vector<arg>::const_iterator it = m_args.begin();
00063         it!=m_args.end();++it) {
00064       if((*it).first==a_key) {
00065         a_value = (*it).second;
00066         return true;
00067       }
00068     }
00069     a_value.clear();
00070     return false;
00071   }
00072   std::vector<std::string> find(const std::string& a_key) const {
00073     std::vector<std::string> vals;
00074     for(std::vector<arg>::const_iterator it = m_args.begin();
00075       it!=m_args.end();++it) {
00076       if((*it).first==a_key) vals.push_back((*it).second);
00077     }
00078     return vals;
00079   }
00080   bool find(const std::string& a_string,bool& a_value) const {
00081     std::string s;
00082     if(!find(a_string,s)) {a_value = false;return false;}
00083     return to(s,a_value);
00084   }
00085   template <class aT>
00086   bool find(const std::string& a_string,aT& a_value) const {
00087     std::string s;
00088     if(!find(a_string,s)) {a_value = aT();return false;}
00089     return to<aT>(s,a_value);
00090   }
00091   std::vector<std::string> tovector() const {
00092     // Return a vector of string <name=value>
00093     std::vector<std::string> vec;
00094     for(std::vector<arg>::const_iterator it = m_args.begin();
00095         it!=m_args.end();++it) {
00096       std::string s;
00097       if((*it).second.empty()) {
00098         s = (*it).first;
00099       } else {
00100         s = (*it).first;
00101         s += "=";
00102         s += (*it).second;
00103       }
00104       vec.push_back(s);
00105     }
00106     return vec;
00107   }
00108 
00109   bool add(const std::string& a_key,const std::string& a_value,bool a_override = true){
00110     if(a_override) {
00111       for(std::vector<arg>::iterator it = m_args.begin();
00112           it!=m_args.end();++it) {
00113         if((*it).first==a_key) {
00114           (*it).second = a_value;
00115           return true;
00116         }
00117       }
00118     }
00119     if(a_key.empty()) return false;
00120     m_args.push_back(arg(a_key,a_value)); 
00121     return true;
00122   }
00123 
00124   void add(const std::vector<std::string>& a_args,bool a_strip = false) {
00125     for(std::vector<std::string>::const_iterator it = a_args.begin();
00126         it!=a_args.end();++it) {
00127       std::vector<std::string> ws;
00128       words((*it),"=",false,ws);
00129       if(ws.size()==1) {
00130         if(a_strip) {
00131           m_args.push_back(arg(strp(ws[0]),"")); 
00132         } else {
00133           m_args.push_back(arg(ws[0],"")); 
00134         }
00135       } else if(ws.size()>=2) {
00136         if(a_strip) {
00137           m_args.push_back(arg(strp(ws[0]),strp(ws[1]))); 
00138         } else {
00139           m_args.push_back(arg(ws[0],ws[1])); 
00140         }
00141       }
00142     }
00143   }
00144 
00145   int remove(const std::string& a_key){
00146     unsigned int nbeg = m_args.size();
00147     for(std::vector<arg>::iterator it = m_args.begin();it!=m_args.end();) {
00148       if(a_key==(*it).first) {
00149         it = m_args.erase(it);
00150       } else {
00151         ++it;
00152       }
00153     }
00154     return nbeg - m_args.size();
00155   }
00156 
00157   void remove_first(){m_args.erase(m_args.begin());}
00158 
00159   bool last(std::string& a_key,std::string& a_value) const {
00160     a_key.clear();
00161     a_value.clear();
00162     if(m_args.empty()) return false;
00163     a_key = m_args.back().first;
00164     a_value = m_args.back().second;
00165     return true;
00166   }
00167   
00168   bool file(std::string& a_file) const {
00169     std::string slast;
00170     std::string s;
00171     if((m_args.size()>1) //first arg is the program name !
00172        && last(slast,s) 
00173        && (slast.find('-')!=0) 
00174        && (s.empty()) ) {
00175       a_file = slast; //Last argument is not an option.
00176       return true;
00177     } else {
00178       a_file.clear();
00179       return false;
00180     }
00181   }
00182   
00183   std::vector<std::string> files(bool a_skip_first = true) const {
00184     // Get the serie of trailing args not beginning with '-'
00185     // and without a value (not of the form [-]xxx=yyy). 
00186     // Note that an argument like that in between arguments
00187     // is NOT taken into account. 
00188     std::vector<std::string> files;
00189     if(m_args.empty()) return files;
00190     std::vector<arg>::const_iterator it = m_args.begin();
00191     if(a_skip_first) it++;
00192     for(;it!=m_args.end();++it) {
00193       if( ((*it).first.find('-')==0) || (*it).second.size() ) {
00194         files.clear();
00195       } else {
00196         files.push_back((*it).first);
00197       }
00198     }
00199     return files;
00200   }  
00201   bool argcv(int& a_argc,char**& a_argv) const {
00202     // If using with :
00203     //   int argc;
00204     //   char** argv;
00205     //   args.argcv(argc,argv);  
00206     // you can delete with :
00207     //   args.delete_argcv(argc,argv);
00208     if(m_args.empty()) {a_argc = 0;a_argv = 0;return true;}
00209     typedef char* cstr_t;
00210     cstr_t* av = new cstr_t[m_args.size()];
00211     if(!av) {a_argc = 0;a_argv = 0;return false;}
00212     a_argv = av;
00213     for(std::vector<arg>::const_iterator it = m_args.begin();
00214         it!=m_args.end();++it,av++) {
00215       std::string::size_type lf = (*it).first.length();
00216       std::string::size_type ls = (*it).second.length();
00217       std::string::size_type sz = 0;
00218       if(ls) {
00219         sz = lf + 1 + ls;
00220       } else {
00221         sz = lf;
00222       }
00223       char* p = new char[sz+1];
00224       if(!p) {a_argc = 0;a_argv = 0;return false;} //some delete are lacking.
00225       *av = p;
00226      {char* pf = (char*)(*it).first.c_str();
00227       for(std::string::size_type i=0;i<lf;i++) {*p++ = *pf++;}
00228       *p = 0;}
00229       if(ls) {*p = '=';p++;}
00230      {char* ps = (char*)(*it).second.c_str();
00231       for(std::string::size_type i=0;i<ls;i++) {*p++ = *ps++;}
00232       *p = 0;}
00233     }
00234     a_argc = (int)m_args.size();
00235     return true;
00236   }
00237   void delete_argcv(int& a_argc,char**& a_argv) const {
00238     for(int index=0;index<a_argc;index++) delete [] a_argv[index];
00239     delete [] a_argv;
00240     a_argc = 0;
00241     a_argv = 0;
00242   }
00243   bool known_options(const std::vector<std::string>& a_opts) const {
00244     for(std::vector<arg>::const_iterator it = m_args.begin();
00245         it!=m_args.end();++it) {
00246       if((*it).first.find('-')==0) { //find '-' at first pos.
00247         bool found = false;
00248         for(std::vector<std::string>::const_iterator it2 = a_opts.begin();
00249           it2!=a_opts.end();++it2) {
00250           if((*it).first==(*it2)) {
00251             found = true;
00252             break;        
00253           }
00254         }
00255         if(!found) return false;
00256       }
00257     }
00258     return true;
00259   }
00260 
00261   void files_at_end(bool a_skip_first = true) {
00262     // reorder to have "file" arguments at end.
00263     if(m_args.empty()) return;
00264     std::vector<arg> args;
00265     if(a_skip_first) args.push_back(*(m_args.begin()));
00266     //first pass :
00267     //FIXME : Android : with inlib/stl/vector having
00268     //        const_iterator does not compile.
00269    {std::vector<arg>::iterator it = m_args.begin();
00270     if(a_skip_first) it++;
00271     for(;it!=m_args.end();++it) {
00272       if( ((*it).first.find('-')==0) || (*it).second.size() ) {
00273         args.push_back(*it);
00274       }
00275     }}
00276     //second pass :
00277     //FIXME : Android : with inlib/stl/vector having
00278     //        const_iterator does not compile.
00279    {std::vector<arg>::iterator it = m_args.begin();
00280     if(a_skip_first) it++;
00281     for(;it!=m_args.end();++it) {
00282       if( ((*it).first.find('-')==0) || (*it).second.size() ) {
00283       } else {
00284         args.push_back(*it);
00285       }
00286     }}
00287     m_args = args;
00288   }
00289 
00290   //NOTE : print is a Python keyword.
00291   void dump(std::ostream& a_out) const {
00292     for(std::vector<arg>::const_iterator it = m_args.begin();
00293         it!=m_args.end();++it) {
00294       a_out << "key = " << sout((*it).first)
00295             << " value = " << sout((*it).second)
00296             << std::endl;
00297     }
00298   }
00299 
00300 private:
00301   std::vector<arg> m_args;
00302 };
00303 
00304 inline bool check_args(const std::vector<std::string>& a_args,unsigned int a_number,std::ostream& a_out){
00305   if(a_args.size()==a_number) return true;
00306   a_out << "bad argument number." 
00307         << " Given " << (unsigned int)a_args.size() 
00308         << " whilst " << a_number << " expected."
00309         << std::endl;
00310   return false;
00311 }
00312 
00313 inline bool check_min(const std::vector<std::string>& a_args,unsigned int a_number,std::string& a_last,std::ostream& a_out){
00314   if(a_args.size()>=a_number) {
00315     if(a_number==0) {
00316       if(a_args.empty()) {
00317         a_last.clear();
00318       } else {
00319         a_last = a_args[0];
00320         for(unsigned int index=1;index<a_args.size();index++) {
00321           a_last += " " + a_args[index];
00322         }
00323       }
00324     } else {
00325       a_last = a_args[a_number-1];
00326       for(unsigned int index=a_number;index<a_args.size();index++) {
00327         a_last += " " + a_args[index];
00328       }
00329     }
00330     return true;
00331   }
00332   a_out << "bad argument number." 
00333         << " Given " << (unsigned int)a_args.size() 
00334         << " whilst at least " << a_number << " expected."
00335         << std::endl;
00336   return false;
00337 }
00338 
00339 inline bool check_min_args(const std::vector<std::string>& aArgs,unsigned int a_number,std::ostream& a_out){
00340   if(aArgs.size()>=a_number) return true;
00341   a_out << "bad argument number." 
00342         << " Given " << (unsigned int)aArgs.size() 
00343         << " whilst at least " << a_number << " expected."
00344         << std::endl;
00345   return false;
00346 }
00347 
00348 inline bool check_or_args(const std::vector<std::string>& aArgs,unsigned int a_1,unsigned int a_2,std::ostream& a_out){
00349   if((aArgs.size()==a_1)||(aArgs.size()==a_2)) return true;
00350   a_out << "bad argument number." 
00351         << " Given " << (unsigned int)aArgs.size() 
00352         << " whilst " << a_1 << " or " << a_2 << " expected."
00353         << std::endl;
00354   return false;
00355 }
00356 
00357 template <class T>
00358 inline bool to(std::ostream& a_out,const std::string& a_string,T& a_value){
00359   if(!to<T>(a_string,a_value)) {
00360     a_out << "Passed value " << sout(a_string)
00361           << " is of bad type."
00362           << std::endl;
00363     return false;
00364   }
00365   return true;
00366 }
00367 
00368 inline bool to(std::ostream& a_out,const std::string& a_string,bool& a_value){
00369   if(!to(a_string,a_value)) {
00370     a_out << "Passed value " << sout(a_string)
00371           << " is not a boolean."
00372           << std::endl;
00373     return false;
00374   }
00375   return true;
00376 }
00377 
00378 inline std::string gui_toolkit(args& a_args,bool a_rm_in_args){
00379   std::string driver;
00380   a_args.find("-toolkit",driver);
00381   if(a_rm_in_args) a_args.remove("-toolkit");
00382   if(driver.empty()) {
00383     if(a_args.is_arg("-Xt")||
00384        a_args.is_arg("-xt")||
00385        a_args.is_arg("-Xm")||
00386        a_args.is_arg("-xm")||
00387        a_args.is_arg("-Motif")||
00388        a_args.is_arg("-motif")) {
00389       driver = "Xt";
00390       if(a_rm_in_args) {
00391         a_args.remove("-Xt");
00392         a_args.remove("-xt");
00393         a_args.remove("-Xm");
00394         a_args.remove("-xm");
00395         a_args.remove("-Motif");
00396         a_args.remove("-motif");
00397       }
00398     } else if(a_args.is_arg("-Win")||
00399               a_args.is_arg("-win")||
00400               a_args.is_arg("-Win32")||
00401               a_args.is_arg("-win32")) {
00402       driver = "Win";
00403       if(a_rm_in_args) {
00404         a_args.remove("-Win");
00405         a_args.remove("-win");
00406         a_args.remove("-Win32");
00407         a_args.remove("-win32");
00408       }
00409     } else if(a_args.is_arg("-NextStep")||
00410               a_args.is_arg("-nextstep")) {
00411       driver = "NextStep";
00412       if(a_rm_in_args) {
00413         a_args.remove("-NextStep");
00414         a_args.remove("-nextstep");
00415       }
00416     } else if(a_args.is_arg("-Gtk")||
00417               a_args.is_arg("-gtk")) {
00418       driver = "Gtk";
00419       if(a_rm_in_args) {
00420         a_args.remove("-Gtk");
00421         a_args.remove("-gtk");
00422       }
00423     } else if(a_args.is_arg("-Qt")||
00424               a_args.is_arg("-qt")) {
00425       driver = "Qt";
00426       if(a_rm_in_args) {
00427         a_args.remove("-Qt");
00428         a_args.remove("-qt");
00429       }
00430     } else if(a_args.is_arg("-SDL")||
00431               a_args.is_arg("-sdl")) {
00432       driver = "SDL";
00433       if(a_rm_in_args) {
00434         a_args.remove("-SDL");
00435         a_args.remove("-sdl");
00436       }
00437     } else if(a_args.is_arg("-Net")||
00438               a_args.is_arg("-net")) {
00439       driver = "Net";
00440       if(a_rm_in_args) {
00441         a_args.remove("-Net");
00442         a_args.remove("-net");
00443       }
00444     }
00445   }
00446 
00447   return driver;
00448 }
00449 
00450 inline void window_size_from_args(const args& a_args,
00451                                   unsigned int& a_ww,unsigned int& a_wh) {
00452   // return some common window size (in pixels).
00453   if(a_args.is_arg("-iPod")||a_args.is_arg("-iPhone")) {
00454     a_ww = 320;
00455     a_wh = 480;
00456   } else if(a_args.is_arg("-iPad")) {
00457     a_ww = 768;
00458     a_wh = 1024;
00459   } else if(a_args.is_arg("-iPhone4")) {
00460     a_ww = 640;
00461     a_wh = 960;
00462   } else if(a_args.is_arg("-SGS")) { //Samsung Galaxy S
00463     //a_ww = 320;
00464     //a_wh = 533;
00465     a_ww = 480;
00466     a_wh = 800;
00467   } else {
00468     if(a_args.find<unsigned int>("-ww",a_ww)) {
00469       if(a_args.find<unsigned int>("-wh",a_wh)) return;
00470       //A4 : we have ww but not wh :
00471       a_wh = (unsigned int)(a_ww*(29.7f/21.0f)); //29.7/21 = 1.414
00472     } else { //we don't have ww.
00473       if(a_args.find<unsigned int>("-wh",a_wh)) {
00474         //A4 : we have wh but not ww :
00475         a_ww = (unsigned int)(a_wh*(21.0f/29.7f));
00476       } else {
00477         //we have nothing. Take a ww of 700. With A4 wh is then 990.
00478         a_ww = 700;
00479         a_wh = (unsigned int)(a_ww*(29.7f/21.0f)); //29.7/21 = 1.414
00480       }
00481     }
00482   }
00483   if(a_args.is_arg("-land")){
00484     unsigned int tmp = a_ww;
00485     a_ww = a_wh;
00486     a_wh = tmp;
00487   }
00488 }
00489 
00490 }
00491 
00492 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines