libfilezilla
string.hpp
Go to the documentation of this file.
00001 #ifndef LIBFILEZILLA_STRING_HEADER
00002 #define LIBFILEZILLA_STRING_HEADER
00003 
00004 #include "libfilezilla.hpp"
00005 
00006 #include <string>
00007 #include <vector>
00008 
00016 namespace fz {
00017 
00030 #ifdef FZ_WINDOWS
00031 typedef std::wstring native_string;
00032 #endif
00033 #if defined(FZ_UNIX) || defined(FZ_MAC)
00034 typedef std::string native_string;
00035 #endif
00036 
00041 native_string FZ_PUBLIC_SYMBOL to_native(std::string const& in);
00042 
00047 native_string FZ_PUBLIC_SYMBOL to_native(std::wstring const& in);
00048 
00055 int FZ_PUBLIC_SYMBOL stricmp(std::string const& a, std::string const& b);
00056 int FZ_PUBLIC_SYMBOL stricmp(std::wstring const& a, std::wstring const& b);
00057 
00075 template<typename Char>
00076 Char tolower_ascii(Char c) {
00077     if (c >= 'A' && c <= 'Z') {
00078         return c + ('a' - 'A');
00079     }
00080     return c;
00081 }
00082 
00083 template<>
00084 std::wstring::value_type FZ_PUBLIC_SYMBOL tolower_ascii(std::wstring::value_type c);
00085 
00087 template<typename Char>
00088 Char toupper_ascii(Char c) {
00089     if (c >= 'a' && c <= 'z') {
00090         return c + ('A' - 'a');
00091     }
00092     return c;
00093 }
00094 
00095 template<>
00096 std::wstring::value_type FZ_PUBLIC_SYMBOL toupper_ascii(std::wstring::value_type c);
00097 
00100  // Note: For UTF-8 strings it works on individual octets!
00101 template<typename String>
00102 String str_tolower_ascii(String const& s)
00103 {
00104     String ret = s;
00105     for (auto& c : ret) {
00106         c = tolower_ascii(c);
00107     }
00108     return ret;
00109 }
00110 
00111 template<typename String>
00112 String str_toupper_ascii(String const& s)
00113 {
00114     String ret = s;
00115     for (auto& c : ret) {
00116         c = toupper_ascii(c);
00117     }
00118     return ret;
00119 }
00120 
00127 std::wstring FZ_PUBLIC_SYMBOL to_wstring(std::string const& in);
00128 
00130 inline std::wstring FZ_PUBLIC_SYMBOL to_wstring(std::wstring const& in) { return in; }
00131 
00133 template<typename Arg>
00134 inline typename std::enable_if<std::is_arithmetic<std::decay_t<Arg>>::value, std::wstring>::type to_wstring(Arg && arg)
00135 {
00136     return std::to_wstring(std::forward<Arg>(arg));
00137 }
00138 
00139 
00144 std::wstring FZ_PUBLIC_SYMBOL to_wstring_from_utf8(std::string const& in);
00145 
00152 std::string FZ_PUBLIC_SYMBOL to_string(std::wstring const& in);
00153 
00155 inline std::string FZ_PUBLIC_SYMBOL to_string(std::string const& in) { return in; }
00156 
00158 template<typename Arg>
00159 inline typename std::enable_if<std::is_arithmetic<std::decay_t<Arg>>::value, std::string>::type to_string(Arg && arg)
00160 {
00161     return std::to_string(std::forward<Arg>(arg));
00162 }
00163 
00164 
00166 template<typename Char>
00167 size_t strlen(Char const* str) {
00168     return std::char_traits<Char>::length(str);
00169 }
00170 
00171 
00178 std::string FZ_PUBLIC_SYMBOL to_utf8(std::string const& in);
00179 
00186 std::string FZ_PUBLIC_SYMBOL to_utf8(std::wstring const& in);
00187 
00188 
00195 template<typename Char>
00196 int hex_char_to_int(Char c)
00197 {
00198     if (c >= 'a' && c <= 'z') {
00199         return c - 'a' + 10;
00200     }
00201     if (c >= 'A' && c <= 'Z') {
00202         return c - 'A' + 10;
00203     }
00204     else if (c >= '0' && c <= '9') {
00205         return c - '0';
00206     }
00207     return -1;
00208 }
00209 
00210 template<typename String>
00211 std::vector<uint8_t> hex_decode(String const& in)
00212 {
00213     std::vector<uint8_t> ret;
00214     if (!(in.size() % 2)) {
00215         ret.reserve(in.size() / 2);
00216         for (size_t i = 0; i < in.size(); i += 2) {
00217             int high = hex_char_to_int(in[i]);
00218             int low = hex_char_to_int(in[i + 1]);
00219             if (high == -1 || low == -1) {
00220                 return std::vector<uint8_t>();
00221             }
00222             ret.push_back(static_cast<uint8_t>((high << 4) + low));
00223         }
00224     }
00225 
00226     return ret;
00227 }
00228 
00235 template<typename Char = char, bool Lowercase = true>
00236 Char int_to_hex_char(int d)
00237 {
00238     if (d > 9) {
00239         return (Lowercase ? 'a' : 'A') + d - 10;
00240     }
00241     else {
00242         return '0' + d;
00243     }
00244 }
00245 
00246 template<typename String, typename InString, bool Lowercase = true>
00247 String hex_encode(InString const& data)
00248 {
00249     static_assert(sizeof(typename InString::value_type) == 1, "Input must be a container of 8 bit values");
00250     String ret;
00251     ret.reserve(data.size() * 2);
00252     for (auto const& c : data) {
00253         ret.push_back(int_to_hex_char<typename String::value_type, Lowercase>(static_cast<unsigned char>(c) >> 4));
00254         ret.push_back(int_to_hex_char<typename String::value_type, Lowercase>(static_cast<unsigned char>(c) & 0xf));
00255     }
00256 
00257     return ret;
00258 }
00259 
00261 template<typename String, typename Arg>
00262 inline auto toString(Arg&& arg) -> typename std::enable_if<std::is_same<String, std::string>::value, decltype(to_string(std::forward<Arg>(arg)))>::type
00263 {
00264     return to_string(std::forward<Arg>(arg));
00265 }
00266 
00267 template<typename String, typename Arg>
00268 inline auto toString(Arg&& arg) -> typename std::enable_if<std::is_same<String, std::wstring>::value, decltype(to_wstring(std::forward<Arg>(arg)))>::type
00269 {
00270     return to_wstring(std::forward<Arg>(arg));
00271 }
00272 
00273 #if !defined(fzT) || defined(DOXYGEN)
00274 #ifdef FZ_WINDOWS
00275 
00279 #define fzT(x) L ## x
00280 #else
00281 
00285 #define fzT(x) x
00286 #endif
00287 #endif
00288 
00290 template<typename Char>
00291 Char const* choose_string(char const* c, wchar_t const* w);
00292 
00293 template<> inline char const* choose_string(char const* c, wchar_t const*) { return c; }
00294 template<> inline wchar_t const* choose_string(char const*, wchar_t const* w) { return w; }
00295 
00296 #if !defined(fzS) || defined(DOXYGEN)
00297 
00308 #define fzS(Char, s) fz::choose_string<Char>(s, L ## s)
00309 #endif
00310 
00312 std::string FZ_PUBLIC_SYMBOL replaced_substrings(std::string const& in, std::string const& find, std::string const& replacement);
00313 std::wstring FZ_PUBLIC_SYMBOL replaced_substrings(std::wstring const& in, std::wstring const& find, std::wstring const& replacement);
00314 
00316 void FZ_PUBLIC_SYMBOL replace_substrings(std::string& in, std::string const& find, std::string const& replacement);
00317 void FZ_PUBLIC_SYMBOL replace_substrings(std::wstring& in, std::wstring const& find, std::wstring const& replacement);
00318 
00320 template<typename String, typename Delim, typename Container = std::vector<String>>
00321 Container strtok(String const& s, Delim const& delims)
00322 {
00323     Container ret;
00324 
00325     typename String::size_type start{}, pos{};
00326     do {
00327         pos = s.find_first_of(delims, start);
00328 
00329         // Not found, we're at ends;
00330         if (pos == String::npos) {
00331             if (start + 1 < s.size()) {
00332                 ret.emplace_back(s.substr(start));
00333             }
00334         }
00335         else if (pos > start + 1) {
00336             // Non-empty substring
00337             ret.emplace_back(s.substr(start, pos - start));
00338         }
00339         start = pos + 1;
00340     } while (pos != String::npos);
00341 
00342     return ret;
00343 }
00344 
00345 
00347 std::string FZ_PUBLIC_SYMBOL base64_encode(std::string const& in);
00348 
00350 std::string FZ_PUBLIC_SYMBOL base64_decode(std::string const& in);
00351 
00352 // Converts string to integral type T. If string is not convertible, T() is returned.
00353 template<typename T, typename String>
00354 T to_integral(String const& s, T const errorval = T())
00355 {
00356     T ret{};
00357 
00358     auto it = s.cbegin();
00359     if (it != s.cend() && (*it == '-' || *it == '+')) {
00360         ++it;
00361     }
00362 
00363     if (it == s.cend()) {
00364         return errorval;
00365     }
00366 
00367     for (; it != s.cend(); ++it) {
00368         auto const& c = *it;
00369         if (c < '0' || c > '9') {
00370             return errorval;
00371         }
00372         ret *= 10;
00373         ret += c - '0';
00374     }
00375 
00376     if (!s.empty() && s.front() == '-') {
00377         return ret *= static_cast<T>(-1);
00378     }
00379     else {
00380         return ret;
00381     }
00382 }
00383 
00385 template<typename String>
00386 bool str_is_ascii(String const& s) {
00387     for (auto const& c : s) {
00388         if (static_cast<std::make_unsigned_t<typename String::value_type>>(c) > 127) {
00389             return false;
00390         }
00391     }
00392 
00393     return true;
00394 }
00395 
00397 template<typename String>
00398 String trimmed(String const& s) {
00399     size_t const first = s.find_first_not_of(fzS(typename String::value_type, " \r\n\t"));
00400     if (first == String::npos) {
00401         return String();
00402     }
00403     else {
00404         // Cannot be npos
00405         size_t const last = s.find_last_not_of(fzS(typename String::value_type, " \r\n\t"));
00406 
00407         return s.substr(first, last - first + 1);
00408     }
00409 }
00410 
00411 
00413 template<typename String>
00414 void trim(String & s) {
00415     s = trimmed(s);
00416 }
00417 
00418 }
00419 
00420 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines