Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

string_util.cc

Go to the documentation of this file.
00001 #include "string_util.h"
00002 #include <cctype>
00003 #include <locale>
00004 #include <pwd.h>
00005 #include <stdlib.h>
00006 #include <regex.h>
00007 #include <sstream>
00008 #include <algorithm>
00009 #include <memory>
00010 #ifdef __GNUC__
00011 #  include <cxxabi.h> // demangling
00012 #endif
00013 
00014 using namespace std;
00015 
00016 namespace string_util {
00017 
00018   //! reference to the current standard library 'locale'
00019   static const std::locale& curLocale=std::locale::classic();
00020   
00021   char localeToUpper(char c) {
00022     return std::toupper(c,curLocale);
00023   }
00024 
00025   char localeToLower(char c) {
00026     return std::tolower(c,curLocale);
00027   }
00028   
00029   string makeUpper(const string& s) {
00030     string ans(s); // yes, I actually checked if it's faster to copy and then overwrite or reserve and use std::back_inserter(ans)
00031     std::transform(ans.begin(), ans.end(), ans.begin(), (int(*)(int)) std::toupper);
00032     return ans;
00033   }
00034   
00035   string makeLower(const string& s) {
00036     string ans(s);
00037     std::transform(ans.begin(), ans.end(), ans.begin(), (int(*)(int)) std::tolower);
00038     return ans;
00039   }
00040 
00041   string removePrefix(const string& str, const string& pre) {
00042     if(str.compare(0,pre.size(),pre)==0)
00043       return str.substr(pre.size());
00044     return string();
00045   }
00046   
00047   string tildeExpansion(const string& str) {
00048     string ans;
00049     if(str[0]!='~') {
00050       return str;
00051     }
00052 #ifndef PLATFORM_APERIOS
00053     else if(str=="~" || str[1]=='/') {
00054       char* home=getenv("HOME");
00055       if(home==NULL)
00056         return str;
00057       if(str=="~")
00058         return home;
00059       return home+str.substr(1);
00060     } else {
00061       string::size_type p=str.find('/');
00062       struct passwd * pw;
00063       pw=getpwnam(str.substr(1,p-1).c_str());
00064       if(pw==NULL)
00065         return str;
00066       return pw->pw_dir+str.substr(p);
00067     }
00068 #else
00069     return str.substr(1);
00070 #endif
00071   }
00072 
00073   string trim(const string& str) {
00074     if(str.size()==0)
00075       return str;
00076     unsigned int b=0;
00077     unsigned int e=str.size()-1;
00078     while(b<str.size() && isspace(str[b]))
00079       b++;
00080     while(b<e && isspace(str[e]))
00081       e--;
00082     return str.substr(b,e-b+1);
00083   }
00084   
00085   bool beginsWith(const std::string& str, const std::string& prefix) {
00086     if(str.size()<prefix.size()) // str is shorter than prefix, cannot contain suffix
00087       return false;
00088     if(prefix.size()==0) // empty suffix matches everything
00089       return true;
00090     return str.compare(0,prefix.size(),prefix)==0;
00091   }
00092   
00093   bool endsWith(const std::string& str, const std::string& suffix) {
00094     if(str.size()<suffix.size()) // str is shorter than suffix, cannot contain suffix
00095       return false;
00096     if(suffix.size()==0) // empty suffix matches everything
00097       return true;
00098     return str.compare(str.size()-suffix.size(),suffix.size(),suffix)==0;
00099   }
00100   
00101   std::string makePath(const std::string& rel, const std::string& path) {
00102     if(path[0]=='/') {
00103       return path;
00104     } else {
00105       std::string::size_type d = rel.rfind('/');
00106       if(d==std::string::npos) {
00107         return path;
00108       } else {
00109         return rel.substr(0,d+1)+path;
00110       }
00111     }
00112   }
00113   
00114   std::vector<std::string> tokenize(const std::string & str, const std::string & delims /*=", \t"*/) {
00115     // Skip delims at beginning, find start of first token
00116     string::size_type lastPos = str.find_first_not_of(delims, 0);
00117     // Find next delimiter at end of token
00118     string::size_type pos     = str.find_first_of(delims, lastPos);
00119     
00120     vector<string> tokens; // output vector
00121     while (string::npos != pos || string::npos != lastPos) {
00122       // Found a token, add it to the vector.
00123       tokens.push_back(str.substr(lastPos, pos - lastPos));
00124       // Skip delims.  Note the "not_of". this is beginning of token
00125       lastPos = str.find_first_not_of(delims, pos);
00126       // Find next delimiter at end of token.
00127       pos     = str.find_first_of(delims, lastPos);
00128     }
00129     return tokens;
00130   }
00131   
00132   bool parseArgs(const string& input, vector<string>& args, vector<unsigned int>& offsets) {
00133     string cur;
00134     bool isDoubleQuote=false;
00135     bool isSingleQuote=false;
00136     args.clear();
00137     offsets.clear();
00138     unsigned int begin=-1U;
00139     for(unsigned int i=0; i<input.size(); i++) {
00140       char c=input[i];
00141       if(begin==-1U && !isspace(c))
00142         begin=i;
00143       switch(c) {
00144       case ' ':
00145       case '\n':
00146       case '\r':
00147       case '\t':
00148       case '\v':
00149       case '\f':
00150         if(isSingleQuote || isDoubleQuote)
00151           cur+=c;
00152         else if(cur.size()!=0) {
00153           args.push_back(cur);
00154           offsets.push_back(begin);
00155           cur.clear();
00156           begin=-1U;
00157         }
00158         break;
00159       case '\\':
00160         if(i==input.size()-1) { //escaped line break
00161           return false;
00162         } else
00163           cur.push_back(input[++i]);
00164         break;
00165       case '"':
00166         if(isSingleQuote)
00167           cur.push_back(c);
00168         else
00169           isDoubleQuote=!isDoubleQuote;
00170         break;
00171       case '\'':
00172         if(isDoubleQuote)
00173           cur+=c;
00174         else
00175           isSingleQuote=!isSingleQuote;
00176         break;
00177       default:
00178         cur+=c;
00179         break;
00180       }
00181     }
00182     if(cur.size()>0) {
00183       args.push_back(cur);
00184       offsets.push_back(begin);
00185     }
00186     return !isDoubleQuote && !isSingleQuote;
00187   }
00188 
00189   bool reMatch(const std::string& str, const std::string& regex) {
00190     return reMatch(str,regex,REG_EXTENDED);
00191   }
00192   
00193   bool reMatch(const std::string& str, const std::string& regex, int flags) {
00194     regex_t re;
00195     if(int err=regcomp(&re,regex.c_str(),flags | REG_NOSUB)) {
00196       char msg[128];
00197       regerror(err,&re,msg,128);
00198       string errmsg;
00199       errmsg.append("Bad filter '").append(regex).append("': ").append(msg);
00200       regfree(&re);
00201       throw errmsg;
00202     }
00203     int match=regexec(&re,str.c_str(),0,NULL,0);
00204     regfree(&re);
00205     if(match==0) {
00206       return true;
00207     } else if(match==REG_NOMATCH) {
00208       return false;
00209     } else {
00210       char msg[128];
00211       regerror(match,&re,msg,128);
00212       string errmsg;
00213       errmsg.append("Regex error on reMatch('").append(str).append("', '").append(regex).append("'): ").append(msg);
00214       throw errmsg;
00215     }
00216   }
00217 
00218   std::string intToStringIP(int ip) {
00219     std::stringstream ret;
00220     ret << (ip >> 24 & 0xff) << '.' << (ip >> 16 & 0xff) << '.'
00221     << (ip >> 8 & 0xff) << '.' << (ip >> 0 & 0xff);
00222     return ret.str();
00223   }
00224   
00225   int stringToIntIP(std::string ip_str) {
00226     std::istringstream sstr;
00227     sstr.str(ip_str);
00228     int ip = 0, b;
00229     char c;
00230     
00231     sstr >> b >> c;
00232     ip |= b << 24;
00233     
00234     sstr >> b >> c;
00235     ip |= b << 16;
00236     
00237     sstr >> b >> c;
00238     ip |= b << 8;
00239     
00240     sstr >> b;
00241     ip |= b << 0;
00242     
00243     return ip;
00244   }
00245   
00246   size_t utf8len(const std::string& str) {
00247     size_t len=0, i=0;
00248     while(i<str.size()) {
00249       unsigned char c = str[i];
00250       if(c < 0x80)
00251         ++i;
00252       else if((c >> 5) == 0x6)
00253         i+=2;
00254       else if((c >> 4) == 0xe)
00255         i+=3;
00256       else if((c >> 3) == 0x1e)
00257         i+=4;
00258       else
00259         ++i; // actually invalid, but we're not checking for that, so count as one
00260       ++len;
00261     }
00262     return len;
00263   }
00264 
00265 #ifndef __GNUC__
00266   std::string demangle(const std::string& symbol) { return symbol; }
00267 #else
00268   std::string demangle(const std::string& symbol) {
00269     std::string ret = symbol;
00270     try {
00271       int status = 0;
00272       std::auto_ptr<const char> d(abi::__cxa_demangle(symbol.c_str(), 0, 0, &status));
00273       if(d.get()!=NULL)
00274         ret = d.get();
00275     } catch(...) {  }
00276     return ret;
00277   }
00278 #endif
00279   
00280   std::string int2str(int const n) {
00281     ostringstream os;
00282     os << n;
00283     return os.str();
00284   }
00285   
00286 }
00287 
00288 /*! @file
00289  * @brief Implements some useful functions for string manipulation in the string_util namespace
00290  * @author ejt (Creator)
00291  */

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:51 2016 by Doxygen 1.6.3