1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2001 The LyX Team.
9 * ====================================================== */
14 #pragma implementation
30 #ifndef CXX_GLOBAL_CSTD
37 int compare_no_case(string const & s, string const & s2)
39 string::const_iterator p = s.begin();
40 string::const_iterator p2 = s2.begin();
42 while (p != s.end() && p2 != s2.end()) {
43 int const lc1 = tolower(*p);
44 int const lc2 = tolower(*p2);
46 return (lc1 < lc2) ? -1 : 1;
51 if (s.size() == s2.size())
53 if (s.size() < s2.size())
60 int ascii_tolower(int c) {
61 if (c >= 'A' && c <= 'Z')
68 int compare_ascii_no_case(string const & s, string const & s2)
70 string::const_iterator p = s.begin();
71 string::const_iterator p2 = s2.begin();
73 while (p != s.end() && p2 != s2.end()) {
74 int const lc1 = ascii_tolower(*p);
75 int const lc2 = ascii_tolower(*p2);
77 return (lc1 < lc2) ? -1 : 1;
82 if (s.size() == s2.size())
84 if (s.size() < s2.size())
90 int compare_no_case(string const & s, string const & s2, unsigned int len)
92 string::const_iterator p = s.begin();
93 string::const_iterator p2 = s2.begin();
95 while (i < len && p != s.end() && p2 != s2.end()) {
96 int const lc1 = tolower(*p);
97 int const lc2 = tolower(*p2);
99 return (lc1 < lc2) ? -1 : 1;
105 if (s.size() >= len && s2.size() >= len)
107 if (s.size() < s2.size())
113 bool isStrInt(string const & str)
115 if (str.empty()) return false;
117 // Remove leading and trailing white space chars.
118 string const tmpstr = frontStrip(strip(str, ' '), ' ');
119 if (tmpstr.empty()) return false;
121 string::const_iterator cit = tmpstr.begin();
122 if ((*cit) == '-') ++cit;
123 string::const_iterator end = tmpstr.end();
124 for (; cit != end; ++cit) {
125 if (!isdigit((*cit))) return false;
131 bool isStrUnsignedInt(string const & str)
133 if (str.empty()) return false;
135 // Remove leading and trailing white space chars.
136 string const tmpstr = frontStrip(strip(str, ' '), ' ');
137 if (tmpstr.empty()) return false;
139 string::const_iterator cit = tmpstr.begin();
140 string::const_iterator end = tmpstr.end();
141 for (; cit != end; ++cit) {
142 if (!isdigit((*cit))) return false;
148 int strToInt(string const & str)
151 // Remove leading and trailing white space chars.
152 string const tmpstr = frontStrip(strip(str, ' '), ' ');
153 // Do the conversion proper.
154 return lyx::atoi(tmpstr);
161 unsigned int strToUnsignedInt(string const & str)
163 if (isStrUnsignedInt(str)) {
164 // Remove leading and trailing white space chars.
165 string const tmpstr = frontStrip(strip(str, ' '), ' ');
166 // Do the conversion proper.
167 return lyx::atoi(tmpstr);
174 bool isStrDbl(string const & str)
176 if (str.empty()) return false;
178 // Remove leading and trailing white space chars.
179 string const tmpstr = frontStrip(strip(str, ' '), ' ');
180 if (tmpstr.empty()) return false;
181 // if (1 < tmpstr.count('.')) return false;
183 string::const_iterator cit = tmpstr.begin();
184 bool found_dot(false);
185 if ((*cit) == '-') ++cit;
186 string::const_iterator end = tmpstr.end();
187 for (; cit != end; ++cit) {
204 double strToDbl(string const & str)
207 // Remove leading and trailing white space chars.
208 string const tmpstr = frontStrip(strip(str, ' '), ' ');
209 // Do the conversion proper.
210 return ::atof(tmpstr.c_str());
217 char lowercase(char c)
219 return char( tolower(c) );
223 char uppercase(char c)
225 return char( toupper(c) );
231 // since we cannot use std::tolower and std::toupper directly in the
232 // calls to std::transform yet, we use these helper clases. (Lgb)
234 struct local_lowercase {
235 char operator()(char c) const {
240 struct local_uppercase {
241 char operator()(char c) const {
246 } // end of anon namespace
248 string const lowercase(string const & a)
251 transform(tmp.begin(), tmp.end(), tmp.begin(), local_lowercase());
255 string const uppercase(string const & a)
258 transform(tmp.begin(), tmp.end(), tmp.begin(), local_uppercase());
263 bool prefixIs(string const & a, char const * pre)
267 size_t const l = strlen(pre);
268 string::size_type const alen = a.length();
270 if (l > alen || a.empty())
273 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
274 // Delete this code when the compilers get a bit better.
275 return ::strncmp(a.c_str(), pre, l) == 0;
277 // This is the code that we really want to use
278 // but until gcc ships with a basic_string that
279 // implements std::string correctly we have to
280 // use the code above.
281 return a.compare(0, l, pre, l) == 0;
287 bool prefixIs(string const & a, string const & pre)
289 string::size_type const prelen = pre.length();
290 string::size_type const alen = a.length();
292 if (prelen > alen || a.empty())
295 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
296 return ::strncmp(a.c_str(), pre.c_str(), prelen) == 0;
298 return a.compare(0, prelen, pre) == 0;
304 bool suffixIs(string const & a, char c)
306 if (a.empty()) return false;
307 return a[a.length() - 1] == c;
311 bool suffixIs(string const & a, char const * suf)
315 size_t const suflen = strlen(suf);
316 string::size_type const alen = a.length();
321 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
322 // Delete this code when the compilers get a bit better.
323 string tmp(a, alen - suflen);
324 return ::strncmp(tmp.c_str(), suf, suflen) == 0;
326 // This is the code that we really want to use
327 // but until gcc ships with a basic_string that
328 // implements std::string correctly we have to
329 // use the code above.
330 return a.compare(alen - suflen, suflen, suf) == 0;
336 bool suffixIs(string const & a, string const & suf)
338 string::size_type const suflen = suf.length();
339 string::size_type const alen = a.length();
344 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
345 string tmp(a, alen - suflen);
346 return ::strncmp(tmp.c_str(), suf.c_str(), suflen) == 0;
348 return a.compare(alen - suflen, suflen, suf) == 0;
354 bool contains(char const * a, string const & b)
358 return contains(at, b);
362 bool contains(string const & a, char const * b)
366 return contains(a, bt);
370 bool contains(string const & a, string const & b)
374 return a.find(b) != string::npos;
378 bool contains(string const & a, char b)
382 return a.find(b) != string::npos;
386 bool contains(char const * a, char const * b)
391 return contains(at, bt);
395 bool containsOnly(string const & s, char const * cset)
399 return s.find_first_not_of(cset) == string::npos;
403 bool containsOnly(string const & s, string const & cset)
405 return s.find_first_not_of(cset) == string::npos;
409 bool containsOnly(char const * s, char const * cset)
411 lyx::Assert(s && cset);
413 return string(s).find_first_not_of(cset) == string::npos;
417 bool containsOnly(char const * s, string const & cset)
421 return string(s).find_first_not_of(cset) == string::npos;
425 string::size_type countChar(string const & a, char c)
427 #ifdef HAVE_STD_COUNT
428 return count(a.begin(), a.end(), c);
431 count(a.begin(), a.end(), c, n);
437 // ale970405+lasgoutt-970425
438 // rewritten to use new string (Lgb)
439 string const token(string const & a, char delim, int n)
441 if (a.empty()) return string();
443 string::size_type k = 0;
444 string::size_type i = 0;
446 // Find delimiter or end of string
448 if ((i = a.find(delim, i)) == string::npos)
452 // i is now the n'th delim (or string::npos)
453 if (i == string::npos) return string();
454 k = a.find(delim, i);
455 // k is now the n'th + 1 delim (or string::npos)
457 return a.substr(i, k - i);
461 // this could probably be faster and/or cleaner, but it seems to work (JMarc)
462 // rewritten to use new string (Lgb)
463 int tokenPos(string const & a, char delim, string const & tok)
469 while (!str.empty()) {
470 str = split(str, tmptok, delim);
479 bool regexMatch(string const & a, string const & pattern)
481 // We massage the pattern a bit so that the usual
482 // shell pattern we all are used to will work.
483 // One nice thing about using a real regex is that
484 // things like "*.*[^~]" will work also.
485 // build the regex string.
486 string regex(pattern);
487 regex = subst(regex, ".", "\\.");
488 regex = subst(regex, "*", ".*");
490 return reg.exact_match(a);
494 string const subst(string const & a, char oldchar, char newchar)
497 string::iterator lit = tmp.begin();
498 string::iterator end = tmp.end();
499 for (; lit != end; ++lit)
500 if ((*lit) == oldchar)
506 string const subst(string const & a,
507 char const * oldstr, string const & newstr)
512 string::size_type i = 0;
513 string::size_type olen = strlen(oldstr);
514 while((i = lstr.find(oldstr, i)) != string::npos) {
515 lstr.replace(i, olen, newstr);
516 i += newstr.length(); // We need to be sure that we dont
517 // use the same i over and over again.
523 string const subst(string const & a,
524 string const & oldstr, string const & newstr)
527 string::size_type i = 0;
528 string::size_type const olen = oldstr.length();
529 while((i = lstr.find(oldstr, i)) != string::npos) {
530 lstr.replace(i, olen, newstr);
531 i += newstr.length(); // We need to be sure that we dont
532 // use the same i over and over again.
538 string const strip(string const & a, char c)
540 if (a.empty()) return a;
542 string::size_type i = tmp.find_last_not_of(c);
543 if (i == a.length() - 1) return tmp; // no c's at end of a
544 if (i != string::npos)
545 tmp.erase(i + 1, string::npos);
546 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
547 /// Needed for broken string::find_last_not_of
548 else if (tmp[0] != c) {
549 if (a.length() == 1) return tmp;
550 tmp.erase(1, string::npos);
554 tmp.erase(); // only c in the whole string
559 string const frontStrip(string const & a, char const * p)
563 if (a.empty() || !*p) return a;
565 string::size_type i = tmp.find_first_not_of(p);
572 string const frontStrip(string const & a, char c)
574 if (a.empty()) return a;
576 string::size_type i = tmp.find_first_not_of(c);
583 string const split(string const & a, string & piece, char delim)
586 string::size_type i = a.find(delim);
587 if (i == a.length() - 1) {
588 piece = a.substr(0, i);
589 } else if (i != string::npos) {
590 piece = a.substr(0, i);
591 tmp = a.substr(i + 1);
594 tmp = a.substr(i + 1);
602 string const split(string const & a, char delim)
605 string::size_type i = a.find(delim);
606 if (i != string::npos) // found delim
607 tmp = a.substr(i + 1);
613 string const rsplit(string const & a, string & piece, char delim)
616 string::size_type i = a.rfind(delim);
617 if (i != string::npos) { // delimiter was found
618 piece = a.substr(0, i);
619 tmp = a.substr(i + 1);
620 } else { // delimter was not found
627 // This function escapes 8-bit characters and other problematic
628 // characters that cause problems in latex labels.
629 string const escape(string const & lab)
631 char hexdigit[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
632 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
634 for (string::size_type i = 0; i < lab.length(); ++i) {
635 unsigned char c= lab[i];
636 if (c >= 128 || c == '=' || c == '%') {
638 enc += hexdigit[c>>4];
639 enc += hexdigit[c & 15];