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
31 #ifndef CXX_GLOBAL_CSTD
38 int compare_no_case(string const & s, string const & s2)
40 string::const_iterator p = s.begin();
41 string::const_iterator p2 = s2.begin();
43 while (p != s.end() && p2 != s2.end()) {
44 int const lc1 = tolower(*p);
45 int const lc2 = tolower(*p2);
47 return (lc1 < lc2) ? -1 : 1;
52 if (s.size() == s2.size())
54 if (s.size() < s2.size())
61 int ascii_tolower(int c) {
62 if (c >= 'A' && c <= 'Z')
69 int compare_ascii_no_case(string const & s, string const & s2)
71 string::const_iterator p = s.begin();
72 string::const_iterator p2 = s2.begin();
74 while (p != s.end() && p2 != s2.end()) {
75 int const lc1 = ascii_tolower(*p);
76 int const lc2 = ascii_tolower(*p2);
78 return (lc1 < lc2) ? -1 : 1;
83 if (s.size() == s2.size())
85 if (s.size() < s2.size())
91 int compare_no_case(string const & s, string const & s2, unsigned int len)
93 string::const_iterator p = s.begin();
94 string::const_iterator p2 = s2.begin();
96 while (i < len && p != s.end() && p2 != s2.end()) {
97 int const lc1 = tolower(*p);
98 int const lc2 = tolower(*p2);
100 return (lc1 < lc2) ? -1 : 1;
106 if (s.size() >= len && s2.size() >= len)
108 if (s.size() < s2.size())
114 bool isStrInt(string const & str)
116 if (str.empty()) return false;
118 // Remove leading and trailing white space chars.
119 string const tmpstr = frontStrip(strip(str, ' '), ' ');
120 if (tmpstr.empty()) return false;
122 string::const_iterator cit = tmpstr.begin();
123 if ((*cit) == '-') ++cit;
124 string::const_iterator end = tmpstr.end();
125 for (; cit != end; ++cit) {
126 if (!isdigit((*cit))) return false;
132 bool isStrUnsignedInt(string const & str)
134 if (str.empty()) return false;
136 // Remove leading and trailing white space chars.
137 string const tmpstr = frontStrip(strip(str, ' '), ' ');
138 if (tmpstr.empty()) return false;
140 string::const_iterator cit = tmpstr.begin();
141 string::const_iterator end = tmpstr.end();
142 for (; cit != end; ++cit) {
143 if (!isdigit((*cit))) return false;
149 int strToInt(string const & str)
152 // Remove leading and trailing white space chars.
153 string const tmpstr = frontStrip(strip(str, ' '), ' ');
154 // Do the conversion proper.
155 return lyx::atoi(tmpstr);
162 unsigned int strToUnsignedInt(string const & str)
164 if (isStrUnsignedInt(str)) {
165 // Remove leading and trailing white space chars.
166 string const tmpstr = frontStrip(strip(str, ' '), ' ');
167 // Do the conversion proper.
168 return lyx::atoi(tmpstr);
175 bool isStrDbl(string const & str)
177 if (str.empty()) return false;
179 // Remove leading and trailing white space chars.
180 string const tmpstr = frontStrip(strip(str, ' '), ' ');
181 if (tmpstr.empty()) return false;
182 // if (1 < tmpstr.count('.')) return false;
184 string::const_iterator cit = tmpstr.begin();
185 bool found_dot(false);
186 if ((*cit) == '-') ++cit;
187 string::const_iterator end = tmpstr.end();
188 for (; cit != end; ++cit) {
205 double strToDbl(string const & str)
208 // Remove leading and trailing white space chars.
209 string const tmpstr = frontStrip(strip(str, ' '), ' ');
210 // Do the conversion proper.
211 return ::atof(tmpstr.c_str());
218 char lowercase(char c)
220 return char(tolower(c));
224 char uppercase(char c)
226 return char(toupper(c));
232 // since we cannot use std::tolower and std::toupper directly in the
233 // calls to std::transform yet, we use these helper clases. (Lgb)
235 struct local_lowercase {
236 char operator()(char c) const {
241 struct local_uppercase {
242 char operator()(char c) const {
247 } // end of anon namespace
249 string const lowercase(string const & a)
252 transform(tmp.begin(), tmp.end(), tmp.begin(), local_lowercase());
256 string const uppercase(string const & a)
259 transform(tmp.begin(), tmp.end(), tmp.begin(), local_uppercase());
264 bool prefixIs(string const & a, char const * pre)
268 size_t const l = strlen(pre);
269 string::size_type const alen = a.length();
271 if (l > alen || a.empty())
274 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
275 // Delete this code when the compilers get a bit better.
276 return ::strncmp(a.c_str(), pre, l) == 0;
278 // This is the code that we really want to use
279 // but until gcc ships with a basic_string that
280 // implements std::string correctly we have to
281 // use the code above.
282 return a.compare(0, l, pre, l) == 0;
288 bool prefixIs(string const & a, string const & pre)
290 string::size_type const prelen = pre.length();
291 string::size_type const alen = a.length();
293 if (prelen > alen || a.empty())
296 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
297 return ::strncmp(a.c_str(), pre.c_str(), prelen) == 0;
299 return a.compare(0, prelen, pre) == 0;
305 bool suffixIs(string const & a, char c)
307 if (a.empty()) return false;
308 return a[a.length() - 1] == c;
312 bool suffixIs(string const & a, char const * suf)
316 size_t const suflen = strlen(suf);
317 string::size_type const alen = a.length();
322 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
323 // Delete this code when the compilers get a bit better.
324 string tmp(a, alen - suflen);
325 return ::strncmp(tmp.c_str(), suf, suflen) == 0;
327 // This is the code that we really want to use
328 // but until gcc ships with a basic_string that
329 // implements std::string correctly we have to
330 // use the code above.
331 return a.compare(alen - suflen, suflen, suf) == 0;
337 bool suffixIs(string const & a, string const & suf)
339 string::size_type const suflen = suf.length();
340 string::size_type const alen = a.length();
345 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
346 string tmp(a, alen - suflen);
347 return ::strncmp(tmp.c_str(), suf.c_str(), suflen) == 0;
349 return a.compare(alen - suflen, suflen, suf) == 0;
355 bool contains(char const * a, string const & b)
359 return contains(at, b);
363 bool contains(string const & a, char const * b)
367 return contains(a, bt);
371 bool contains(string const & a, string const & b)
375 return a.find(b) != string::npos;
379 bool contains(string const & a, char b)
383 return a.find(b) != string::npos;
387 bool contains(char const * a, char const * b)
392 return contains(at, bt);
396 bool containsOnly(string const & s, char const * cset)
400 return s.find_first_not_of(cset) == string::npos;
404 bool containsOnly(string const & s, string const & cset)
406 return s.find_first_not_of(cset) == string::npos;
410 bool containsOnly(char const * s, char const * cset)
412 lyx::Assert(s && cset);
414 return string(s).find_first_not_of(cset) == string::npos;
418 bool containsOnly(char const * s, string const & cset)
422 return string(s).find_first_not_of(cset) == string::npos;
426 // ale970405+lasgoutt-970425
427 // rewritten to use new string (Lgb)
428 string const token(string const & a, char delim, int n)
430 if (a.empty()) return string();
432 string::size_type k = 0;
433 string::size_type i = 0;
435 // Find delimiter or end of string
437 if ((i = a.find(delim, i)) == string::npos)
441 // i is now the n'th delim (or string::npos)
442 if (i == string::npos) return string();
443 k = a.find(delim, i);
444 // k is now the n'th + 1 delim (or string::npos)
446 return a.substr(i, k - i);
450 // this could probably be faster and/or cleaner, but it seems to work (JMarc)
451 // rewritten to use new string (Lgb)
452 int tokenPos(string const & a, char delim, string const & tok)
458 while (!str.empty()) {
459 str = split(str, tmptok, delim);
468 bool regexMatch(string const & a, string const & pattern)
470 // We massage the pattern a bit so that the usual
471 // shell pattern we all are used to will work.
472 // One nice thing about using a real regex is that
473 // things like "*.*[^~]" will work also.
474 // build the regex string.
475 string regex(pattern);
476 regex = subst(regex, ".", "\\.");
477 regex = subst(regex, "*", ".*");
479 return reg.exact_match(a);
483 string const subst(string const & a, char oldchar, char newchar)
486 string::iterator lit = tmp.begin();
487 string::iterator end = tmp.end();
488 for (; lit != end; ++lit)
489 if ((*lit) == oldchar)
495 string const subst(string const & a,
496 char const * oldstr, string const & newstr)
501 string::size_type i = 0;
502 string::size_type olen = strlen(oldstr);
503 while ((i = lstr.find(oldstr, i)) != string::npos) {
504 lstr.replace(i, olen, newstr);
505 i += newstr.length(); // We need to be sure that we dont
506 // use the same i over and over again.
512 string const subst(string const & a,
513 string const & oldstr, string const & newstr)
516 string::size_type i = 0;
517 string::size_type const olen = oldstr.length();
518 while ((i = lstr.find(oldstr, i)) != string::npos) {
519 lstr.replace(i, olen, newstr);
520 i += newstr.length(); // We need to be sure that we dont
521 // use the same i over and over again.
527 string const strip(string const & a, char c)
529 if (a.empty()) return a;
531 string::size_type i = tmp.find_last_not_of(c);
532 if (i == a.length() - 1) return tmp; // no c's at end of a
533 if (i != string::npos)
534 tmp.erase(i + 1, string::npos);
535 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
536 /// Needed for broken string::find_last_not_of
537 else if (tmp[0] != c) {
538 if (a.length() == 1) return tmp;
539 tmp.erase(1, string::npos);
543 tmp.erase(); // only c in the whole string
548 string const frontStrip(string const & a, char const * p)
552 if (a.empty() || !*p) return a;
554 string::size_type i = tmp.find_first_not_of(p);
561 string const frontStrip(string const & a, char c)
563 if (a.empty()) return a;
565 string::size_type i = tmp.find_first_not_of(c);
572 string const split(string const & a, string & piece, char delim)
575 string::size_type i = a.find(delim);
576 if (i == a.length() - 1) {
577 piece = a.substr(0, i);
578 } else if (i != string::npos) {
579 piece = a.substr(0, i);
580 tmp = a.substr(i + 1);
583 tmp = a.substr(i + 1);
591 string const split(string const & a, char delim)
594 string::size_type i = a.find(delim);
595 if (i != string::npos) // found delim
596 tmp = a.substr(i + 1);
602 string const rsplit(string const & a, string & piece, char delim)
605 string::size_type i = a.rfind(delim);
606 if (i != string::npos) { // delimiter was found
607 piece = a.substr(0, i);
608 tmp = a.substr(i + 1);
609 } else { // delimter was not found
616 // This function escapes 8-bit characters and other problematic
617 // characters that cause problems in latex labels.
618 string const escape(string const & lab)
620 char hexdigit[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
621 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
623 for (string::size_type i = 0; i < lab.length(); ++i) {
624 unsigned char c= lab[i];
625 if (c >= 128 || c == '=' || c == '%') {
627 enc += hexdigit[c>>4];
628 enc += hexdigit[c & 15];