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
22 #include <boost/regex.hpp>
33 #ifndef CXX_GLOBAL_CSTD
40 int compare_no_case(string const & s, string const & s2)
42 string::const_iterator p = s.begin();
43 string::const_iterator p2 = s2.begin();
45 while (p != s.end() && p2 != s2.end()) {
46 int const lc1 = tolower(*p);
47 int const lc2 = tolower(*p2);
49 return (lc1 < lc2) ? -1 : 1;
54 if (s.size() == s2.size())
56 if (s.size() < s2.size())
63 int ascii_tolower(int c) {
64 if (c >= 'A' && c <= 'Z')
71 int compare_ascii_no_case(string const & s, string const & s2)
73 string::const_iterator p = s.begin();
74 string::const_iterator p2 = s2.begin();
76 while (p != s.end() && p2 != s2.end()) {
77 int const lc1 = ascii_tolower(*p);
78 int const lc2 = ascii_tolower(*p2);
80 return (lc1 < lc2) ? -1 : 1;
85 if (s.size() == s2.size())
87 if (s.size() < s2.size())
93 int compare_no_case(string const & s, string const & s2, unsigned int len)
95 string::const_iterator p = s.begin();
96 string::const_iterator p2 = s2.begin();
98 while (i < len && p != s.end() && p2 != s2.end()) {
99 int const lc1 = tolower(*p);
100 int const lc2 = tolower(*p2);
102 return (lc1 < lc2) ? -1 : 1;
108 if (s.size() >= len && s2.size() >= len)
110 if (s.size() < s2.size())
116 bool isStrInt(string const & str)
118 if (str.empty()) return false;
120 // Remove leading and trailing white space chars.
121 string const tmpstr = frontStrip(strip(str, ' '), ' ');
122 if (tmpstr.empty()) return false;
124 string::const_iterator cit = tmpstr.begin();
125 if ((*cit) == '-') ++cit;
126 string::const_iterator end = tmpstr.end();
127 for (; cit != end; ++cit) {
128 if (!isdigit((*cit))) return false;
134 bool isStrUnsignedInt(string const & str)
136 if (str.empty()) return false;
138 // Remove leading and trailing white space chars.
139 string const tmpstr = frontStrip(strip(str, ' '), ' ');
140 if (tmpstr.empty()) return false;
142 string::const_iterator cit = tmpstr.begin();
143 string::const_iterator end = tmpstr.end();
144 for (; cit != end; ++cit) {
145 if (!isdigit((*cit))) return false;
151 int strToInt(string const & str)
154 // Remove leading and trailing white space chars.
155 string const tmpstr = frontStrip(strip(str, ' '), ' ');
156 // Do the conversion proper.
157 return lyx::atoi(tmpstr);
164 unsigned int strToUnsignedInt(string const & str)
166 if (isStrUnsignedInt(str)) {
167 // Remove leading and trailing white space chars.
168 string const tmpstr = frontStrip(strip(str, ' '), ' ');
169 // Do the conversion proper.
170 return lyx::atoi(tmpstr);
177 bool isStrDbl(string const & str)
179 if (str.empty()) return false;
181 // Remove leading and trailing white space chars.
182 string const tmpstr = frontStrip(strip(str, ' '), ' ');
183 if (tmpstr.empty()) return false;
184 // if (1 < tmpstr.count('.')) return false;
186 string::const_iterator cit = tmpstr.begin();
187 bool found_dot(false);
188 if ((*cit) == '-') ++cit;
189 string::const_iterator end = tmpstr.end();
190 for (; cit != end; ++cit) {
207 double strToDbl(string const & str)
210 // Remove leading and trailing white space chars.
211 string const tmpstr = frontStrip(strip(str, ' '), ' ');
212 // Do the conversion proper.
213 return ::atof(tmpstr.c_str());
220 char lowercase(char c)
222 return char(tolower(c));
226 char uppercase(char c)
228 return char(toupper(c));
234 // since we cannot use std::tolower and std::toupper directly in the
235 // calls to std::transform yet, we use these helper clases. (Lgb)
237 struct local_lowercase {
238 char operator()(char c) const {
243 struct local_uppercase {
244 char operator()(char c) const {
249 } // end of anon namespace
251 string const lowercase(string const & a)
254 transform(tmp.begin(), tmp.end(), tmp.begin(), local_lowercase());
258 string const uppercase(string const & a)
261 transform(tmp.begin(), tmp.end(), tmp.begin(), local_uppercase());
266 bool prefixIs(string const & a, char const * pre)
270 size_t const l = strlen(pre);
271 string::size_type const alen = a.length();
273 if (l > alen || a.empty())
276 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
277 // Delete this code when the compilers get a bit better.
278 return ::strncmp(a.c_str(), pre, l) == 0;
280 // This is the code that we really want to use
281 // but until gcc ships with a basic_string that
282 // implements std::string correctly we have to
283 // use the code above.
284 return a.compare(0, l, pre, l) == 0;
290 bool prefixIs(string const & a, string const & pre)
292 string::size_type const prelen = pre.length();
293 string::size_type const alen = a.length();
295 if (prelen > alen || a.empty())
298 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
299 return ::strncmp(a.c_str(), pre.c_str(), prelen) == 0;
301 return a.compare(0, prelen, pre) == 0;
307 bool suffixIs(string const & a, char c)
309 if (a.empty()) return false;
310 return a[a.length() - 1] == c;
314 bool suffixIs(string const & a, char const * suf)
318 size_t const suflen = strlen(suf);
319 string::size_type const alen = a.length();
324 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
325 // Delete this code when the compilers get a bit better.
326 string tmp(a, alen - suflen);
327 return ::strncmp(tmp.c_str(), suf, suflen) == 0;
329 // This is the code that we really want to use
330 // but until gcc ships with a basic_string that
331 // implements std::string correctly we have to
332 // use the code above.
333 return a.compare(alen - suflen, suflen, suf) == 0;
339 bool suffixIs(string const & a, string const & suf)
341 string::size_type const suflen = suf.length();
342 string::size_type const alen = a.length();
347 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
348 string tmp(a, alen - suflen);
349 return ::strncmp(tmp.c_str(), suf.c_str(), suflen) == 0;
351 return a.compare(alen - suflen, suflen, suf) == 0;
357 bool contains(char const * a, string const & b)
361 return contains(at, b);
365 bool contains(string const & a, char const * b)
369 return contains(a, bt);
373 bool contains(string const & a, string const & b)
377 return a.find(b) != string::npos;
381 bool contains(string const & a, char b)
385 return a.find(b) != string::npos;
389 bool contains(char const * a, char const * b)
394 return contains(at, bt);
398 bool containsOnly(string const & s, char const * cset)
402 return s.find_first_not_of(cset) == string::npos;
406 bool containsOnly(string const & s, string const & cset)
408 return s.find_first_not_of(cset) == string::npos;
412 bool containsOnly(char const * s, char const * cset)
414 lyx::Assert(s && cset);
416 return string(s).find_first_not_of(cset) == string::npos;
420 bool containsOnly(char const * s, string const & cset)
424 return string(s).find_first_not_of(cset) == string::npos;
428 // ale970405+lasgoutt-970425
429 // rewritten to use new string (Lgb)
430 string const token(string const & a, char delim, int n)
432 if (a.empty()) return string();
434 string::size_type k = 0;
435 string::size_type i = 0;
437 // Find delimiter or end of string
439 if ((i = a.find(delim, i)) == string::npos)
443 // i is now the n'th delim (or string::npos)
444 if (i == string::npos) return string();
445 k = a.find(delim, i);
446 // k is now the n'th + 1 delim (or string::npos)
448 return a.substr(i, k - i);
452 // this could probably be faster and/or cleaner, but it seems to work (JMarc)
453 // rewritten to use new string (Lgb)
454 int tokenPos(string const & a, char delim, string const & tok)
460 while (!str.empty()) {
461 str = split(str, tmptok, delim);
470 bool regexMatch(string const & a, string const & pattern)
472 // We massage the pattern a bit so that the usual
473 // shell pattern we all are used to will work.
474 // One nice thing about using a real regex is that
475 // things like "*.*[^~]" will work also.
476 // build the regex string.
477 string regex(pattern);
478 regex = subst(regex, ".", "\\.");
479 regex = subst(regex, "*", ".*");
480 boost::regex reg(regex);
481 return boost::regex_match(a, reg);
485 string const subst(string const & a, char oldchar, char newchar)
488 string::iterator lit = tmp.begin();
489 string::iterator end = tmp.end();
490 for (; lit != end; ++lit)
491 if ((*lit) == oldchar)
497 string const subst(string const & a,
498 char const * oldstr, string const & newstr)
503 string::size_type i = 0;
504 string::size_type olen = strlen(oldstr);
505 while ((i = lstr.find(oldstr, i)) != string::npos) {
506 lstr.replace(i, olen, newstr);
507 i += newstr.length(); // We need to be sure that we dont
508 // use the same i over and over again.
514 string const subst(string const & a,
515 string const & oldstr, string const & newstr)
518 string::size_type i = 0;
519 string::size_type const olen = oldstr.length();
520 while ((i = lstr.find(oldstr, i)) != string::npos) {
521 lstr.replace(i, olen, newstr);
522 i += newstr.length(); // We need to be sure that we dont
523 // use the same i over and over again.
529 string const strip(string const & a, char c)
531 if (a.empty()) return a;
533 string::size_type i = tmp.find_last_not_of(c);
534 if (i == a.length() - 1) return tmp; // no c's at end of a
535 if (i != string::npos)
536 tmp.erase(i + 1, string::npos);
537 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
538 /// Needed for broken string::find_last_not_of
539 else if (tmp[0] != c) {
540 if (a.length() == 1) return tmp;
541 tmp.erase(1, string::npos);
545 tmp.erase(); // only c in the whole string
550 string const frontStrip(string const & a, char const * p)
554 if (a.empty() || !*p) return a;
556 string::size_type i = tmp.find_first_not_of(p);
563 string const frontStrip(string const & a, char c)
565 if (a.empty()) return a;
567 string::size_type i = tmp.find_first_not_of(c);
574 string const split(string const & a, string & piece, char delim)
577 string::size_type i = a.find(delim);
578 if (i == a.length() - 1) {
579 piece = a.substr(0, i);
580 } else if (i != string::npos) {
581 piece = a.substr(0, i);
582 tmp = a.substr(i + 1);
585 tmp = a.substr(i + 1);
593 string const split(string const & a, char delim)
596 string::size_type i = a.find(delim);
597 if (i != string::npos) // found delim
598 tmp = a.substr(i + 1);
604 string const rsplit(string const & a, string & piece, char delim)
607 string::size_type i = a.rfind(delim);
608 if (i != string::npos) { // delimiter was found
609 piece = a.substr(0, i);
610 tmp = a.substr(i + 1);
611 } else { // delimter was not found
618 // This function escapes 8-bit characters and other problematic
619 // characters that cause problems in latex labels.
620 string const escape(string const & lab)
622 char hexdigit[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
623 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
625 for (string::size_type i = 0; i < lab.length(); ++i) {
626 unsigned char c= lab[i];
627 if (c >= 128 || c == '=' || c == '%') {
629 enc += hexdigit[c>>4];
630 enc += hexdigit[c & 15];
639 /// gives a vector of stringparts which have the delimiter delim
640 vector<string> const getVectorFromString(string const & str,
641 string const & delim)
646 string keys(strip(str));
648 string::size_type const idx = keys.find(delim);
649 if (idx == string::npos) {
650 vec.push_back(frontStrip(keys));
653 string const key = strip(frontStrip(keys.substr(0, idx)));
656 string::size_type const start = idx + delim.size();
657 keys = keys.substr(start);
662 // the same vice versa
663 string const getStringFromVector(vector<string> const & vec,
664 string const & delim)
668 for (vector<string>::const_iterator it = vec.begin();
669 it != vec.end(); ++it) {
670 string item = strip(frontStrip(*it));
671 if (item.empty()) continue;
673 if (i++ > 0) str += delim;