1 #include "stringutilities.h" 2 #include "mathutilities.h" 3 4 #include <algorithm> 5 #include <stdlib.h> 6 #include <cstring> 7 #include <errno.h> 8 9 #include "Report.h" 10 11 using std::find; 12 using std::vector; 13 using std::string; 14 using std::stringstream; 15 using std::transform; 16 using namespace ProtoMol::Report; 17 18 namespace ProtoMol { 19 20 //_____________________________________________________________________ uppercase uppercase(const string & word)21 string uppercase (const string& word){ 22 string tmp(word); 23 transform(word.begin(),word.end(),tmp.begin(),toupper); 24 return tmp; 25 } 26 27 //_____________________________________________________________________ lowercase lowercase(const string & word)28 string lowercase (const string& word){ 29 string tmp(word); 30 transform(word.begin(),word.end(),tmp.begin(),tolower); 31 return tmp; 32 } 33 34 //_____________________________________________________________________ equal equal(const string & s1,const string & s2)35 bool equal(const string& s1, const string& s2){ 36 return (s1 == s2); 37 } 38 39 //_____________________________________________________________________ equalNocase equalNocase(const string & s1,const string & s2)40 bool equalNocase(const string& s1, const string& s2){ 41 const string::size_type i1 = s1.size(); 42 if(i1 != s2.size()) 43 return false; 44 for(string::size_type i=0;i<i1;++i) 45 if(toupper(s1[i]) != toupper(s2[i])) 46 return false; 47 return true; 48 } 49 50 //_____________________________________________________________________ equalBegin equalBegin(const string & s1,const string & s2)51 bool equalBegin(const string& s1, const string& s2){ 52 const string::size_type i1 = s1.size(); 53 const string::size_type i2 = s2.size(); 54 if(i1 < i2) 55 return (s2.substr(0,i1) == s1); 56 else 57 return (s1.substr(0,i2) == s2); 58 } 59 60 //_____________________________________________________________________ equalBeginNocase equalBeginNocase(const string & s1,const string & s2)61 bool equalBeginNocase(const string& s1, const string& s2){ 62 return equalBegin(uppercase(s1),uppercase(s2)); 63 } 64 65 66 //_____________________________________________________________________ equalStart equalStart(const string & s1,const string & s2)67 bool equalStart(const string& s1, const string& s2){ 68 const string::size_type i1 = s1.size(); 69 if(i1 <= s2.size()) 70 return (s2.substr(0,i1) == s1); 71 else 72 return false; 73 } 74 75 //_____________________________________________________________________ equalStartNocase equalStartNocase(const string & s1,const string & s2)76 bool equalStartNocase(const string& s1, const string& s2){ 77 return equalStart(uppercase(s1),uppercase(s2)); 78 } 79 80 //_____________________________________________________________________ equalEnd equalEnd(const string & s1,const string & s2)81 bool equalEnd(const string& s1, const string& s2){ 82 string::size_type i1 = s1.size(); 83 string::size_type i2 = s2.size(); 84 if(i1 < i2) 85 return (s2.substr(i2-i1) == s1); 86 else 87 return (s1.substr(i1-i2) == s2); 88 } 89 90 //_____________________________________________________________________ equalEndNocase equalEndNocase(const string & s1,const string & s2)91 bool equalEndNocase(const string& s1, const string& s2){ 92 return equalEnd(uppercase(s1),uppercase(s2)); 93 } 94 95 //_____________________________________________________________________ equalTerminate equalTerminate(const string & s1,const string & s2)96 bool equalTerminate(const string& s1, const string& s2){ 97 string::size_type i1 = s1.size(); 98 string::size_type i2 = s2.size(); 99 if(i1 <= i2) 100 return (s2.substr(i2-i1) == s1); 101 else 102 return false; 103 } 104 105 //_____________________________________________________________________ equalTerminateNocase equalTerminateNocase(const string & s1,const string & s2)106 bool equalTerminateNocase(const string& s1, const string& s2){ 107 return equalTerminate(uppercase(s1),uppercase(s2)); 108 } 109 110 111 //_____________________________________________________________________ toStringGeneric 112 template <class T> toStringGeneric(T x)113 inline string toStringGeneric(T x){ 114 // http://www.bespecific.com/dialog/becodetalk/archive/980405/0058.html 115 stringstream ss; 116 ss << x; 117 return string(ss.str()); 118 } 119 120 //_____________________________________________________________________ toString toString(Real x)121 string toString(Real x){ 122 stringstream ss; 123 ss.precision(sizeof(Real) > sizeof(float)?15:9); 124 ss << x; 125 return string(ss.str()); 126 } 127 128 //_____________________________________________________________________ toString toString(Real x,unsigned int n,unsigned int m)129 string toString(Real x,unsigned int n, unsigned int m){ 130 stringstream ss; 131 ss.setf(std::ios::showpoint|std::ios::fixed); 132 ss.precision(m); 133 ss.width(n+m+1); 134 ss << x; 135 return string(ss.str()); 136 } 137 138 139 //_____________________________________________________________________ toString toString(bool x)140 string toString(bool x){ 141 if(x) 142 return "true"; 143 else 144 return "false"; 145 } 146 147 //_____________________________________________________________________ toString toString(const Vector3D & c)148 string toString(const Vector3D& c){ 149 return string(toString(c.x)+" "+toString(c.y)+" "+toString(c.z)); 150 } 151 152 //_____________________________________________________________________ toString toString(const vector<Real> & v)153 string toString(const vector<Real>& v){ 154 string res; 155 for(unsigned int i=0;i<v.size();++i) 156 res += string(i>0?" ":"")+toString(v[i]); 157 return res; 158 } 159 160 //_____________________________________________________________________ isReal isReal(const string & word)161 bool isReal(const string& word){ 162 Real r = 0.0; 163 return toReal(word,r); 164 } 165 166 //_____________________________________________________________________ toReal toReal(const string & word)167 Real toReal(const string& word){ 168 Real r = 0.0; 169 toReal(word,r); 170 return r; 171 } 172 173 //_____________________________________________________________________ toReal 174 // http://www.dinkumware.com/htm_cpl/stdlib.html#strtod toReal(const string & word,Real & r)175 bool toReal(const string& word, Real &r){ 176 char* endptr = NULL; 177 double d = strtod(word.c_str(),&endptr); 178 r = static_cast<Real>(d); 179 return (!word.empty() && ((fabs(d)>= Constant::MINREAL && fabs(d) <= Constant::MAXREAL)|| fabs(d) == 0.0) && errno != ERANGE && (endptr == NULL || isBlank(string(endptr))) && isPrintable(word)); 180 } 181 182 //_____________________________________________________________________ isInt isInt(const string & word)183 bool isInt(const string& word){ 184 int i = 0; 185 return toInt(word,i); 186 } 187 188 //_____________________________________________________________________ toInt toInt(const string & word)189 int toInt(const string& word){ 190 int i=0; 191 toInt(word,i); 192 return i; 193 } 194 195 //_____________________________________________________________________ toInt 196 // http://www.dinkumware.com/htm_cpl/stdlib.html#strtol toInt(const string & word,int & i)197 bool toInt(const string& word, int &i){ 198 char* endptr = NULL; 199 long l = strtol(word.c_str(),&endptr,10); 200 i = static_cast<int>(l); 201 if (!word.empty() && static_cast<long>(i) == l && errno != ERANGE && (endptr == NULL || isBlank(string(endptr))) && isPrintable(word)) 202 return true; 203 204 Real r; 205 if(toReal(word,r)){ 206 i = static_cast<unsigned int>(r); 207 return (static_cast<Real>(i) == r); 208 } 209 return false; 210 } 211 212 //_____________________________________________________________________ isUInt isUInt(const string & word)213 bool isUInt(const string& word){ 214 unsigned int i = 0; 215 return toUInt(word,i); 216 } 217 218 //_____________________________________________________________________ toUInt toUInt(const string & word)219 unsigned int toUInt(const string& word){ 220 unsigned int i=0; 221 toUInt(word,i); 222 return i; 223 } 224 225 //_____________________________________________________________________ toUInt 226 // http://www.dinkumware.com/htm_cpl/stdlib.html#strtol toUInt(const string & word,unsigned int & i)227 bool toUInt(const string& word, unsigned int &i){ 228 char* endptr = NULL; 229 unsigned long l = strtoul(word.c_str(),&endptr,10); 230 i = static_cast<unsigned int>(l); 231 if (!word.empty() && static_cast<unsigned long>(i) == l && errno != ERANGE && (endptr == NULL || isBlank(string(endptr))) && isPrintable(word)) 232 return true; 233 Real r; 234 if(toReal(word,r)){ 235 i = static_cast<unsigned int>(r); 236 return (static_cast<Real>(i) == r); 237 } 238 return false; 239 } 240 241 //_____________________________________________________________________ isBool isBool(const string & word)242 bool isBool(const string& word){ 243 bool b = false; 244 return toBool(word,b); 245 } 246 247 //_____________________________________________________________________ toBool toBool(const string & word)248 bool toBool(const string& word){ 249 bool b = false; 250 toBool(word,b); 251 return b; 252 } 253 254 //_____________________________________________________________________ toBool toBool(const string & word,bool & b)255 bool toBool(const string& word, bool &b){ 256 string s = removeBeginEndBlanks(word); 257 if(equalNocase(s,"true") || equalNocase(s,"yes") || equalNocase(s,"on") || equalNocase(s,"1")){ 258 b = true; 259 return true; 260 } 261 else if(equalNocase(s,"false") || equalNocase(s,"no") || equalNocase(s,"off") || equalNocase(s,"0")){ 262 b = false; 263 return true; 264 } 265 else { 266 return false; 267 } 268 } 269 270 //_____________________________________________________________________ isVector3D isVector3D(const string & word)271 bool isVector3D(const string& word){ 272 Vector3D c(0.0,0.0,0.0); 273 return toVector3D(word,c); 274 275 } 276 277 //_____________________________________________________________________ toVector3D toVector3D(const string & word)278 Vector3D toVector3D(const string& word){ 279 Vector3D c(0.0,0.0,0.0); 280 toVector3D(word,c); 281 return c; 282 } 283 284 //_____________________________________________________________________ toVector3D toVector3D(const string & word,Vector3D & c)285 bool toVector3D(const string& word, Vector3D &c){ 286 string s = removeBeginEndBlanks(word); 287 stringstream ss(s); 288 string x,y,z; 289 ss >> x >> y >> z; 290 bool bx,by,bz; 291 bx = toReal(x,c.x); 292 by = toReal(y,c.y); 293 bz = toReal(z,c.z); 294 return (ss.eof() && bx && by && bz); 295 } 296 297 //_____________________________________________________________________ isVector isVector(const string & word)298 bool isVector(const string& word){ 299 vector<Real> v; 300 return toVector(word,v); 301 302 } 303 304 //_____________________________________________________________________ toVector toVector(const string & word)305 vector<Real> toVector(const string& word){ 306 vector<Real> v; 307 toVector(word,v); 308 return v; 309 } 310 311 //_____________________________________________________________________ toVector toVector(const string & word,vector<Real> & v)312 bool toVector(const string& word, vector<Real> &v){ 313 string s = removeBeginEndBlanks(word); 314 stringstream is(s); 315 v.clear(); 316 string str; 317 is >> str; 318 if(isReal(str)){ 319 v.push_back(toReal(str)); 320 while(is >> str){ 321 if(!isReal(str)) 322 break; 323 v.push_back(toReal(str)); 324 } 325 } 326 else if(str.size() > 2 && str[0] == '-' && str[1] == '-' && isUInt(str.substr(2))){ 327 unsigned int n = toUInt(str.substr(2)); 328 for(unsigned int i=0;i<n;i++){ 329 if(!(is >> str)) 330 return false; 331 if(!isReal(str)){ 332 is.seekg((-1)*static_cast<int>(str.size()),std::ios::cur); 333 is.clear(); 334 return false; 335 } 336 v.push_back(toReal(str)); 337 } 338 return true; 339 } 340 is.seekg((-1)*static_cast<int>(str.size()),std::ios::cur); 341 is.clear(); 342 return true; 343 } 344 345 //_____________________________________________________________________ isBlank isBlank(const string & word)346 bool isBlank(const string& word){ 347 return (word.begin() == std::find_if(word.begin(),word.end(),ProtoMol::isblankchar)); 348 } 349 350 //_____________________________________________________________________ isblankchar isblankchar(char c)351 bool isblankchar(char c){ 352 return (c == ' ' || c == '\t' || c == '\n' || c == '\r'); 353 } 354 355 //_____________________________________________________________________ isPrintable isPrintable(const string & word)356 bool isPrintable(const string& word){ 357 return (word.begin() == std::find_if(word.begin(),word.end(),isprintablechar)); 358 } 359 //_____________________________________________________________________ isprintablechar isprintablechar(char c)360 bool isprintablechar(char c){ 361 return (isblankchar(c) || isprint(c)); 362 } 363 364 //_____________________________________________________________________ getBegin getBegin(const string & s,string::size_type n)365 string getBegin(const string& s,string::size_type n){ 366 if(s.size() <= n ) 367 return s; 368 return s.substr(0,n); 369 } 370 //_____________________________________________________________________ getEnd getEnd(const string & s,string::size_type n)371 string getEnd(const string& s,string::size_type n){ 372 const string::size_type i = s.size(); 373 if(i <= n ) 374 return s; 375 return s.substr(i-n); 376 } 377 378 //_____________________________________________________________________ getRightFill getRightFill(const string & s,string::size_type n)379 string getRightFill(const string& s,string::size_type n){ 380 const string::size_type i = s.size(); 381 if(i < n ) 382 return s+string(n-i,' '); 383 return s.substr(0,n); 384 } 385 //_____________________________________________________________________ getLeftFill getLeftFill(const string & s,string::size_type n)386 string getLeftFill(const string& s,string::size_type n){ 387 const string::size_type i = s.size(); 388 if(i < n ) 389 return string(n-i,' ')+s; 390 return s.substr(0,n); 391 } 392 393 //_____________________________________________________________________ removeBeginEndBlanks removeBeginEndBlanks(const string & s)394 string removeBeginEndBlanks(const string& s){ 395 string::size_type a = s.find_first_not_of(" \t"); 396 if(a == string::npos) 397 return ""; 398 return string(&s[a],&s[s.find_last_not_of(" \t")+1]); 399 } 400 401 //_____________________________________________________________________ ltstrNocase operator ()(const string & s1,const string & s2) const402 bool ltstrNocase::operator()(const string& s1, const string& s2) const{ 403 return strcmp(uppercase(s1).c_str(),uppercase(s2).c_str()) < 0; 404 } 405 406 //_____________________________________________________________________ ltstrNocaseOp ltstrNocaseOp(const string & s1,const string & s2)407 bool ltstrNocaseOp (const string& s1, const string& s2){ 408 return strcmp(uppercase(s1).c_str(),uppercase(s2).c_str()) < 0; 409 } 410 411 //_____________________________________________________________________ equalWildcard equalWildcard(const string & wildcard,const string & name)412 int equalWildcard(const string& wildcard, const string& name){ 413 414 // Match with no wildcards 415 if(wildcard == name){ 416 return 2; 417 } 418 419 // Return if no wildcards found 420 if(find(wildcard.begin(),wildcard.end(),'*') == wildcard.end() && 421 find(wildcard.begin(),wildcard.end(),'%') == wildcard.end() && 422 find(wildcard.begin(),wildcard.end(),'#') == wildcard.end() && 423 find(wildcard.begin(),wildcard.end(),'+') == wildcard.end()){ 424 return 0; 425 } 426 427 // Move to first wildcard 428 unsigned int pos = 0; 429 for(unsigned int i=0;i<wildcard.size();i++){ 430 pos = i; 431 if(wildcard[i] == '*' || 432 wildcard[i] == '%' || 433 wildcard[i] == '#' || 434 wildcard[i] == '+') 435 break; 436 if(!(i<name.size())){ 437 return 0; 438 } 439 if(wildcard[i] != name[i]){ 440 return 0; 441 } 442 } 443 444 if(pos+1==wildcard.size()){ 445 // Test if last wildcard 446 if(wildcard[pos] == '*'){ 447 return 1; 448 } 449 else if(wildcard[pos] == '#'){ 450 for(unsigned int i=pos;i<name.size();i++){ 451 if(!isdigit(name[i])){ 452 return 0; 453 } 454 } 455 return 1; 456 } 457 else if(wildcard[pos] == '%' && pos+1==name.size()){ 458 return 1; 459 } 460 else if(wildcard[pos] == '+' && pos+1==name.size() && isdigit(name[pos])){ 461 return 1; 462 } 463 } 464 else { 465 // Recursive test if inside wildcard 466 if(wildcard[pos] == '*'){ 467 int ok = 0; 468 for(unsigned int i=pos;i<=name.size();i++){ 469 if(equalWildcard(string(wildcard.begin()+pos+1,wildcard.end()),string(name.begin()+i,name.end())) > 0) 470 ok = 1; 471 } 472 return ok; 473 } 474 else if(wildcard[pos] == '%'){ 475 if(pos<name.size() && 476 equalWildcard(string(wildcard.begin()+pos+1,wildcard.end()),string(name.begin()+pos+1,name.end())) > 0){ 477 return 1; 478 } 479 else { 480 return 0; 481 } 482 } 483 else if(wildcard[pos] == '#'){ 484 int ok = 0; 485 for(unsigned int i=pos;i<=name.size();i++){ 486 if(equalWildcard(string(wildcard.begin()+pos+1,wildcard.end()),string(name.begin()+i,name.end())) > 0) 487 ok = 1; 488 if(i<name.size() && !isdigit(name[i])) 489 break; 490 } 491 return ok; 492 } 493 else if(wildcard[pos] == '+'){ 494 if(pos<name.size() && isdigit(name[pos]) && 495 equalWildcard(string(wildcard.begin()+pos+1,wildcard.end()),string(name.begin()+pos+1,name.end())) > 0){ 496 return 1; 497 } 498 else { 499 return 0; 500 } 501 } 502 503 } 504 return 0; 505 } 506 507 //_____________________________________________________________________ splitString splitString(const string & id)508 vector<string> splitString(const string& id){ 509 stringstream ss(id); 510 vector<string> res; 511 string str; 512 while(ss >> str){ 513 if(!str.empty()) 514 res.push_back(str); 515 } 516 return res; 517 } 518 519 //_____________________________________________________________________ mergeString mergeString(const vector<string> & id)520 string mergeString(const vector<string>& id){ 521 string res; 522 for(unsigned int i=0;i<id.size();i++){ 523 res += (i>0?" ":"")+id[i]; 524 } 525 return res; 526 } 527 528 //_____________________________________________________________________ normalizeString normalizeString(const string & word)529 string normalizeString(const string& word){ 530 stringstream ss(word); 531 string res,str; 532 while(ss >> str){ 533 if(!str.empty()) 534 res += (res.empty()?"":" ")+str; 535 } 536 return res; 537 } 538 539 } 540