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 <string>
00026 #include <sstream>
00027 #include <cctype>
00028
00029 namespace wibble {
00030 namespace str {
00031
00033 template<typename T>
00034 inline std::string fmt(const T& val)
00035 {
00036 std::stringstream str;
00037 str << val;
00038 return str.str();
00039 }
00040 template<> inline std::string fmt<std::string>(const std::string& val) { return val; }
00041 template<> inline std::string fmt<char*>(char * const & val) { return val; }
00042
00044 inline std::string basename(const std::string& pathname)
00045 {
00046 size_t pos = pathname.rfind("/");
00047 if (pos == std::string::npos)
00048 return pathname;
00049 else
00050 return pathname.substr(pos+1);
00051 }
00052
00054 inline std::string dirname(const std::string& pathname)
00055 {
00056 size_t pos = pathname.rfind("/");
00057 if (pos == std::string::npos)
00058 return std::string();
00059 else if (pos == 0)
00060
00061 return std::string("/");
00062 else
00063 return pathname.substr(0, pos);
00064 }
00065
00071 std::string normpath(const std::string& pathname);
00072
00074 inline bool startsWith(const std::string& str, const std::string& part)
00075 {
00076 if (str.size() < part.size())
00077 return false;
00078 return str.substr(0, part.size()) == part;
00079 }
00080
00082 inline bool endsWith(const std::string& str, const std::string& part)
00083 {
00084 if (str.size() < part.size())
00085 return false;
00086 return str.substr(str.size() - part.size()) == part;
00087 }
00088
00089 #if ! __GNUC__ || __GNUC__ >= 4
00090
00094 template<typename FUN>
00095 inline std::string trim(const std::string& str, const FUN& classifier)
00096 {
00097 if (str.empty())
00098 return str;
00099
00100 size_t beg = 0;
00101 size_t end = str.size() - 1;
00102 while (beg < end && classifier(str[beg]))
00103 ++beg;
00104 while (end >= beg && classifier(str[end]))
00105 --end;
00106
00107 return str.substr(beg, end-beg+1);
00108 }
00109
00113 inline std::string trim(const std::string& str)
00114 {
00115 return trim(str, ::isspace);
00116 }
00117 #else
00119 inline std::string trim(const std::string& str)
00120 {
00121 if (str.empty())
00122 return str;
00123
00124 size_t beg = 0;
00125 size_t end = str.size() - 1;
00126 while (beg < end && ::isspace(str[beg]))
00127 ++beg;
00128 while (end >= beg && ::isspace(str[end]))
00129 --end;
00130
00131 return str.substr(beg, end-beg+1);
00132 }
00133 #endif
00134
00136 inline std::string toupper(const std::string& str)
00137 {
00138 std::string res;
00139 res.reserve(str.size());
00140 for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
00141 res += ::toupper(*i);
00142 return res;
00143 }
00144
00146 inline std::string tolower(const std::string& str)
00147 {
00148 std::string res;
00149 res.reserve(str.size());
00150 for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
00151 res += ::tolower(*i);
00152 return res;
00153 }
00154
00156 inline std::string ucfirst(const std::string& str)
00157 {
00158 if (str.empty()) return str;
00159 std::string res;
00160 res += ::toupper(str[0]);
00161 return res + tolower(str.substr(1));
00162 }
00163
00165 inline std::string joinpath(const std::string& path1, const std::string& path2)
00166 {
00167 if (path1.empty())
00168 return path2;
00169 if (path2.empty())
00170 return path1;
00171
00172 if (path1[path1.size() - 1] == '/')
00173 if (path2[0] == '/')
00174 return path1 + path2.substr(1);
00175 else
00176 return path1 + path2;
00177 else
00178 if (path2[0] == '/')
00179 return path1 + path2;
00180 else
00181 return path1 + '/' + path2;
00182 }
00183
00185 std::string urlencode(const std::string& str);
00186
00188 std::string urldecode(const std::string& str);
00189
00191 std::string encodeBase64(const std::string& str);
00192
00194 std::string decodeBase64(const std::string& str);
00195
00208 class Split
00209 {
00210 std::string sep;
00211 std::string str;
00212
00213 public:
00214
00215 class const_iterator
00216 {
00217 const std::string& sep;
00218 const std::string& str;
00219 std::string cur;
00220 size_t pos;
00221
00222 public:
00223 const_iterator(const std::string& sep, const std::string& str) : sep(sep), str(str), pos(0)
00224 {
00225 ++*this;
00226 }
00227 const_iterator(const std::string& sep, const std::string& str, bool) : sep(sep), str(str), pos(std::string::npos) {}
00228
00229 const_iterator& operator++()
00230 {
00231 if (pos == str.size())
00232 pos = std::string::npos;
00233 else
00234 {
00235 size_t end;
00236 if (sep.empty())
00237 if (pos + 1 == str.size())
00238 end = std::string::npos;
00239 else
00240 end = pos + 1;
00241 else
00242 end = str.find(sep, pos);
00243 if (end == std::string::npos)
00244 {
00245 cur = str.substr(pos);
00246 pos = str.size();
00247 }
00248 else
00249 {
00250 cur = str.substr(pos, end-pos);
00251 pos = end + sep.size();
00252 }
00253 }
00254 return *this;
00255 }
00256
00257 std::string remainder() const
00258 {
00259 if (pos == std::string::npos)
00260 return std::string();
00261 else
00262 return str.substr(pos);
00263 }
00264
00265 const std::string& operator*() const
00266 {
00267 return cur;
00268 }
00269 const std::string* operator->() const
00270 {
00271 return &cur;
00272 }
00273 bool operator==(const const_iterator& ti) const
00274 {
00275
00276
00277 return pos == ti.pos;
00278 }
00279 bool operator!=(const const_iterator& ti) const
00280 {
00281
00282
00283 return pos != ti.pos;
00284 }
00285 };
00286
00290 Split(const std::string& sep, const std::string& str) : sep(sep), str(str) {}
00291
00295 const_iterator begin() const { return const_iterator(sep, str); }
00296 const_iterator end() const { return const_iterator(sep, str, false); }
00297 };
00298
00313 class YamlStream
00314 {
00315 public:
00316
00317 class const_iterator
00318 {
00319 std::istream* in;
00320 std::pair<std::string, std::string> value;
00321 std::string line;
00322
00323 public:
00324 const_iterator(std::istream& in);
00325 const_iterator() : in(0) {}
00326
00327 const_iterator& operator++();
00328
00329 const std::pair<std::string, std::string>& operator*() const
00330 {
00331 return value;
00332 }
00333 const std::pair<std::string, std::string>* operator->() const
00334 {
00335 return &value;
00336 }
00337 bool operator==(const const_iterator& ti) const
00338 {
00339 return in == ti.in;
00340 }
00341 bool operator!=(const const_iterator& ti) const
00342 {
00343 return in != ti.in;
00344 }
00345 };
00346
00347 const_iterator begin(std::istream& in) { return const_iterator(in); }
00348 const_iterator end() { return const_iterator(); }
00349 };
00350
00351
00352 }
00353 }
00354
00355
00356 #endif