Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Utils.hh

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #ifndef RIVET_Utils_HH
00003 #define RIVET_Utils_HH 1
00004 
00005 #include <cctype>
00006 #include <algorithm>
00007 
00008 namespace Rivet {
00009 
00010   inline int nocase_cmp(const string& s1, const string& s2) {
00011     string::const_iterator it1 = s1.begin();
00012     string::const_iterator it2 = s2.begin();
00013     while ( (it1 != s1.end()) && (it2 != s2.end()) ) { 
00014       if(::toupper(*it1) != ::toupper(*it2)) { // < Letters differ?
00015         // Return -1 to indicate smaller than, 1 otherwise
00016         return (::toupper(*it1) < ::toupper(*it2)) ? -1 : 1; 
00017       }
00018       // Proceed to the next character in each string
00019       ++it1;
00020       ++it2;
00021     }
00022     size_t size1 = s1.size(), size2 = s2.size(); // Cache lengths
00023     // Return -1,0 or 1 according to strings' lengths
00024     if (size1 == size2) return 0;
00025     return (size1 < size2) ? -1 : 1;
00026 }
00027 
00028 
00029   inline string toLower(const string& s) {
00030     string out = s;
00031     transform(out.begin(), out.end(), out.begin(), (int(*)(int)) tolower); 
00032     return out;
00033   }
00034 
00035 
00036   inline string toUpper(const string& s) {
00037     string out = s;
00038     std::transform(out.begin(), out.end(), out.begin(), (int(*)(int)) toupper); 
00039     return out;
00040   }
00041 
00042 
00043   template <typename Real>
00044   inline bool fuzzyEquals(Real a, Real b, Real tolerance = 0.001) {
00045     const double absavg = fabs(a + b)/2.0;
00046     const double absdiff = fabs(a - b);
00047     return (absavg == 0.0 && absdiff == 0.0) || absdiff/absavg < tolerance;
00048   }
00049 
00050 
00051   /// Split a string with single-character delimiters, ignoring zero-length 
00052   /// substrings. Designed for getting elements of filesystem paths, naturally.
00053   inline vector<string> split(const string& s, const string delim = ":") {
00054     string path = s;
00055     vector<string> dirs;
00056     if (delim.length() != 1) {
00057       throw runtime_error("Rivet::split(string): delimiter must be a single character.");
00058     }
00059     while (size_t delim_pos = path.find(delim) != string::npos) {
00060       string dir = path.substr(0, delim_pos);
00061       if (dir.length()) dirs.push_back(dir); // Don't insert "empties"
00062       path.replace(0, delim_pos+1, "");
00063     }
00064     if (path.length()) dirs.push_back(path); // Don't forget the trailing component!
00065     return dirs;
00066   }
00067 
00068 
00069   /// Get Rivet data install path
00070   const string getInstalledDataPath();
00071 
00072   /// Get Rivet library install path
00073   const string getInstalledLibPath();
00074 
00075 }
00076 
00077 
00078 namespace std {
00079 
00080   template <typename T>
00081   inline void operator+=(set<T>& s1, const set<T>& s2) {
00082     for (typename set<T>::const_iterator s = s2.begin(); s != s2.end(); ++s) {
00083       s1.insert(*s);
00084     }
00085   }
00086 
00087   template <typename T>
00088   inline void operator+=(vector<T>& s1, const vector<T>& s2) {
00089     for (typename vector<T>::const_iterator s = s2.begin(); s != s2.end(); ++s) {
00090       s1.push_back(*s);
00091     }
00092   }
00093 
00094 }
00095 
00096 #endif