rivet is hosted by Hepforge, IPPP Durham
Utils.hh
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #ifndef RIVET_Utils_HH
00003 #define RIVET_Utils_HH
00004 
00005 #include <Rivet/Math/Math.hh>
00006 #include <Rivet/Tools/RivetSTL.hh>
00007 #include <Rivet/Tools/RivetBoost.hh>
00008 #include <cctype>
00009 #include <algorithm>
00010 #include <cerrno>
00011 
00012 namespace Rivet {
00013 
00014 
00015   /// @name String utils
00016   //@{
00017 
00018   /// @brief Convert any object to a string
00019   ///
00020   /// Just a convenience wrapper for the more general Boost lexical_cast
00021   template <typename T>
00022   inline std::string to_str(const T& x) {
00023     return lexical_cast<string>(x);
00024   }
00025 
00026   /// @brief Convert any object to a string
00027   ///
00028   /// An alias for to_str() with a more "Rivety" mixedCase name.
00029   template <typename T>
00030   inline std::string toString(const T& x) {
00031     return to_str(x);
00032   }
00033 
00034 
00035   /// Case-insensitive string comparison function
00036   ///
00037   /// @todo Replace with something from the Boost string library
00038   inline int nocase_cmp(const std::string& s1, const std::string& s2) {
00039     string::const_iterator it1 = s1.begin();
00040     string::const_iterator it2 = s2.begin();
00041     while ( (it1 != s1.end()) && (it2 != s2.end()) ) {
00042       if(::toupper(*it1) != ::toupper(*it2)) { // < Letters differ?
00043         // Return -1 to indicate smaller than, 1 otherwise
00044         return (::toupper(*it1) < ::toupper(*it2)) ? -1 : 1;
00045       }
00046       // Proceed to the next character in each string
00047       ++it1;
00048       ++it2;
00049     }
00050     size_t size1 = s1.size(), size2 = s2.size(); // Cache lengths
00051     // Return -1,0 or 1 according to strings' lengths
00052     if (size1 == size2) return 0;
00053     return (size1 < size2) ? -1 : 1;
00054   }
00055 
00056 
00057   /// Case-insensitive string equality function
00058   inline bool nocase_equals(const std::string& s1, const std::string& s2) {
00059     return nocase_cmp(s1, s2) == 0;
00060   }
00061 
00062 
00063   /// Convert a string to lower-case
00064   ///
00065   /// @todo Replace with something from the Boost string library
00066   inline std::string toLower(const std::string& s) {
00067     string out = s;
00068     transform(out.begin(), out.end(), out.begin(), (int(*)(int)) tolower);
00069     return out;
00070   }
00071 
00072 
00073   /// Convert a string to upper-case
00074   ///
00075   /// @todo Replace with something from the Boost string library
00076   inline std::string toUpper(const std::string& s) {
00077     string out = s;
00078     std::transform(out.begin(), out.end(), out.begin(), (int(*)(int)) toupper);
00079     return out;
00080   }
00081 
00082 
00083   /// Check whether a string @a start is found at the start of @a s
00084   inline bool startsWith(const std::string& s, const std::string& start) {
00085     if (s.length() < start.length()) return false;
00086     return s.substr(0, start.length()) == start;
00087   }
00088 
00089 
00090   /// Check whether a string @a end is found at the end of @a s
00091   inline bool endsWith(const std::string& s, const std::string& end) {
00092     if (s.length() < end.length()) return false;
00093     return s.substr(s.length() - end.length()) == end;
00094   }
00095 
00096 
00097   /// Make a string containing the string representations of each item in v, separated by sep
00098   template <typename T>
00099   inline std::string join(const vector<T>& v, const std::string& sep = " ") {
00100     string rtn;
00101     for (size_t i = 0; i < v.size(); ++i) {
00102       if (i != 0) rtn += sep;
00103       rtn += to_str(v[i]);
00104     }
00105     return rtn;
00106   }
00107 
00108   /// Make a string containing the string representations of each item in s, separated by sep
00109   template <typename T>
00110   inline std::string join(const set<T>& s, const std::string& sep = " ") {
00111     string rtn;
00112     foreach (const T& x, s) {
00113       if (rtn.size() > 0) rtn += sep;
00114       rtn += to_str(x);
00115     }
00116     return rtn;
00117   }
00118 
00119   //@}
00120 
00121 
00122   /// @name Path utils
00123   //@{
00124 
00125   /// @brief Split a path string with colon delimiters
00126   ///
00127   /// Ignores zero-length substrings. Designed for getting elements of filesystem paths, naturally.
00128   inline vector<std::string> pathsplit(const std::string& path) {
00129     const string delim = ":";
00130     vector<string> dirs;
00131     string tmppath = path;
00132     while (true) {
00133       const size_t delim_pos = tmppath.find(delim);
00134       if (delim_pos == string::npos) break;
00135       const string dir = tmppath.substr(0, delim_pos);
00136       if (dir.length()) dirs.push_back(dir); // Don't insert "empties"
00137       tmppath.replace(0, delim_pos+1, "");
00138     }
00139     if (tmppath.length()) dirs.push_back(tmppath); // Don't forget the trailing component!
00140     return dirs;
00141   }
00142 
00143 
00144   /// @brief Join several filesystem paths together with the standard ':' delimiter
00145   ///
00146   /// Note that this does NOT join path elements together with a platform-portable
00147   /// directory delimiter, cf. the Python @c {os.path.join}!
00148   inline std::string pathjoin(const vector<std::string>& paths) {
00149     return join(paths, ":");
00150   }
00151 
00152   //@}
00153 
00154 
00155   /// @name Container utils
00156   //@{
00157 
00158   /// Return true if f(x) is true for any x in container c, otherwise false.
00159   template <typename CONTAINER, typename FN>
00160   inline bool any(const CONTAINER& c, const FN& f) {
00161     //for (const typename CONTAINER::value_type& val : c) {
00162     foreach (const typename CONTAINER::value_type& val, c) {
00163       if (f(val)) return true;
00164     }
00165     return false;
00166   }
00167 
00168   /// Return true if f(x) is true for all x in container c, otherwise false.
00169   template <typename CONTAINER, typename FN>
00170   inline bool all(const CONTAINER& c, const FN& f) {
00171     //for (const typename CONTAINER::value_type& val : c) {
00172     foreach (const typename CONTAINER::value_type& val, c) {
00173       if (!f(val)) return false;
00174     }
00175     return true;
00176   }
00177 
00178   //@}
00179 
00180 
00181 }
00182 
00183 #endif