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
32 #ifndef CXX_GLOBAL_CSTD
39 int compare_no_case(string const & s, string const & s2)
41 string::const_iterator p = s.begin();
42 string::const_iterator p2 = s2.begin();
44 while (p != s.end() && p2 != s2.end()) {
45 int const lc1 = tolower(*p);
46 int const lc2 = tolower(*p2);
48 return (lc1 < lc2) ? -1 : 1;
53 if (s.size() == s2.size())
55 if (s.size() < s2.size())
62 int ascii_tolower(int c) {
63 if (c >= 'A' && c <= 'Z')
70 int compare_ascii_no_case(string const & s, string const & s2)
72 string::const_iterator p = s.begin();
73 string::const_iterator p2 = s2.begin();
75 while (p != s.end() && p2 != s2.end()) {
76 int const lc1 = ascii_tolower(*p);
77 int const lc2 = ascii_tolower(*p2);
79 return (lc1 < lc2) ? -1 : 1;
84 if (s.size() == s2.size())
86 if (s.size() < s2.size())
92 int compare_no_case(string const & s, string const & s2, unsigned int len)
94 string::const_iterator p = s.begin();
95 string::const_iterator p2 = s2.begin();
97 while (i < len && p != s.end() && p2 != s2.end()) {
98 int const lc1 = tolower(*p);
99 int const lc2 = tolower(*p2);
101 return (lc1 < lc2) ? -1 : 1;
107 if (s.size() >= len && s2.size() >= len)
109 if (s.size() < s2.size())
115 bool isStrInt(string const & str)
117 if (str.empty()) return false;
119 // Remove leading and trailing white space chars.
120 string const tmpstr = frontStrip(strip(str, ' '), ' ');
121 if (tmpstr.empty()) return false;
123 string::const_iterator cit = tmpstr.begin();
124 if ((*cit) == '-') ++cit;
125 string::const_iterator end = tmpstr.end();
126 for (; cit != end; ++cit) {
127 if (!isdigit((*cit))) return false;
133 bool isStrUnsignedInt(string const & str)
135 if (str.empty()) return false;
137 // Remove leading and trailing white space chars.
138 string const tmpstr = frontStrip(strip(str, ' '), ' ');
139 if (tmpstr.empty()) return false;
141 string::const_iterator cit = tmpstr.begin();
142 string::const_iterator end = tmpstr.end();
143 for (; cit != end; ++cit) {
144 if (!isdigit((*cit))) return false;
150 int strToInt(string const & str)
153 // Remove leading and trailing white space chars.
154 string const tmpstr = frontStrip(strip(str, ' '), ' ');
155 // Do the conversion proper.
156 return lyx::atoi(tmpstr);
163 unsigned int strToUnsignedInt(string const & str)
165 if (isStrUnsignedInt(str)) {
166 // Remove leading and trailing white space chars.
167 string const tmpstr = frontStrip(strip(str, ' '), ' ');
168 // Do the conversion proper.
169 return lyx::atoi(tmpstr);
176 bool isStrDbl(string const & str)
178 if (str.empty()) return false;
180 // Remove leading and trailing white space chars.
181 string const tmpstr = frontStrip(strip(str, ' '), ' ');
182 if (tmpstr.empty()) return false;
183 // if (1 < tmpstr.count('.')) return false;
185 string::const_iterator cit = tmpstr.begin();
186 bool found_dot(false);
187 if ((*cit) == '-') ++cit;
188 string::const_iterator end = tmpstr.end();
189 for (; cit != end; ++cit) {
206 double strToDbl(string const & str)
209 // Remove leading and trailing white space chars.
210 string const tmpstr = frontStrip(strip(str, ' '), ' ');
211 // Do the conversion proper.
212 return ::atof(tmpstr.c_str());
219 char lowercase(char c)
221 return char(tolower(c));
225 char uppercase(char c)
227 return char(toupper(c));
233 // since we cannot use std::tolower and std::toupper directly in the
234 // calls to std::transform yet, we use these helper clases. (Lgb)
236 struct local_lowercase {
237 char operator()(char c) const {
242 struct local_uppercase {
243 char operator()(char c) const {
248 } // end of anon namespace
250 string const lowercase(string const & a)
253 transform(tmp.begin(), tmp.end(), tmp.begin(), local_lowercase());
257 string const uppercase(string const & a)
260 transform(tmp.begin(), tmp.end(), tmp.begin(), local_uppercase());
265 bool prefixIs(string const & a, char const * pre)
269 size_t const l = strlen(pre);
270 string::size_type const alen = a.length();
272 if (l > alen || a.empty())
275 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
276 // Delete this code when the compilers get a bit better.
277 return ::strncmp(a.c_str(), pre, l) == 0;
279 // This is the code that we really want to use
280 // but until gcc ships with a basic_string that
281 // implements std::string correctly we have to
282 // use the code above.
283 return a.compare(0, l, pre, l) == 0;
289 bool prefixIs(string const & a, string const & pre)
291 string::size_type const prelen = pre.length();
292 string::size_type const alen = a.length();
294 if (prelen > alen || a.empty())
297 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
298 return ::strncmp(a.c_str(), pre.c_str(), prelen) == 0;
300 return a.compare(0, prelen, pre) == 0;
306 bool suffixIs(string const & a, char c)
308 if (a.empty()) return false;
309 return a[a.length() - 1] == c;
313 bool suffixIs(string const & a, char const * suf)
317 size_t const suflen = strlen(suf);
318 string::size_type const alen = a.length();
323 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
324 // Delete this code when the compilers get a bit better.
325 string tmp(a, alen - suflen);
326 return ::strncmp(tmp.c_str(), suf, suflen) == 0;
328 // This is the code that we really want to use
329 // but until gcc ships with a basic_string that
330 // implements std::string correctly we have to
331 // use the code above.
332 return a.compare(alen - suflen, suflen, suf) == 0;
338 bool suffixIs(string const & a, string const & suf)
340 string::size_type const suflen = suf.length();
341 string::size_type const alen = a.length();
346 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
347 string tmp(a, alen - suflen);
348 return ::strncmp(tmp.c_str(), suf.c_str(), suflen) == 0;
350 return a.compare(alen - suflen, suflen, suf) == 0;
356 bool contains(char const * a, string const & b)
360 return contains(at, b);
364 bool contains(string const & a, char const * b)
368 return contains(a, bt);
372 bool contains(string const & a, string const & b)
376 return a.find(b) != string::npos;
380 bool contains(string const & a, char b)
384 return a.find(b) != string::npos;
388 bool contains(char const * a, char const * b)
393 return contains(at, bt);
397 bool containsOnly(string const & s, char const * cset)
401 return s.find_first_not_of(cset) == string::npos;
405 bool containsOnly(string const & s, string const & cset)
407 return s.find_first_not_of(cset) == string::npos;
411 bool containsOnly(char const * s, char const * cset)
413 lyx::Assert(s && cset);
415 return string(s).find_first_not_of(cset) == string::npos;
419 bool containsOnly(char const * s, string const & cset)
423 return string(s).find_first_not_of(cset) == string::npos;
427 // ale970405+lasgoutt-970425
428 // rewritten to use new string (Lgb)
429 string const token(string const & a, char delim, int n)
431 if (a.empty()) return string();
433 string::size_type k = 0;
434 string::size_type i = 0;
436 // Find delimiter or end of string
438 if ((i = a.find(delim, i)) == string::npos)
442 // i is now the n'th delim (or string::npos)
443 if (i == string::npos) return string();
444 k = a.find(delim, i);
445 // k is now the n'th + 1 delim (or string::npos)
447 return a.substr(i, k - i);
451 // this could probably be faster and/or cleaner, but it seems to work (JMarc)
452 // rewritten to use new string (Lgb)
453 int tokenPos(string const & a, char delim, string const & tok)
459 while (!str.empty()) {
460 str = split(str, tmptok, delim);
469 bool regexMatch(string const & a, string const & pattern)
471 // We massage the pattern a bit so that the usual
472 // shell pattern we all are used to will work.
473 // One nice thing about using a real regex is that
474 // things like "*.*[^~]" will work also.
475 // build the regex string.
476 string regex(pattern);
477 regex = subst(regex, ".", "\\.");
478 regex = subst(regex, "*", ".*");
480 return reg.exact_match(a);
484 string const subst(string const & a, char oldchar, char newchar)
487 string::iterator lit = tmp.begin();
488 string::iterator end = tmp.end();
489 for (; lit != end; ++lit)
490 if ((*lit) == oldchar)
496 string const subst(string const & a,
497 char const * oldstr, string const & newstr)
502 string::size_type i = 0;
503 string::size_type olen = strlen(oldstr);
504 while ((i = lstr.find(oldstr, i)) != string::npos) {
505 lstr.replace(i, olen, newstr);
506 i += newstr.length(); // We need to be sure that we dont
507 // use the same i over and over again.
513 string const subst(string const & a,
514 string const & oldstr, string const & newstr)
517 string::size_type i = 0;
518 string::size_type const olen = oldstr.length();
519 while ((i = lstr.find(oldstr, i)) != string::npos) {
520 lstr.replace(i, olen, newstr);
521 i += newstr.length(); // We need to be sure that we dont
522 // use the same i over and over again.
528 string const strip(string const & a, char c)
530 if (a.empty()) return a;
532 string::size_type i = tmp.find_last_not_of(c);
533 if (i == a.length() - 1) return tmp; // no c's at end of a
534 if (i != string::npos)
535 tmp.erase(i + 1, string::npos);
536 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
537 /// Needed for broken string::find_last_not_of
538 else if (tmp[0] != c) {
539 if (a.length() == 1) return tmp;
540 tmp.erase(1, string::npos);
544 tmp.erase(); // only c in the whole string
549 string const frontStrip(string const & a, char const * p)
553 if (a.empty() || !*p) return a;
555 string::size_type i = tmp.find_first_not_of(p);
562 string const frontStrip(string const & a, char c)
564 if (a.empty()) return a;
566 string::size_type i = tmp.find_first_not_of(c);
573 string const split(string const & a, string & piece, char delim)
576 string::size_type i = a.find(delim);
577 if (i == a.length() - 1) {
578 piece = a.substr(0, i);
579 } else if (i != string::npos) {
580 piece = a.substr(0, i);
581 tmp = a.substr(i + 1);
584 tmp = a.substr(i + 1);
592 string const split(string const & a, char delim)
595 string::size_type i = a.find(delim);
596 if (i != string::npos) // found delim
597 tmp = a.substr(i + 1);
603 string const rsplit(string const & a, string & piece, char delim)
606 string::size_type i = a.rfind(delim);
607 if (i != string::npos) { // delimiter was found
608 piece = a.substr(0, i);
609 tmp = a.substr(i + 1);
610 } else { // delimter was not found
617 // This function escapes 8-bit characters and other problematic
618 // characters that cause problems in latex labels.
619 string const escape(string const & lab)
621 char hexdigit[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
622 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
624 for (string::size_type i = 0; i < lab.length(); ++i) {
625 unsigned char c= lab[i];
626 if (c >= 128 || c == '=' || c == '%') {
628 enc += hexdigit[c>>4];
629 enc += hexdigit[c & 15];
638 /// gives a vector of stringparts which have the delimiter delim
639 vector<string> const getVectorFromString(string const & str,
640 string const & delim)
645 string keys(strip(str));
647 string::size_type const idx = keys.find(delim);
648 if (idx == string::npos) {
649 vec.push_back(frontStrip(keys));
652 string const key = strip(frontStrip(keys.substr(0, idx)));
655 string::size_type const start = idx + delim.size();
656 keys = keys.substr(start);
661 // the same vice versa
662 string const getStringFromVector(vector<string> const & vec,
663 string const & delim)
667 for (vector<string>::const_iterator it = vec.begin();
668 it != vec.end(); ++it) {
669 string item = strip(frontStrip(*it));
670 if (item.empty()) continue;
672 if (i++ > 0) str += delim;