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