]> git.lyx.org Git - features.git/blob - src/support/lstrings.C
Patch from Yves to check whether C functions are defined in std:: namespace
[features.git] / src / support / lstrings.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *        
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2000 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include <algorithm>
18
19 #include <cctype>
20 #include <cstdlib>
21
22 #include "LString.h"
23 #include "lstrings.h"
24 #include "LRegex.h"
25 #include "LAssert.h"
26
27 using std::count;
28 using std::transform;
29 #ifndef CXX_GLOBAL_CSTD
30 using std::tolower;
31 using std::toupper;
32 #endif
33
34
35 int compare_no_case(string const & s, string const & s2)
36 {
37         // ANSI C
38         string::const_iterator p = s.begin();
39         string::const_iterator p2 = s2.begin();
40
41         while (p != s.end() && p2 != s2.end()) {
42                 int const lc1 = tolower(*p);
43                 int const lc2 = tolower(*p2);
44                 if (lc1 != lc2)
45                         return (lc1 < lc2) ? -1 : 1;
46                 ++p;
47                 ++p2;
48         }
49         
50         if (s.size() == s2.size())
51                 return 0;
52         if (s.size() < s2.size())
53                 return -1;
54         return 1;
55 }
56
57
58 int compare_no_case(string const & s, string const & s2, unsigned int len)
59 {
60         string::const_iterator p = s.begin();
61         string::const_iterator p2 = s2.begin();
62         unsigned int i = 0;
63         while (i < len && p != s.end() && p2 != s2.end()) {
64                 int const lc1 = tolower(*p);
65                 int const lc2 = tolower(*p2);
66                 if (lc1 != lc2)
67                         return (lc1 < lc2) ? -1 : 1;
68                 ++i;
69                 ++p;
70                 ++p2;
71         }
72         if (s.size() == s2.size())
73                 return 0;
74         if (s.size() < s2.size())
75                 return -1;
76         return 1;
77 }
78
79
80 bool isStrInt(string const & str)
81 {
82         if (str.empty()) return false;
83        
84         // Remove leading and trailing white space chars.
85         string const tmpstr = frontStrip(strip(str, ' '), ' ');
86         if (tmpstr.empty()) return false;
87        
88         string::const_iterator cit = tmpstr.begin();
89         if ((*cit) == '-') ++cit;
90         string::const_iterator end = tmpstr.end();
91         for (; cit != end; ++cit) {
92                 if (!isdigit((*cit))) return false;
93         }
94         return true;
95 }
96
97
98 int strToInt(string const & str)
99 {
100         if (isStrInt(str)) {
101                 // Remove leading and trailing white space chars.
102                 string const tmpstr = frontStrip(strip(str, ' '), ' ');
103                 // Do the conversion proper.
104                 return lyx::atoi(tmpstr);
105         } else {
106                 return 0;
107         }
108 }
109
110
111 bool isStrDbl(string const & str)
112 {
113         if (str.empty()) return false;
114         
115         // Remove leading and trailing white space chars.
116         string const tmpstr = frontStrip(strip(str, ' '), ' ');
117         if (tmpstr.empty()) return false;
118         //      if (1 < tmpstr.count('.')) return false;
119
120         string::const_iterator cit = tmpstr.begin();
121         bool found_dot(false);
122         if ((*cit) == '-') ++cit;
123         string::const_iterator end = tmpstr.end();
124         for (; cit != end; ++cit) {
125                 if (!isdigit((*cit))
126                     && '.' != (*cit)) {
127                         return false;
128                 }
129                 if ('.' == (*cit)) {
130                         if (found_dot) {
131                                 return false;
132                         } else {
133                                 found_dot = true;
134                         }
135                 }
136         }
137         return true;
138 }
139
140
141 double strToDbl(string const & str)
142 {
143         if (isStrDbl(str)) {
144                 // Remove leading and trailing white space chars.
145                 string const tmpstr = frontStrip(strip(str, ' '), ' ');
146                 // Do the conversion proper.
147                 return ::atof(tmpstr.c_str());
148         } else {
149                 return 0.0;
150         }
151 }
152
153
154 char lowercase(char c) 
155
156         return char( tolower(c) ); 
157 }
158
159
160 char uppercase(char c) 
161
162         return char( toupper(c) ); 
163 }
164
165
166 string const lowercase(string const & a)
167 {
168         string tmp(a);
169 #if 1
170         string::iterator result = tmp.begin();
171         string::iterator end = tmp.end();
172         for (string::iterator first = tmp.begin();
173              first != end; ++first, ++result) {
174                 *result = lowercase(*first);
175         }
176 #else
177         // We want to use this one. (Lgb)
178         transform(tmp.begin(), tmp.end(), tmp.begin(), tolower);
179 #endif
180         return tmp;
181 }
182
183
184 string const uppercase(string const & a)
185 {
186         string tmp(a);
187 #if 1
188         string::iterator result = tmp.begin();
189         string::iterator end = tmp.end();
190         for (string::iterator first = tmp.begin();
191              first != end; ++first, ++result) {
192                 *result = uppercase(*first);
193         }
194 #else
195         // We want to use this one. (Lgb)
196         transform(tmp.begin(), tmp.end(), tmp.begin(), toupper);
197 #endif
198         return tmp;
199 }
200
201
202 bool prefixIs(string const & a, char const * pre)
203 {
204         Assert(pre);
205         
206         size_t const l = strlen(pre);
207         string::size_type const alen = a.length();
208         
209         if (l > alen || a.empty())
210                 return false;
211         else {
212 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
213                 // Delete this code when the compilers get a bit better.
214                 return ::strncmp(a.c_str(), pre, l) == 0;
215 #else
216                 // This is the code that we really want to use
217                 // but until gcc ships with a basic_string that
218                 // implements std::string correctly we have to
219                 // use the code above.
220                 return a.compare(0, l, pre, l) == 0;
221 #endif
222         }
223 }
224
225
226 bool prefixIs(string const & a, string const & pre)
227 {
228         string::size_type const prelen = pre.length();
229         string::size_type const alen = a.length();
230         
231         if (prelen < alen || a.empty())
232                 return false;
233         else {
234 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
235                 return ::strncmp(a.c_str(), pre.c_str(), prelen) == 0;
236 #else
237                 return a.compare(0, prelen, pre) == 0;
238 #endif
239         }
240 }
241
242
243 bool suffixIs(string const & a, char c)
244 {
245         if (a.empty()) return false;
246         return a[a.length() - 1] == c;
247 }
248
249
250 bool suffixIs(string const & a, char const * suf)
251 {
252         Assert(suf);
253         
254         size_t const suflen = strlen(suf);
255         if (suflen > a.length())
256                 return false;
257         else {
258 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
259                 // Delete this code when the compilers get a bit better.
260                 string tmp(a, a.length() - suflen);
261                 return ::strncmp(tmp.c_str(), suf, suflen) == 0;
262 #else
263                 // This is the code that we really want to use
264                 // but until gcc ships with a basic_string that
265                 // implements std::string correctly we have to
266                 // use the code above.
267                 return a.compare(a.length() - suflen, suflen, suf) == 0;
268 #endif
269         }
270 }
271
272
273 bool suffixIs(string const & a, string const & suf)
274 {
275         string::size_type const suflen = suf.length();
276         string::size_type const alen = a.length();
277         
278         if (suflen > alen) {
279                 return false;
280         } else {
281 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
282                 string tmp(a, alen - suflen);
283                 return ::strncmp(tmp.c_str(), suf.c_str(), suflen) == 0;
284 #else
285                 return a.compare(alen - suflen, suflen, suf) == 0;
286 #endif
287         }
288 }
289
290
291 bool contains(char const * a, string const & b)
292 {
293         Assert(a);
294         string const at(a);
295         return contains(at, b);
296 }
297
298
299 bool contains(string const & a, char const * b)
300 {
301         Assert(b);
302         string const bt(b);
303         return contains(a, bt);
304 }
305
306
307 bool contains(string const & a, string const & b)
308 {
309         if (a.empty())
310                 return false;
311         return a.find(b) != string::npos;
312 }
313
314
315 bool contains(char const * a, char const * b)
316 {
317         Assert(a && b);
318         string const at(a);
319         string const bt(b);
320         return contains(at, bt);
321 }
322
323
324 bool containsOnly(string const & s, char const * cset)
325 {
326         Assert(cset);
327         
328         return s.find_first_not_of(cset) == string::npos;
329 }
330
331
332 bool containsOnly(string const & s, string const & cset)
333 {
334         return s.find_first_not_of(cset) == string::npos;
335 }
336
337
338 bool containsOnly(char const * s, char const * cset)
339 {
340         Assert(s && cset);
341         
342         return string(s).find_first_not_of(cset) == string::npos;
343 }
344
345
346 bool containsOnly(char const * s, string const & cset)
347 {
348         Assert(s);
349         
350         return string(s).find_first_not_of(cset) == string::npos;
351 }
352
353
354 string::size_type countChar(string const & a, char c)
355 {
356 #ifdef HAVE_STD_COUNT
357         return count(a.begin(), a.end(), c);
358 #else
359         unsigned int n = 0;
360         count(a.begin(), a.end(), c, n);
361         return n;
362 #endif
363 }
364
365
366 // ale970405+lasgoutt-970425
367 // rewritten to use new string (Lgb)
368 string const token(string const & a, char delim, int n)
369 {
370         if (a.empty()) return string();
371         
372         string::size_type k = 0;
373         string::size_type i = 0;
374
375         // Find delimiter or end of string
376         for (; n--;)
377                 if ((i = a.find(delim, i)) == string::npos)
378                         break;
379                 else
380                         ++i; // step delim
381         // i is now the n'th delim (or string::npos)
382         if (i == string::npos) return string();
383         k = a.find(delim, i);
384         // k is now the n'th + 1 delim (or string::npos)
385
386         return a.substr(i, k - i);
387 }
388
389
390 // this could probably be faster and/or cleaner, but it seems to work (JMarc)
391 // rewritten to use new string (Lgb)
392 int tokenPos(string const & a, char delim, string const & tok)
393 {
394         int i = 0;
395         string str(a);
396         string tmptok;
397
398         while (!str.empty()) {
399                 str = split(str, tmptok, delim);
400                 if (tok == tmptok)
401                         return i;
402                 ++i;
403         }
404         return -1;
405 }
406
407
408 bool regexMatch(string const & a, string const & pattern)
409 {
410         // We massage the pattern a bit so that the usual
411         // shell pattern we all are used to will work.
412         // One nice thing about using a real regex is that
413         // things like "*.*[^~]" will work also.
414         // build the regex string.
415         string regex(pattern);
416         regex = subst(regex, ".", "\\.");
417         regex = subst(regex, "*", ".*");
418         LRegex reg(regex);
419         return reg.exact_match(a);
420 }
421
422
423 string const subst(string const & a, char oldchar, char newchar)
424 {
425         string tmp(a);
426         string::iterator lit = tmp.begin();
427         string::iterator end = tmp.end();
428         for (; lit != end; ++lit)
429                 if ((*lit) == oldchar)
430                         (*lit) = newchar;
431         return tmp;
432 }
433
434
435 string const subst(string const & a,
436              char const * oldstr, string const & newstr)
437 {
438         Assert(oldstr);
439         
440         string lstr(a);
441         string::size_type i = 0;
442         string::size_type olen = strlen(oldstr);
443         while((i = lstr.find(oldstr, i)) != string::npos) {
444                 lstr.replace(i, olen, newstr);
445                 i += newstr.length(); // We need to be sure that we dont
446                 // use the same i over and over again.
447         }
448         return lstr;
449 }
450
451
452 string const subst(string const & a,
453                    string const & oldstr, string const & newstr)
454 {
455         string lstr(a);
456         string::size_type i = 0;
457         string::size_type const olen = oldstr.length();
458         while((i = lstr.find(oldstr, i)) != string::npos) {
459                 lstr.replace(i, olen, newstr);
460                 i += newstr.length(); // We need to be sure that we dont
461                 // use the same i over and over again.
462         }
463         return lstr;
464 }
465
466
467 string const strip(string const & a, char c)
468 {
469         if (a.empty()) return a;
470         string tmp(a);
471         string::size_type i = tmp.find_last_not_of(c);
472         if (i == a.length() - 1) return tmp; // no c's at end of a
473         if (i != string::npos) 
474                 tmp.erase(i + 1, string::npos);
475         else
476                 tmp.erase(); // only c in the whole string
477         return tmp;
478 }
479
480
481 string const frontStrip(string const & a, char const * p)
482 {
483         Assert(p);
484         
485         if (a.empty() || !*p) return a;
486         string tmp(a);
487         string::size_type i = tmp.find_first_not_of(p);
488         if (i > 0)
489                 tmp.erase(0, i);
490         return tmp;
491 }
492
493
494 string const frontStrip(string const & a, char c)
495 {
496         if (a.empty()) return a;
497         string tmp(a);
498         string::size_type i = tmp.find_first_not_of(c);
499         if (i > 0)
500                 tmp.erase(0, i);
501         return tmp;
502 }
503
504
505 string const split(string const & a, string & piece, char delim)
506 {
507         string tmp;
508         string::size_type i = a.find(delim);
509         if (i == a.length() - 1) {
510                 piece = a.substr(0, i);
511         } else if (i != string::npos) {
512                 piece = a.substr(0, i);
513                 tmp = a.substr(i + 1);
514         } else if (i == 0) {
515                 piece.erase();
516                 tmp = a.substr(i + 1);
517         } else {
518                 piece = a;
519         }
520         return tmp;
521 }
522
523
524 string const split(string const & a, char delim)
525 {
526         string tmp;
527         string::size_type i = a.find(delim);
528         if (i != string::npos) // found delim
529                 tmp = a.substr(i + 1);
530         return tmp;
531 }
532
533
534 // ale970521
535 string const rsplit(string const & a, string & piece, char delim)
536 {
537         string tmp;
538         string::size_type i = a.rfind(delim);
539         if (i != string::npos) { // delimiter was found
540                 piece = a.substr(0, i);
541                 tmp = a.substr(i + 1);
542         } else { // delimter was not found
543                 piece.erase();
544         }
545         return tmp;
546 }