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