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_smanip 00005 #define inlib_smanip 00006 00007 #include "sep" 00008 00009 #include <vector> 00010 #include <cstring> 00011 00012 #include "sout" //for back compatibility. 00013 #include "words" //for back compatibility. 00014 #include "sto" //for back compatibility. 00015 #include "strip" //for back compatibility. 00016 #include "path" //for back compatibility. 00017 #include "sjust" //for back compatibility. 00018 #include "srep" //for back compatibility. 00019 00020 namespace inlib { 00021 00022 inline bool belong(const std::vector<std::string>& a_vec, 00023 const std::string& a_s) { 00024 std::vector<std::string>::const_iterator it; 00025 for(it=a_vec.begin();it!=a_vec.end();++it) { 00026 if(*it==a_s) return true; 00027 } 00028 return false; 00029 } 00030 00031 inline bool match(const std::string& a_string,const std::string& a_pattern){ 00032 std::string::size_type lpattern = a_pattern.length(); 00033 std::string::size_type lstring = a_string.length(); 00034 if ((lpattern==0)&&(lstring==0)) return true; 00035 if ((lpattern==0)&&(lstring!=0)) return true; 00036 if ((lpattern!=0)&&(lstring==0)) return false; 00037 00038 if(a_pattern=="*") return true; // pattern is * : 00039 00040 {bool some_star = false; 00041 for(unsigned int count=0;count<lpattern;count++) { 00042 if(a_pattern[count]=='*') {some_star = true;break;} 00043 } 00044 if(!some_star) { // no wildcard : 00045 return (a_pattern==a_string ? true : false ); 00046 }} 00047 00048 // complex pattern : 00049 std::vector<std::string> ws; 00050 words(a_pattern,"*",false,ws); 00051 if(ws.empty()) return true; // only wildcards : 00052 00053 // tricky case : 00054 unsigned int wnumber = ws.size(); 00055 char* token = (char*)a_string.c_str(); 00056 {for(unsigned int count=0;count<wnumber;count++) { 00057 unsigned int lword = ws[count].size(); 00058 if(!lword) continue;//should never happen ! 00059 if(count==0) { 00060 if(a_pattern[0]!='*') { 00061 // Begin of pattern (ws[0]) and a_string must match : 00062 if(::strncmp(token,ws[count].c_str(),lword)) return false; 00063 token = token + lword; 00064 continue; 00065 } 00066 } 00067 char* pos = ::strstr(token,ws[count].c_str()); 00068 if(!pos) return false; 00069 if((count==(wnumber-1)) && (a_pattern[lpattern-1]!='*') ) { // Last word. 00070 // Compare last word and end of a_string. 00071 if(::strcmp(a_string.c_str()+lstring-lword,ws[count].c_str())) 00072 return false; 00073 break; 00074 } else { 00075 token = pos + lword; 00076 } 00077 }} 00078 return true; 00079 } 00080 00081 inline unsigned int numchar(const std::string& a_string,char a_c){ 00082 unsigned int num = 0; 00083 std::string::const_iterator it; 00084 for(it=a_string.begin();it!=a_string.end();++it) { 00085 if((*it)==a_c) num++; 00086 } 00087 return num; 00088 } 00089 00090 inline void replace(std::string& a_string,char a_old,char a_new){ 00091 for(std::string::iterator it=a_string.begin();it!=a_string.end();++it) { 00092 if((*it)==a_old) *it = a_new; 00093 } 00094 } 00095 00096 inline std::vector<std::string> path_words(const std::string& a_path,bool& a_absolute,bool& a_win_path,std::string& a_drive){ 00097 00098 // a_path could be at the Windows syntax : <drive>:\dir1\dir2... 00099 // If so, only dir1, dirn are put in a_words. 00100 00101 std::string path = a_path; 00102 std::string::size_type pos = path.find('\\'); 00103 a_win_path = (pos==std::string::npos?false:true); 00104 if(a_win_path) { 00105 replace(path,"\\","/"); 00106 pos = path.find(':'); 00107 if(pos!=std::string::npos) { //drive 00108 a_drive = path.substr(0,pos); 00109 path = path.substr(pos+1,path.size()-(pos+1)); 00110 } else { 00111 a_drive = ""; 00112 } 00113 } else { 00114 a_drive = ""; 00115 } 00116 00117 a_absolute = (path.size()&&(path[0]=='/')?true:false); 00118 00119 return words(path,"/"); 00120 } 00121 00122 inline bool remove(std::vector<std::string>& a_strings,const std::string& a_string){ 00123 bool found_some = false; 00124 //std::vector<std::string>::iterator it; 00125 //for(it=a_strings.begin();it!=a_strings.end();) { 00126 // if(*it==a_string) { 00127 // it = a_strings.erase(it); 00128 // found_some = true; 00129 // } else { 00130 // ++it; 00131 // } 00132 //} 00133 //brut force avoiding erase(). For Android + inlib/stl. 00134 std::vector<std::string> ss; 00135 std::vector<std::string>::iterator it; 00136 for(it=a_strings.begin();it!=a_strings.end();++it) { 00137 if(*it==a_string) { 00138 found_some = true; 00139 } else { 00140 ss.push_back(*it); 00141 } 00142 } 00143 a_strings = ss; 00144 return found_some; 00145 } 00146 00147 inline void tolowercase(std::string& a_string){ 00148 for(std::string::iterator it=a_string.begin();it!=a_string.end();++it) { 00149 char c = *it; 00150 *it = ((c) >= 'A' && (c) <= 'Z' ? c - 'A' + 'a' : c); 00151 } 00152 } 00153 00154 inline void touppercase(std::string& a_string){ 00155 for(std::string::iterator it=a_string.begin();it!=a_string.end();++it) { 00156 char c = *it; 00157 *it = ((c) >= 'a' && (c) <= 'z' ? c - 'a' + 'A' : c); 00158 } 00159 } 00160 00161 inline bool is_ip(const std::string& a_string){ 00162 if(a_string.empty()) return false; 00163 if(a_string[0]=='.') return false; 00164 if(a_string[a_string.size()-1]=='.') return false; 00165 unsigned int ndot = 0; 00166 std::string::const_iterator it; 00167 for(it=a_string.begin();it!=a_string.end();++it) { 00168 if((*it)=='.') { 00169 ndot++; 00170 } else if( ((*it)=='0') || ((*it)=='1') || 00171 ((*it)=='2') || ((*it)=='3') || 00172 ((*it)=='4') || ((*it)=='5') || 00173 ((*it)=='6') || ((*it)=='7') || 00174 ((*it)=='8') || ((*it)=='9') ){ 00175 } else { 00176 return false; 00177 } 00178 } 00179 if(ndot!=3) return false; 00180 return true; 00181 } 00182 00183 //used in OpenPAW, BatchLab. 00184 inline bool is_f77(const std::string& a_path){ 00185 std::string sfx = suffix(a_path); 00186 tolowercase(sfx); 00187 if(sfx=="f") return true; //the standard. 00188 if(sfx=="for") return true; //for opaw. Known by g77. 00189 if(sfx=="ftn") return true; //for opaw. 00190 if(sfx=="fortran") return true; //for opaw. 00191 if(sfx=="f77") return true; 00192 return false; 00193 } 00194 00195 //used in OpenPAW, BatchLab. 00196 inline bool is_cpp(const std::string& a_path){ 00197 std::string sfx = suffix(a_path); 00198 tolowercase(sfx); 00199 if(sfx=="c") return true; 00200 if(sfx=="cxx") return true; 00201 if(sfx=="cpp") return true; 00202 if(sfx=="C") return true; 00203 return false; 00204 } 00205 00206 inline std::string to_xml(const std::string& a_string){ 00207 // > : < 00208 // < : > 00209 // & : & 00210 // " : " 00211 // ' : ' 00212 std::string s = a_string; 00213 replace(s,"<","<"); 00214 replace(s,">",">"); 00215 replace(s,"&","&"); 00216 replace(s,"\"","""); 00217 replace(s,"'","'"); 00218 return s; 00219 } 00220 00221 inline std::string to_string(const std::vector<std::string>& a_strings,const std::string& a_sep,bool a_sep_at_end = false){ 00222 unsigned int number = a_strings.size(); 00223 if(number<=0) return ""; 00224 std::string result; 00225 number--; 00226 for(unsigned int index=0;index<number;index++) { 00227 result += a_strings[index]; 00228 result += a_sep; 00229 } 00230 result += a_strings[number]; 00231 if(a_sep_at_end) result += a_sep; 00232 return result; 00233 } 00234 00235 inline std::string to_string(unsigned int a_linen,const char* a_lines[]) { 00236 std::string s; 00237 for(unsigned int index=0;index<a_linen;index++) { 00238 s += std::string(a_lines[index]); 00239 s += "\n"; 00240 } 00241 return s; 00242 } 00243 00244 inline std::vector<std::string> to(int a_argc,char** a_argv) { 00245 std::vector<std::string> v; 00246 for(int index=0;index<a_argc;index++) v.push_back(a_argv[index]); 00247 return v; 00248 } 00249 00250 // same logic as words() function. 00251 template <class T> 00252 inline bool values(const std::string& a_string,const std::string& a_sep,bool a_take_empty,std::vector<T>& a_values){ 00253 a_values.clear(); 00254 if(a_string.empty()) return true; 00255 std::string::size_type lim = (a_take_empty?0:1); 00256 if(a_sep.empty()) { 00257 T value; 00258 if(!to<T>(a_string,value)) { 00259 a_values.clear(); 00260 return false; 00261 } 00262 a_values.push_back(value); 00263 } else { 00264 std::string::size_type l = a_string.length(); 00265 std::string::size_type llimiter = a_sep.length(); 00266 std::string::size_type pos = 0; 00267 while(true) { 00268 std::string::size_type index = a_string.find(a_sep,pos); 00269 if(index==std::string::npos){ // Last word. 00270 if((l-pos)>=lim) { 00271 T value; 00272 if(!to<T>(a_string.substr(pos,l-pos),value)) { 00273 a_values.clear(); 00274 return false; 00275 } 00276 a_values.push_back(value); 00277 } 00278 break; 00279 } else { 00280 // abcxxxef 00281 // 0 3 67 00282 if((index-pos)>=lim) { 00283 T value; 00284 if(!to<T>(a_string.substr(pos,index-pos),value)) { 00285 a_values.clear(); 00286 return false; 00287 } 00288 a_values.push_back(value); 00289 } 00290 pos = index + llimiter; 00291 } 00292 } 00293 } 00294 return true; 00295 } 00296 00297 } 00298 00299 #include <cstdlib> //::strtol 00300 00301 namespace inlib { 00302 00303 inline bool version(const std::string& a_string,std::vector<unsigned int>& a_version) { 00304 // a_string is of the form [v,V][<number><char>]<number> 00305 // Examples : 0 1.2 v0 v1r2 V1r2p3 v0.1.3 00306 unsigned int number = a_string.size(); 00307 if(!number) { 00308 a_version.clear(); 00309 return false; 00310 } 00311 char* pos = (char*)a_string.c_str(); 00312 if( ((*pos)=='v') || ((*pos)=='V') ) { 00313 if(number==1) { 00314 a_version.clear(); 00315 return false; //a_string is only 'v' or 'V' ! 00316 } 00317 pos++; 00318 } 00319 while(*pos!='\0') { 00320 char* s; 00321 long v = ::strtol(pos,&s,10); 00322 if(s==pos) { 00323 a_version.clear(); 00324 return false; 00325 } 00326 if(v<0) { 00327 a_version.clear(); 00328 return false; 00329 } 00330 a_version.push_back((unsigned int)v); 00331 pos = s; //Could be at end. 00332 if(*pos=='\0') break; 00333 // Next char is then not a digit. Skip it. 00334 pos++; 00335 } 00336 return true; 00337 } 00338 00339 00340 inline bool is_version(const std::string& a_string) { 00341 std::vector<unsigned int> vers; 00342 return version(a_string,vers); 00343 } 00344 00345 inline std::string remove_version(const std::string& a_string) { 00346 // replace "@@top@@/pack/vers" -> "@@top@@/pack". 00347 std::string sold = a_string; 00348 replace(sold,"\"",sep()+"@quote@"); //To treat AIDA/v3r2p1"/src 00349 std::vector<std::string> words = inlib::words(sold,sep()); 00350 unsigned int wordn = words.size(); 00351 std::string snew; 00352 for(unsigned int index=0;index<wordn;index++) { 00353 std::vector<unsigned int> vers; 00354 std::string word = words[index]; 00355 if(!version(word,vers)) { 00356 if(snew.size()) snew += sep(); 00357 snew += words[index]; 00358 } 00359 } 00360 replace(snew,sep()+"@quote@","\""); 00361 return snew; 00362 } 00363 00364 inline bool polynomial_degree(const std::string& a_string,int& a_degree){ 00365 // a_string = [p,P,Polynomial]<integer degree> 00366 // We extract <degree> from the upper. 00367 // The degree is the maximum "x" power. 00368 // For example P1 is ax+b which of degree 1. 00369 // For example P2 is ax*x+bx+c which of degree 2. 00370 std::string s = a_string; 00371 tolowercase(s); 00372 replace(s,"polynomial","p"); 00373 a_degree = 0; 00374 if(s.size()<=0) return false; 00375 if(s[0]!='p') return false; 00376 int number = 0; 00377 if(!to<int>(s.substr(1,s.size()-1),number)) return false; 00378 a_degree = number; 00379 return true; 00380 } 00381 00382 } 00383 00384 #endif