]> git.lyx.org Git - features.git/blob - src/support/lstrings.C
The big KDE reorg + fi l10n update
[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 bool isStrUnsignedInt(string const & str)
99 {
100         if (str.empty()) return false;
101        
102         // Remove leading and trailing white space chars.
103         string const tmpstr = frontStrip(strip(str, ' '), ' ');
104         if (tmpstr.empty()) return false;
105        
106         string::const_iterator cit = tmpstr.begin();
107         string::const_iterator end = tmpstr.end();
108         for (; cit != end; ++cit) {
109                 if (!isdigit((*cit))) return false;
110         }
111         return true;
112 }
113
114
115 int strToInt(string const & str)
116 {
117         if (isStrInt(str)) {
118                 // Remove leading and trailing white space chars.
119                 string const tmpstr = frontStrip(strip(str, ' '), ' ');
120                 // Do the conversion proper.
121                 return lyx::atoi(tmpstr);
122         } else {
123                 return 0;
124         }
125 }
126
127
128 unsigned int strToUnsignedInt(string const & str)
129 {
130         if (isStrUnsignedInt(str)) {
131                 // Remove leading and trailing white space chars.
132                 string const tmpstr = frontStrip(strip(str, ' '), ' ');
133                 // Do the conversion proper.
134                 return lyx::atoi(tmpstr);
135         } else {
136                 return 0;
137         }
138 }
139
140
141 bool isStrDbl(string const & str)
142 {
143         if (str.empty()) return false;
144         
145         // Remove leading and trailing white space chars.
146         string const tmpstr = frontStrip(strip(str, ' '), ' ');
147         if (tmpstr.empty()) return false;
148         //      if (1 < tmpstr.count('.')) return false;
149
150         string::const_iterator cit = tmpstr.begin();
151         bool found_dot(false);
152         if ((*cit) == '-') ++cit;
153         string::const_iterator end = tmpstr.end();
154         for (; cit != end; ++cit) {
155                 if (!isdigit((*cit))
156                     && '.' != (*cit)) {
157                         return false;
158                 }
159                 if ('.' == (*cit)) {
160                         if (found_dot) {
161                                 return false;
162                         } else {
163                                 found_dot = true;
164                         }
165                 }
166         }
167         return true;
168 }
169
170
171 double strToDbl(string const & str)
172 {
173         if (isStrDbl(str)) {
174                 // Remove leading and trailing white space chars.
175                 string const tmpstr = frontStrip(strip(str, ' '), ' ');
176                 // Do the conversion proper.
177                 return ::atof(tmpstr.c_str());
178         } else {
179                 return 0.0;
180         }
181 }
182
183
184 char lowercase(char c) 
185
186         return char( tolower(c) ); 
187 }
188
189
190 char uppercase(char c) 
191
192         return char( toupper(c) ); 
193 }
194
195
196 string const lowercase(string const & a)
197 {
198         string tmp(a);
199 #if 1
200         string::iterator result = tmp.begin();
201         string::iterator end = tmp.end();
202         for (string::iterator first = tmp.begin();
203              first != end; ++first, ++result) {
204                 *result = lowercase(*first);
205         }
206 #else
207         // We want to use this one. (Lgb)
208         transform(tmp.begin(), tmp.end(), tmp.begin(), lowercase);
209 #endif
210         return tmp;
211 }
212
213
214 string const uppercase(string const & a)
215 {
216         string tmp(a);
217 #if 1
218         string::iterator result = tmp.begin();
219         string::iterator end = tmp.end();
220         for (string::iterator first = tmp.begin();
221              first != end; ++first, ++result) {
222                 *result = uppercase(*first);
223         }
224 #else
225         // We want to use this one. (Lgb)
226         transform(tmp.begin(), tmp.end(), tmp.begin(), uppercase);
227 #endif
228         return tmp;
229 }
230
231
232 bool prefixIs(string const & a, char const * pre)
233 {
234         Assert(pre);
235         
236         size_t const l = strlen(pre);
237         string::size_type const alen = a.length();
238         
239         if (l > alen || a.empty())
240                 return false;
241         else {
242 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
243                 // Delete this code when the compilers get a bit better.
244                 return ::strncmp(a.c_str(), pre, l) == 0;
245 #else
246                 // This is the code that we really want to use
247                 // but until gcc ships with a basic_string that
248                 // implements std::string correctly we have to
249                 // use the code above.
250                 return a.compare(0, l, pre, l) == 0;
251 #endif
252         }
253 }
254
255
256 bool prefixIs(string const & a, string const & pre)
257 {
258         string::size_type const prelen = pre.length();
259         string::size_type const alen = a.length();
260         
261         if (prelen < alen || a.empty())
262                 return false;
263         else {
264 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
265                 return ::strncmp(a.c_str(), pre.c_str(), prelen) == 0;
266 #else
267                 return a.compare(0, prelen, pre) == 0;
268 #endif
269         }
270 }
271
272
273 bool suffixIs(string const & a, char c)
274 {
275         if (a.empty()) return false;
276         return a[a.length() - 1] == c;
277 }
278
279
280 bool suffixIs(string const & a, char const * suf)
281 {
282         Assert(suf);
283         
284         size_t const suflen = strlen(suf);
285         if (suflen > a.length())
286                 return false;
287         else {
288 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
289                 // Delete this code when the compilers get a bit better.
290                 string tmp(a, a.length() - suflen);
291                 return ::strncmp(tmp.c_str(), suf, suflen) == 0;
292 #else
293                 // This is the code that we really want to use
294                 // but until gcc ships with a basic_string that
295                 // implements std::string correctly we have to
296                 // use the code above.
297                 return a.compare(a.length() - suflen, suflen, suf) == 0;
298 #endif
299         }
300 }
301
302
303 bool suffixIs(string const & a, string const & suf)
304 {
305         string::size_type const suflen = suf.length();
306         string::size_type const alen = a.length();
307         
308         if (suflen > alen) {
309                 return false;
310         } else {
311 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
312                 string tmp(a, alen - suflen);
313                 return ::strncmp(tmp.c_str(), suf.c_str(), suflen) == 0;
314 #else
315                 return a.compare(alen - suflen, suflen, suf) == 0;
316 #endif
317         }
318 }
319
320
321 bool contains(char const * a, string const & b)
322 {
323         Assert(a);
324         string const at(a);
325         return contains(at, b);
326 }
327
328
329 bool contains(string const & a, char const * b)
330 {
331         Assert(b);
332         string const bt(b);
333         return contains(a, bt);
334 }
335
336
337 bool contains(string const & a, string const & b)
338 {
339         if (a.empty())
340                 return false;
341         return a.find(b) != string::npos;
342 }
343
344
345 bool contains(char const * a, char const * b)
346 {
347         Assert(a && b);
348         string const at(a);
349         string const bt(b);
350         return contains(at, bt);
351 }
352
353
354 bool containsOnly(string const & s, char const * cset)
355 {
356         Assert(cset);
357         
358         return s.find_first_not_of(cset) == string::npos;
359 }
360
361
362 bool containsOnly(string const & s, string const & cset)
363 {
364         return s.find_first_not_of(cset) == string::npos;
365 }
366
367
368 bool containsOnly(char const * s, char const * cset)
369 {
370         Assert(s && cset);
371         
372         return string(s).find_first_not_of(cset) == string::npos;
373 }
374
375
376 bool containsOnly(char const * s, string const & cset)
377 {
378         Assert(s);
379         
380         return string(s).find_first_not_of(cset) == string::npos;
381 }
382
383
384 string::size_type countChar(string const & a, char c)
385 {
386 #ifdef HAVE_STD_COUNT
387         return count(a.begin(), a.end(), c);
388 #else
389         unsigned int n = 0;
390         count(a.begin(), a.end(), c, n);
391         return n;
392 #endif
393 }
394
395
396 // ale970405+lasgoutt-970425
397 // rewritten to use new string (Lgb)
398 string const token(string const & a, char delim, int n)
399 {
400         if (a.empty()) return string();
401         
402         string::size_type k = 0;
403         string::size_type i = 0;
404
405         // Find delimiter or end of string
406         for (; n--;)
407                 if ((i = a.find(delim, i)) == string::npos)
408                         break;
409                 else
410                         ++i; // step delim
411         // i is now the n'th delim (or string::npos)
412         if (i == string::npos) return string();
413         k = a.find(delim, i);
414         // k is now the n'th + 1 delim (or string::npos)
415
416         return a.substr(i, k - i);
417 }
418
419
420 // this could probably be faster and/or cleaner, but it seems to work (JMarc)
421 // rewritten to use new string (Lgb)
422 int tokenPos(string const & a, char delim, string const & tok)
423 {
424         int i = 0;
425         string str(a);
426         string tmptok;
427
428         while (!str.empty()) {
429                 str = split(str, tmptok, delim);
430                 if (tok == tmptok)
431                         return i;
432                 ++i;
433         }
434         return -1;
435 }
436
437
438 bool regexMatch(string const & a, string const & pattern)
439 {
440         // We massage the pattern a bit so that the usual
441         // shell pattern we all are used to will work.
442         // One nice thing about using a real regex is that
443         // things like "*.*[^~]" will work also.
444         // build the regex string.
445         string regex(pattern);
446         regex = subst(regex, ".", "\\.");
447         regex = subst(regex, "*", ".*");
448         LRegex reg(regex);
449         return reg.exact_match(a);
450 }
451
452
453 string const subst(string const & a, char oldchar, char newchar)
454 {
455         string tmp(a);
456         string::iterator lit = tmp.begin();
457         string::iterator end = tmp.end();
458         for (; lit != end; ++lit)
459                 if ((*lit) == oldchar)
460                         (*lit) = newchar;
461         return tmp;
462 }
463
464
465 string const subst(string const & a,
466              char const * oldstr, string const & newstr)
467 {
468         Assert(oldstr);
469         
470         string lstr(a);
471         string::size_type i = 0;
472         string::size_type olen = strlen(oldstr);
473         while((i = lstr.find(oldstr, i)) != string::npos) {
474                 lstr.replace(i, olen, newstr);
475                 i += newstr.length(); // We need to be sure that we dont
476                 // use the same i over and over again.
477         }
478         return lstr;
479 }
480
481
482 string const subst(string const & a,
483                    string const & oldstr, string const & newstr)
484 {
485         string lstr(a);
486         string::size_type i = 0;
487         string::size_type const olen = oldstr.length();
488         while((i = lstr.find(oldstr, i)) != string::npos) {
489                 lstr.replace(i, olen, newstr);
490                 i += newstr.length(); // We need to be sure that we dont
491                 // use the same i over and over again.
492         }
493         return lstr;
494 }
495
496
497 string const strip(string const & a, char c)
498 {
499         if (a.empty()) return a;
500         string tmp(a);
501         string::size_type i = tmp.find_last_not_of(c);
502         if (i == a.length() - 1) return tmp; // no c's at end of a
503         if (i != string::npos) 
504                 tmp.erase(i + 1, string::npos);
505         else
506                 tmp.erase(); // only c in the whole string
507         return tmp;
508 }
509
510
511 string const frontStrip(string const & a, char const * p)
512 {
513         Assert(p);
514         
515         if (a.empty() || !*p) return a;
516         string tmp(a);
517         string::size_type i = tmp.find_first_not_of(p);
518         if (i > 0)
519                 tmp.erase(0, i);
520         return tmp;
521 }
522
523
524 string const frontStrip(string const & a, char c)
525 {
526         if (a.empty()) return a;
527         string tmp(a);
528         string::size_type i = tmp.find_first_not_of(c);
529         if (i > 0)
530                 tmp.erase(0, i);
531         return tmp;
532 }
533
534
535 string const split(string const & a, string & piece, char delim)
536 {
537         string tmp;
538         string::size_type i = a.find(delim);
539         if (i == a.length() - 1) {
540                 piece = a.substr(0, i);
541         } else if (i != string::npos) {
542                 piece = a.substr(0, i);
543                 tmp = a.substr(i + 1);
544         } else if (i == 0) {
545                 piece.erase();
546                 tmp = a.substr(i + 1);
547         } else {
548                 piece = a;
549         }
550         return tmp;
551 }
552
553
554 string const split(string const & a, char delim)
555 {
556         string tmp;
557         string::size_type i = a.find(delim);
558         if (i != string::npos) // found delim
559                 tmp = a.substr(i + 1);
560         return tmp;
561 }
562
563
564 // ale970521
565 string const rsplit(string const & a, string & piece, char delim)
566 {
567         string tmp;
568         string::size_type i = a.rfind(delim);
569         if (i != string::npos) { // delimiter was found
570                 piece = a.substr(0, i);
571                 tmp = a.substr(i + 1);
572         } else { // delimter was not found
573                 piece.erase();
574         }
575         return tmp;
576 }