libfilezilla
string.hpp
Go to the documentation of this file.
1 #ifndef LIBFILEZILLA_STRING_HEADER
2 #define LIBFILEZILLA_STRING_HEADER
3 
4 #include "libfilezilla.hpp"
5 
6 #include <string>
7 #include <vector>
8 
16 namespace fz {
17 
30 #ifdef FZ_WINDOWS
31 typedef std::wstring native_string;
32 #endif
33 #if defined(FZ_UNIX) || defined(FZ_MAC)
34 typedef std::string native_string;
35 #endif
36 
41 native_string FZ_PUBLIC_SYMBOL to_native(std::string const& in);
42 
47 native_string FZ_PUBLIC_SYMBOL to_native(std::wstring const& in);
48 
55 int FZ_PUBLIC_SYMBOL stricmp(std::string const& a, std::string const& b);
56 int FZ_PUBLIC_SYMBOL stricmp(std::wstring const& a, std::wstring const& b);
57 
75 template<typename Char>
76 Char tolower_ascii(Char c) {
77  if (c >= 'A' && c <= 'Z') {
78  return c + ('a' - 'A');
79  }
80  return c;
81 }
82 
83 template<>
84 std::wstring::value_type FZ_PUBLIC_SYMBOL tolower_ascii(std::wstring::value_type c);
85 
87 template<typename Char>
88 Char toupper_ascii(Char c) {
89  if (c >= 'a' && c <= 'z') {
90  return c + ('A' - 'a');
91  }
92  return c;
93 }
94 
95 template<>
96 std::wstring::value_type FZ_PUBLIC_SYMBOL toupper_ascii(std::wstring::value_type c);
97 
100  // Note: For UTF-8 strings it works on individual octets!
101 template<typename String>
102 String str_tolower_ascii(String const& s)
103 {
104  String ret = s;
105  for (auto& c : ret) {
106  c = tolower_ascii(c);
107  }
108  return ret;
109 }
110 
111 template<typename String>
112 String str_toupper_ascii(String const& s)
113 {
114  String ret = s;
115  for (auto& c : ret) {
116  c = toupper_ascii(c);
117  }
118  return ret;
119 }
120 
127 std::wstring FZ_PUBLIC_SYMBOL to_wstring(std::string const& in);
128 
130 inline std::wstring FZ_PUBLIC_SYMBOL to_wstring(std::wstring const& in) { return in; }
131 
133 template<typename Arg>
134 inline typename std::enable_if<std::is_arithmetic<std::decay_t<Arg>>::value, std::wstring>::type to_wstring(Arg && arg)
135 {
136  return std::to_wstring(std::forward<Arg>(arg));
137 }
138 
139 
144 std::wstring FZ_PUBLIC_SYMBOL to_wstring_from_utf8(std::string const& in);
145 std::wstring FZ_PUBLIC_SYMBOL to_wstring_from_utf8(char const* s, size_t len);
146 
153 std::string FZ_PUBLIC_SYMBOL to_string(std::wstring const& in);
154 
156 inline std::string FZ_PUBLIC_SYMBOL to_string(std::string const& in) { return in; }
157 
159 template<typename Arg>
160 inline typename std::enable_if<std::is_arithmetic<std::decay_t<Arg>>::value, std::string>::type to_string(Arg && arg)
161 {
162  return std::to_string(std::forward<Arg>(arg));
163 }
164 
165 
167 template<typename Char>
168 size_t strlen(Char const* str) {
169  return std::char_traits<Char>::length(str);
170 }
171 
172 
179 std::string FZ_PUBLIC_SYMBOL to_utf8(std::string const& in);
180 
187 std::string FZ_PUBLIC_SYMBOL to_utf8(std::wstring const& in);
188 
189 
196 template<typename Char>
197 int hex_char_to_int(Char c)
198 {
199  if (c >= 'a' && c <= 'z') {
200  return c - 'a' + 10;
201  }
202  if (c >= 'A' && c <= 'Z') {
203  return c - 'A' + 10;
204  }
205  else if (c >= '0' && c <= '9') {
206  return c - '0';
207  }
208  return -1;
209 }
210 
211 template<typename String>
212 std::vector<uint8_t> hex_decode(String const& in)
213 {
214  std::vector<uint8_t> ret;
215  if (!(in.size() % 2)) {
216  ret.reserve(in.size() / 2);
217  for (size_t i = 0; i < in.size(); i += 2) {
218  int high = hex_char_to_int(in[i]);
219  int low = hex_char_to_int(in[i + 1]);
220  if (high == -1 || low == -1) {
221  return std::vector<uint8_t>();
222  }
223  ret.push_back(static_cast<uint8_t>((high << 4) + low));
224  }
225  }
226 
227  return ret;
228 }
229 
236 template<typename Char = char, bool Lowercase = true>
237 Char int_to_hex_char(int d)
238 {
239  if (d > 9) {
240  return (Lowercase ? 'a' : 'A') + d - 10;
241  }
242  else {
243  return '0' + d;
244  }
245 }
246 
247 template<typename String, typename InString, bool Lowercase = true>
248 String hex_encode(InString const& data)
249 {
250  static_assert(sizeof(typename InString::value_type) == 1, "Input must be a container of 8 bit values");
251  String ret;
252  ret.reserve(data.size() * 2);
253  for (auto const& c : data) {
254  ret.push_back(int_to_hex_char<typename String::value_type, Lowercase>(static_cast<unsigned char>(c) >> 4));
255  ret.push_back(int_to_hex_char<typename String::value_type, Lowercase>(static_cast<unsigned char>(c) & 0xf));
256  }
257 
258  return ret;
259 }
260 
262 template<typename String, typename Arg>
263 inline auto toString(Arg&& arg) -> typename std::enable_if<std::is_same<String, std::string>::value, decltype(to_string(std::forward<Arg>(arg)))>::type
264 {
265  return to_string(std::forward<Arg>(arg));
266 }
267 
268 template<typename String, typename Arg>
269 inline auto toString(Arg&& arg) -> typename std::enable_if<std::is_same<String, std::wstring>::value, decltype(to_wstring(std::forward<Arg>(arg)))>::type
270 {
271  return to_wstring(std::forward<Arg>(arg));
272 }
273 
274 #if !defined(fzT) || defined(DOXYGEN)
275 #ifdef FZ_WINDOWS
276 
280 #define fzT(x) L ## x
281 #else
282 
286 #define fzT(x) x
287 #endif
288 #endif
289 
291 template<typename Char>
292 Char const* choose_string(char const* c, wchar_t const* w);
293 
294 template<> inline char const* choose_string(char const* c, wchar_t const*) { return c; }
295 template<> inline wchar_t const* choose_string(char const*, wchar_t const* w) { return w; }
296 
297 #if !defined(fzS) || defined(DOXYGEN)
298 
309 #define fzS(Char, s) fz::choose_string<Char>(s, L ## s)
310 #endif
311 
313 std::string FZ_PUBLIC_SYMBOL replaced_substrings(std::string const& in, std::string const& find, std::string const& replacement);
314 std::wstring FZ_PUBLIC_SYMBOL replaced_substrings(std::wstring const& in, std::wstring const& find, std::wstring const& replacement);
315 
317 void FZ_PUBLIC_SYMBOL replace_substrings(std::string& in, std::string const& find, std::string const& replacement);
318 void FZ_PUBLIC_SYMBOL replace_substrings(std::wstring& in, std::wstring const& find, std::wstring const& replacement);
319 
321 template<typename String, typename Delim, typename Container = std::vector<String>>
322 Container strtok(String const& s, Delim const& delims)
323 {
324  Container ret;
325 
326  typename String::size_type start{}, pos{};
327  do {
328  pos = s.find_first_of(delims, start);
329 
330  // Not found, we're at ends;
331  if (pos == String::npos) {
332  if (start < s.size()) {
333  ret.emplace_back(s.substr(start));
334  }
335  }
336  else if (pos > start) {
337  // Non-empty substring
338  ret.emplace_back(s.substr(start, pos - start));
339  }
340  start = pos + 1;
341  } while (pos != String::npos);
342 
343  return ret;
344 }
345 
346 
348 std::string FZ_PUBLIC_SYMBOL base64_encode(std::string const& in);
349 
351 std::string FZ_PUBLIC_SYMBOL base64_decode(std::string const& in);
352 
353 // Converts string to integral type T. If string is not convertible, T() is returned.
354 template<typename T, typename String>
355 T to_integral(String const& s, T const errorval = T())
356 {
357  T ret{};
358 
359  auto it = s.cbegin();
360  if (it != s.cend() && (*it == '-' || *it == '+')) {
361  ++it;
362  }
363 
364  if (it == s.cend()) {
365  return errorval;
366  }
367 
368  for (; it != s.cend(); ++it) {
369  auto const& c = *it;
370  if (c < '0' || c > '9') {
371  return errorval;
372  }
373  ret *= 10;
374  ret += c - '0';
375  }
376 
377  if (!s.empty() && s.front() == '-') {
378  return ret *= static_cast<T>(-1);
379  }
380  else {
381  return ret;
382  }
383 }
384 
386 template<typename String>
387 bool str_is_ascii(String const& s) {
388  for (auto const& c : s) {
389  if (static_cast<std::make_unsigned_t<typename String::value_type>>(c) > 127) {
390  return false;
391  }
392  }
393 
394  return true;
395 }
396 
398 template<typename String>
399 String trimmed(String const& s, String const& chars = fzS(typename String::value_type, " \r\n\t"), bool fromLeft = true, bool fromRight = true) {
400  size_t const first = fromLeft ? s.find_first_not_of(chars) : 0;
401  if (first == String::npos) {
402  return String();
403  }
404 
405  size_t const last = fromRight ? s.find_last_not_of(chars) : s.size();
406  if (last == String::npos) {
407  return String();
408  }
409  return s.substr(first, last - first + 1);
410 }
411 
412 template<typename String>
413 String ltrimmed(String const& s, String const& chars = fzS(typename String::value_type, " \r\n\t"), bool fromLeft = true, bool fromRight = true) {
414  return trimmed(s, chars, true, false);
415 }
416 
417 template<typename String>
418 String rtrimmed(String const& s, String const& chars = fzS(typename String::value_type, " \r\n\t"), bool fromLeft = true, bool fromRight = true) {
419  return trimmed(s, chars, false, true);
420 }
421 
423 template<typename String>
424 void trim(String & s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
425  s = trimmed(s, chars);
426 }
427 
428 template<typename String>
429 void ltrim(String & s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
430  s = trimmed(s, chars, true, false);
431 }
432 
433 template<typename String>
434 void rtrim(String & s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
435  s = trimmed(s, chars, false, true);
436 }
437 
438 }
439 
440 #endif
std::wstring to_wstring_from_utf8(std::string const &in)
Converts from std::string in UTF-8 into std::wstring.
Char toupper_ascii(Char c)
Converts ASCII lowercase characters to uppercase as if C-locale is used.
Definition: string.hpp:88
Char int_to_hex_char(int d)
Converts an integer to the corresponding lowercase hex digit.
Definition: string.hpp:237
int hex_char_to_int(Char c)
Converts a hex digit to decimal int.
Definition: string.hpp:197
std::enable_if< std::is_arithmetic< std::decay_t< Arg > >::value, std::wstring >::type to_wstring(Arg &&arg)
Converts from arithmetic type to std::wstring.
Definition: string.hpp:134
std::enable_if< std::is_arithmetic< std::decay_t< Arg > >::value, std::string >::type to_string(Arg &&arg)
Converts from arithmetic type to std::string.
Definition: string.hpp:160
#define fzS(Char, s)
Macro to get const pointer to a string of the corresponding type.
Definition: string.hpp:309
int stricmp(std::string const &a, std::string const &b)
Locale-sensitive stricmp.
Char tolower_ascii(Char c)
Converts ASCII uppercase characters to lowercase as if C-locale is used.
Definition: string.hpp:76
std::string replaced_substrings(std::string const &in, std::string const &find, std::string const &replacement)
Returns in with all occurrences of find in the input string replaced with replacement.
std::string to_utf8(std::string const &in)
Converts from std::string in native encoding into std::string in UTF-8.
void replace_substrings(std::string &in, std::string const &find, std::string const &replacement)
Modifies in, replacing all occurrences of find with replacement.
size_t strlen(Char const *str)
Returns length of 0-terminated character sequence. Works with both narrow and wide-characters.
Definition: string.hpp:168
bool str_is_ascii(String const &s)
Returns true iff the string only has characters in the 7-bit ASCII range.
Definition: string.hpp:387
Container strtok(String const &s, Delim const &delims)
Tokenizes string. Returns all non-empty substrings.
Definition: string.hpp:322
std::string base64_encode(std::string const &in)
Encodes raw input string to base64.
std::wstring native_string
A string in the system&#39;s native character type and encoding. Note: This typedef changes depending on...
Definition: string.hpp:31
std::string to_string(std::wstring const &in)
Converts from std::wstring into std::string in system encoding.
The namespace used by libfilezilla.
Definition: apply.hpp:16
Char const * choose_string(char const *c, wchar_t const *w)
Returns the function argument of the type matching the template argument.
Definition: string.hpp:294
void trim(String &s, String const &chars=fz::choose_string< typename String::value_type >(" \\, L" \\\"))
Remove all leading and trailing whitespace from string.
Definition: string.hpp:424
String str_tolower_ascii(String const &s)
tr_tolower_ascii does for strings what tolower_ascii does for individual characters ...
Definition: string.hpp:102
Sets some global macros and further includes string.hpp.
native_string to_native(std::string const &in)
Converts std::string to native_string.
std::string base64_decode(std::string const &in)
Decodes base64, ignores whitespace. Returns empty string on invalid input.
auto toString(Arg &&arg) -> typename std::enable_if< std::is_same< String, std::string >::value, decltype(to_string(std::forward< Arg >(arg)))>::type
Calls either fz::to_string or fz::to_wstring depending on the passed template argument.
Definition: string.hpp:263
String trimmed(String const &s, String const &chars=fz::choose_string< typename String::value_type >(" \\, L" \\\"), bool fromLeft=true, bool fromRight=true)
Return passed string with all leading and trailing whitespace removed.
Definition: string.hpp:399
std::wstring to_wstring(std::string const &in)
Converts from std::string in system encoding into std::wstring.