• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

string.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #ifndef WIBBLE_STRING_H
00003 #define WIBBLE_STRING_H
00004 
00005 /*
00006  * Various string functions
00007  *
00008  * Copyright (C) 2007,2008  Enrico Zini <enrico@debian.org>
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00023  */
00024 
00025 #include <wibble/operators.h>
00026 #include <wibble/sfinae.h>
00027 
00028 #include <cstdarg>
00029 #include <cstdio>
00030 #include <string>
00031 #include <set>
00032 #include <vector>
00033 #include <sstream>
00034 #include <cctype>
00035 #ifdef _WIN32
00036 #include <cstring>
00037 #include <cstdlib>
00038 #endif
00039 
00040 namespace wibble {
00041 namespace str {
00042 
00043 using namespace wibble::operators;
00044 
00045 // Formatting lists -- actually, we need to move list handling into wibble,
00046 // really.
00047 template< typename X >
00048 inline typename TPair< std::ostream, typename X::Type >::First &operator<<(
00049     std::ostream &o, X list )
00050 {
00051     if ( list.empty() )
00052         return o << "[]";
00053 
00054     o << "[ ";
00055     while( !list.empty() ) {
00056         o << fmt( list.head() );
00057         if ( !list.tail().empty() )
00058             o << ", ";
00059         list = list.tail();
00060     }
00061     return o << " ]";
00062 }
00063 
00064 #ifdef _WIN32
00065 static int vasprintf (char **, const char *, va_list);
00066 #endif
00067 
00068 std::string fmt( const char* f, ... ) __attribute__ ((deprecated));
00069 std::string fmtf( const char* f, ... );
00070 
00072 template< typename T >
00073 inline std::string fmt(const T& val)
00074 {
00075     std::stringstream str;
00076     str << val;
00077     return str.str();
00078 }
00079 
00080 template<> inline std::string fmt<std::string>(const std::string& val) {
00081     return val;
00082 }
00083 template<> inline std::string fmt<char*>(char * const & val) { return val; }
00084 
00085 template< typename C >
00086 inline std::string fmt_container( const C &c, char f, char l )
00087 {
00088     std::string s;
00089     s += f;
00090     if ( c.empty() )
00091         return s + l;
00092 
00093     s += ' ';
00094     for ( typename C::const_iterator i = c.begin(); i != c.end(); ++i ) {
00095         s += fmt( *i );
00096         if ( i != c.end() && i + 1 != c.end() )
00097             s += ", ";
00098     }
00099     s += ' ';
00100     s += l;
00101     return s;
00102 }
00103 
00104 // formatting sets using { ... } notation
00105 template< typename X >
00106 inline std::string fmt(const std::set< X >& val) {
00107     return fmt_container( val, '{', '}' );
00108 }
00109 
00110 // formatting vectors using [ ... ] notation
00111 template< typename X >
00112 inline std::string fmt(const std::vector< X > &val) {
00113     return fmt_container( val, '[', ']' );
00114 }
00115 
00117 inline std::string basename(const std::string& pathname)
00118 {
00119     size_t pos = pathname.rfind("/");
00120     if (pos == std::string::npos)
00121         return pathname;
00122     else
00123         return pathname.substr(pos+1);
00124 }
00125 
00127 inline std::string dirname(const std::string& pathname)
00128 {
00129     size_t pos = pathname.rfind("/");
00130     if (pos == std::string::npos)
00131         return std::string();
00132     else if (pos == 0)
00133         // Handle the case of '/foo'
00134         return std::string("/");
00135     else
00136         return pathname.substr(0, pos);
00137 }
00138 
00144 std::string normpath(const std::string& pathname);
00145 
00147 inline bool startsWith(const std::string& str, const std::string& part)
00148 {
00149     if (str.size() < part.size())
00150         return false;
00151     return str.substr(0, part.size()) == part;
00152 }
00153 
00155 inline bool endsWith(const std::string& str, const std::string& part)
00156 {
00157     if (str.size() < part.size())
00158         return false;
00159     return str.substr(str.size() - part.size()) == part;
00160 }
00161 
00162 #if ! __GNUC__ || __GNUC__ >= 4
00163 
00167 template<typename FUN>
00168 inline std::string trim(const std::string& str, const FUN& classifier)
00169 {
00170     if (str.empty())
00171         return str;
00172 
00173     size_t beg = 0;
00174     size_t end = str.size() - 1;
00175     while (beg < end && classifier(str[beg]))
00176         ++beg;
00177     while (end >= beg && classifier(str[end]))
00178         --end;
00179 
00180     return str.substr(beg, end-beg+1);
00181 }
00182 
00186 inline std::string trim(const std::string& str)
00187 {
00188     return trim(str, ::isspace);
00189 }
00190 #else
00191 
00192 inline std::string trim(const std::string& str)
00193 {
00194     if (str.empty())
00195         return str;
00196 
00197     size_t beg = 0;
00198     size_t end = str.size() - 1;
00199     while (beg < end && ::isspace(str[beg]))
00200         ++beg;
00201     while (end >= beg && ::isspace(str[end]))
00202         --end;
00203 
00204     return str.substr(beg, end-beg+1);
00205 }
00206 #endif
00207 
00209 inline std::string toupper(const std::string& str)
00210 {
00211     std::string res;
00212     res.reserve(str.size());
00213     for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
00214         res += ::toupper(*i);
00215     return res;
00216 }
00217 
00219 inline std::string tolower(const std::string& str)
00220 {
00221     std::string res;
00222     res.reserve(str.size());
00223     for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
00224         res += ::tolower(*i);
00225     return res;
00226 }
00227 
00229 inline std::string ucfirst(const std::string& str)
00230 {
00231     if (str.empty()) return str;
00232     std::string res;
00233     res += ::toupper(str[0]);
00234     return res + tolower(str.substr(1));
00235 }
00236 
00238 inline std::string joinpath(const std::string& path1, const std::string& path2)
00239 {
00240     if (path1.empty())
00241         return path2;
00242     if (path2.empty())
00243         return path1;
00244 
00245     if (path1[path1.size() - 1] == '/')
00246         if (path2[0] == '/')
00247             return path1 + path2.substr(1);
00248         else
00249             return path1 + path2;
00250     else
00251         if (path2[0] == '/')
00252             return path1 + path2;
00253         else
00254             return path1 + '/' + path2;
00255 }
00256 
00258 std::string urlencode(const std::string& str);
00259 
00261 std::string urldecode(const std::string& str);
00262 
00264 std::string encodeBase64(const std::string& str);
00265 
00267 std::string decodeBase64(const std::string& str);
00268 
00281 class Split
00282 {
00283     std::string sep;
00284     std::string str;
00285 
00286 public:
00287     // TODO: add iterator_traits
00288     class const_iterator
00289     {
00290         const std::string& sep;
00291         const std::string& str;
00292         std::string cur;
00293         size_t pos;
00294 
00295     public:
00296         const_iterator(const std::string& sep, const std::string& str) : sep(sep), str(str), pos(0)
00297         {
00298             ++*this;
00299         }
00300         const_iterator(const std::string& sep, const std::string& str, bool) : sep(sep), str(str), pos(std::string::npos) {}
00301 
00302         const_iterator& operator++()
00303         {
00304             if (pos == str.size())
00305                 pos = std::string::npos;
00306             else
00307             {
00308                 size_t end;
00309                 if (sep.empty())
00310                     if (pos + 1 == str.size())
00311                         end = std::string::npos;
00312                     else
00313                         end = pos + 1;
00314                 else
00315                     end = str.find(sep, pos);
00316                 if (end == std::string::npos)
00317                 {
00318                     cur = str.substr(pos);
00319                     pos = str.size();
00320                 }
00321                 else
00322                 {
00323                     cur = str.substr(pos, end-pos);
00324                     pos = end + sep.size();
00325                 }
00326             }
00327             return *this;
00328         }
00329 
00330         std::string remainder() const
00331         {
00332             if (pos == std::string::npos)
00333                 return std::string();
00334             else
00335                 return str.substr(pos);
00336         }
00337 
00338         const std::string& operator*() const
00339         {
00340             return cur;
00341         }
00342         const std::string* operator->() const
00343         {
00344             return &cur;
00345         }
00346         bool operator==(const const_iterator& ti) const
00347         {
00348             // Comparing iterators on different strings is not supported for
00349             // performance reasons
00350             return pos == ti.pos;
00351         }
00352         bool operator!=(const const_iterator& ti) const
00353         {
00354             // Comparing iterators on different strings is not supported for
00355             // performance reasons
00356             return pos != ti.pos;
00357         }
00358     };
00359 
00363     Split(const std::string& sep, const std::string& str) : sep(sep), str(str) {}
00364 
00368     const_iterator begin() const { return const_iterator(sep, str); }
00369     const_iterator end() const { return const_iterator(sep, str, false); }
00370 };
00371 
00372 template<typename ITER>
00373 std::string join(const ITER& begin, const ITER& end, const std::string& sep = ", ")
00374 {
00375     std::stringstream res;
00376     bool first = true;
00377     for (ITER i = begin; i != end; ++i)
00378     {
00379         if (first)
00380             first = false;
00381         else
00382             res << sep;
00383         res << *i;
00384     }
00385     return res.str();
00386 }
00387 
00402 class YamlStream
00403 {
00404 public:
00405     // TODO: add iterator_traits
00406     class const_iterator
00407     {
00408         std::istream* in;
00409         std::pair<std::string, std::string> value;
00410         std::string line;
00411 
00412     public:
00413         const_iterator(std::istream& in);
00414         const_iterator() : in(0) {}
00415 
00416         const_iterator& operator++();
00417 
00418         const std::pair<std::string, std::string>& operator*() const
00419         {
00420             return value;
00421         }
00422         const std::pair<std::string, std::string>* operator->() const
00423         {
00424             return &value;
00425         }
00426         bool operator==(const const_iterator& ti) const
00427         {
00428             return in == ti.in;
00429         }
00430         bool operator!=(const const_iterator& ti) const
00431         {
00432             return in != ti.in;
00433         }
00434     };
00435 
00436     const_iterator begin(std::istream& in) { return const_iterator(in); }
00437     const_iterator end() { return const_iterator(); }
00438 };
00439 
00440 }
00441 }
00442 
00443 // vim:set ts=4 sw=4:
00444 #endif

Generated on Tue May 10 2011 16:51:50 for wibble by  doxygen 1.7.1