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