![]() |
libfilezilla
|
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