00001
00002 #ifndef WIBBLE_STRING_H
00003 #define WIBBLE_STRING_H
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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 #ifdef _WIN32
00046 static int vasprintf (char **, const char *, va_list);
00047 #endif
00048
00049 std::string fmt( const char* f, ... ) __attribute__ ((deprecated));
00050 std::string fmtf( const char* f, ... );
00051 template< typename T > inline std::string fmt(const T& val);
00052
00053
00054
00055 template< typename X >
00056 inline typename TPair< std::ostream, typename X::Type >::First &operator<<(
00057 std::ostream &o, X list )
00058 {
00059 if ( list.empty() )
00060 return o << "[]";
00061
00062 o << "[ ";
00063 while( !list.empty() ) {
00064 o << fmt( list.head() );
00065 if ( !list.tail().empty() )
00066 o << ", ";
00067 list = list.tail();
00068 }
00069 return o << " ]";
00070 }
00071
00073 template< typename T >
00074 inline std::string fmt(const T& val)
00075 {
00076 std::stringstream str;
00077 str << val;
00078 return str.str();
00079 }
00080
00081 template<> inline std::string fmt<std::string>(const std::string& val) {
00082 return val;
00083 }
00084 template<> inline std::string fmt<char*>(char * const & val) { return val; }
00085
00086 template< typename C >
00087 inline std::string fmt_container( const C &c, char f, char l )
00088 {
00089 std::string s;
00090 s += f;
00091 if ( c.empty() )
00092 return s + l;
00093
00094 s += ' ';
00095 for ( typename C::const_iterator i = c.begin(); i != c.end(); ++i ) {
00096 s += fmt( *i );
00097 if ( i != c.end() && i + 1 != c.end() )
00098 s += ", ";
00099 }
00100 s += ' ';
00101 s += l;
00102 return s;
00103 }
00104
00105
00106 template< typename X >
00107 inline std::string fmt(const std::set< X >& val) {
00108 return fmt_container( val, '{', '}' );
00109 }
00110
00111
00112 template< typename X >
00113 inline std::string fmt(const std::vector< X > &val) {
00114 return fmt_container( val, '[', ']' );
00115 }
00116
00118 inline std::string basename(const std::string& pathname)
00119 {
00120 size_t pos = pathname.rfind("/");
00121 if (pos == std::string::npos)
00122 return pathname;
00123 else
00124 return pathname.substr(pos+1);
00125 }
00126
00128 inline std::string dirname(const std::string& pathname)
00129 {
00130 size_t pos = pathname.rfind("/");
00131 if (pos == std::string::npos)
00132 return std::string();
00133 else if (pos == 0)
00134
00135 return std::string("/");
00136 else
00137 return pathname.substr(0, pos);
00138 }
00139
00145 std::string normpath(const std::string& pathname);
00146
00148 inline bool startsWith(const std::string& str, const std::string& part)
00149 {
00150 if (str.size() < part.size())
00151 return false;
00152 return str.substr(0, part.size()) == part;
00153 }
00154
00156 inline bool endsWith(const std::string& str, const std::string& part)
00157 {
00158 if (str.size() < part.size())
00159 return false;
00160 return str.substr(str.size() - part.size()) == part;
00161 }
00162
00163 inline std::string replace(const std::string& str, char from, char to)
00164 {
00165 std::string res;
00166 res.reserve(str.size());
00167 for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
00168 if (*i == from)
00169 res.append(1, to);
00170 else
00171 res.append(1, *i);
00172 return res;
00173 }
00174
00175 #if !__xlC__ && (! __GNUC__ || __GNUC__ >= 4)
00176
00180 template<typename FUN>
00181 inline std::string trim(const std::string& str, const FUN& classifier)
00182 {
00183 if (str.empty())
00184 return str;
00185
00186 size_t beg = 0;
00187 size_t end = str.size() - 1;
00188 while (beg < end && classifier(str[beg]))
00189 ++beg;
00190 while (end >= beg && classifier(str[end]))
00191 --end;
00192
00193 return str.substr(beg, end-beg+1);
00194 }
00195
00199 inline std::string trim(const std::string& str)
00200 {
00201 return trim(str, ::isspace);
00202 }
00203 #else
00204
00205 inline std::string trim(const std::string& str)
00206 {
00207 if (str.empty())
00208 return str;
00209
00210 size_t beg = 0;
00211 size_t end = str.size() - 1;
00212 while (beg < end && ::isspace(str[beg]))
00213 ++beg;
00214 while (end >= beg && ::isspace(str[end]))
00215 --end;
00216
00217 return str.substr(beg, end-beg+1);
00218 }
00219 #endif
00220
00222 inline std::string toupper(const std::string& str)
00223 {
00224 std::string res;
00225 res.reserve(str.size());
00226 for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
00227 res += ::toupper(*i);
00228 return res;
00229 }
00230
00232 inline std::string tolower(const std::string& str)
00233 {
00234 std::string res;
00235 res.reserve(str.size());
00236 for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
00237 res += ::tolower(*i);
00238 return res;
00239 }
00240
00242 inline std::string ucfirst(const std::string& str)
00243 {
00244 if (str.empty()) return str;
00245 std::string res;
00246 res += ::toupper(str[0]);
00247 return res + tolower(str.substr(1));
00248 }
00249
00251 inline std::string joinpath(const std::string& path1, const std::string& path2)
00252 {
00253 if (path1.empty())
00254 return path2;
00255 if (path2.empty())
00256 return path1;
00257
00258 if (path1[path1.size() - 1] == '/')
00259 if (path2[0] == '/')
00260 return path1 + path2.substr(1);
00261 else
00262 return path1 + path2;
00263 else
00264 if (path2[0] == '/')
00265 return path1 + path2;
00266 else
00267 return path1 + '/' + path2;
00268 }
00269
00271 std::string urlencode(const std::string& str);
00272
00274 std::string urldecode(const std::string& str);
00275
00277 std::string encodeBase64(const std::string& str);
00278
00280 std::string decodeBase64(const std::string& str);
00281
00294 class Split
00295 {
00296 std::string sep;
00297 std::string str;
00298
00299 public:
00300
00301 class const_iterator
00302 {
00303 const std::string& sep;
00304 const std::string& str;
00305 std::string cur;
00306 size_t pos;
00307
00308 public:
00309 const_iterator(const std::string& sep, const std::string& str) : sep(sep), str(str), pos(0)
00310 {
00311 ++*this;
00312 }
00313 const_iterator(const std::string& sep, const std::string& str, bool) : sep(sep), str(str), pos(std::string::npos) {}
00314
00315 const_iterator& operator++()
00316 {
00317 if (pos == str.size())
00318 pos = std::string::npos;
00319 else
00320 {
00321 size_t end;
00322 if (sep.empty())
00323 if (pos + 1 == str.size())
00324 end = std::string::npos;
00325 else
00326 end = pos + 1;
00327 else
00328 end = str.find(sep, pos);
00329 if (end == std::string::npos)
00330 {
00331 cur = str.substr(pos);
00332 pos = str.size();
00333 }
00334 else
00335 {
00336 cur = str.substr(pos, end-pos);
00337 pos = end + sep.size();
00338 }
00339 }
00340 return *this;
00341 }
00342
00343 std::string remainder() const
00344 {
00345 if (pos == std::string::npos)
00346 return std::string();
00347 else
00348 return str.substr(pos);
00349 }
00350
00351 const std::string& operator*() const
00352 {
00353 return cur;
00354 }
00355 const std::string* operator->() const
00356 {
00357 return &cur;
00358 }
00359 bool operator==(const const_iterator& ti) const
00360 {
00361
00362
00363 return pos == ti.pos;
00364 }
00365 bool operator!=(const const_iterator& ti) const
00366 {
00367
00368
00369 return pos != ti.pos;
00370 }
00371 };
00372
00376 Split(const std::string& sep, const std::string& str) : sep(sep), str(str) {}
00377
00381 const_iterator begin() const { return const_iterator(sep, str); }
00382 const_iterator end() const { return const_iterator(sep, str, false); }
00383 };
00384
00385 template<typename ITER>
00386 std::string join(const ITER& begin, const ITER& end, const std::string& sep = ", ")
00387 {
00388 std::stringstream res;
00389 bool first = true;
00390 for (ITER i = begin; i != end; ++i)
00391 {
00392 if (first)
00393 first = false;
00394 else
00395 res << sep;
00396 res << *i;
00397 }
00398 return res.str();
00399 }
00400
00415 class YamlStream
00416 {
00417 public:
00418
00419 class const_iterator
00420 {
00421 std::istream* in;
00422 std::pair<std::string, std::string> value;
00423 std::string line;
00424
00425 public:
00426 const_iterator(std::istream& in);
00427 const_iterator() : in(0) {}
00428
00429 const_iterator& operator++();
00430
00431 const std::pair<std::string, std::string>& operator*() const
00432 {
00433 return value;
00434 }
00435 const std::pair<std::string, std::string>* operator->() const
00436 {
00437 return &value;
00438 }
00439 bool operator==(const const_iterator& ti) const
00440 {
00441 return in == ti.in;
00442 }
00443 bool operator!=(const const_iterator& ti) const
00444 {
00445 return in != ti.in;
00446 }
00447 };
00448
00449 const_iterator begin(std::istream& in) { return const_iterator(in); }
00450 const_iterator end() { return const_iterator(); }
00451 };
00452
00453 }
00454 }
00455
00456
00457 #endif