inlib
1.2.0
|
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