libfilezilla
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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 <algorithm>
7 #include <string>
8 #include <string_view>
9 #include <vector>
10 
18 namespace fz {
19 
32 #ifdef FZ_WINDOWS
33 typedef std::wstring native_string;
34 typedef std::wstring_view native_string_view;
35 #endif
36 #if defined(FZ_UNIX) || defined(FZ_MAC)
37 typedef std::string native_string;
38 typedef std::string_view native_string_view;
39 #endif
40 
45 native_string FZ_PUBLIC_SYMBOL to_native(std::string_view const& in);
46 
51 native_string FZ_PUBLIC_SYMBOL to_native(std::wstring_view const& in);
52 
54 template<typename T, typename std::enable_if_t<std::is_same_v<native_string, typename std::decay_t<T>>, int> = 0>
55 inline native_string to_native(T const& in) {
56  return in;
57 }
58 
65 int FZ_PUBLIC_SYMBOL stricmp(std::string_view const& a, std::string_view const& b);
66 int FZ_PUBLIC_SYMBOL stricmp(std::wstring_view const& a, std::wstring_view const& b);
67 
85 template<typename Char>
86 Char tolower_ascii(Char c) {
87  if (c >= 'A' && c <= 'Z') {
88  return c + ('a' - 'A');
89  }
90  return c;
91 }
92 
93 template<>
94 std::wstring::value_type FZ_PUBLIC_SYMBOL tolower_ascii(std::wstring::value_type c);
95 
97 template<typename Char>
98 Char toupper_ascii(Char c) {
99  if (c >= 'a' && c <= 'z') {
100  return c + ('A' - 'a');
101  }
102  return c;
103 }
104 
105 template<>
106 std::wstring::value_type FZ_PUBLIC_SYMBOL toupper_ascii(std::wstring::value_type c);
107 
110  // Note: For UTF-8 strings it works on individual octets!
111 std::string FZ_PUBLIC_SYMBOL str_tolower_ascii(std::string_view const& s);
112 std::wstring FZ_PUBLIC_SYMBOL str_tolower_ascii(std::wstring_view const& s);
113 
114 std::string FZ_PUBLIC_SYMBOL str_toupper_ascii(std::string_view const& s);
115 std::wstring FZ_PUBLIC_SYMBOL str_toupper_ascii(std::wstring_view const& s);
116 
122 struct FZ_PUBLIC_SYMBOL less_insensitive_ascii final
123 {
124  template<typename T>
125  bool operator()(T const& lhs, T const& rhs) const {
126  return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(),
127  [](typename T::value_type const& a, typename T::value_type const& b) {
128  return tolower_ascii(a) < tolower_ascii(b);
129  }
130  );
131  }
132 };
133 
138 template<typename String>
139 bool equal_insensitive_ascii(String const& a, String const& b)
140 {
141  return std::equal(a.cbegin(), a.cend(), b.cbegin(), b.cend(),
142  [](typename String::value_type const& a, typename String::value_type const& b) {
143  return tolower_ascii(a) == tolower_ascii(b);
144  }
145  );
146 }
147 
152 std::wstring FZ_PUBLIC_SYMBOL to_wstring(std::string_view const& in);
153 
155 inline std::wstring FZ_PUBLIC_SYMBOL to_wstring(std::wstring const& in) { return in; }
156 
158 template<typename Arg>
159 inline typename std::enable_if<std::is_arithmetic<std::decay_t<Arg>>::value, std::wstring>::type to_wstring(Arg && arg)
160 {
161  return std::to_wstring(std::forward<Arg>(arg));
162 }
163 
164 
169 std::wstring FZ_PUBLIC_SYMBOL to_wstring_from_utf8(std::string const& in);
170 std::wstring FZ_PUBLIC_SYMBOL to_wstring_from_utf8(char const* s, size_t len);
171 
176 std::string FZ_PUBLIC_SYMBOL to_string(std::wstring_view const& in);
177 
179 inline std::string FZ_PUBLIC_SYMBOL to_string(std::string const& in) { return in; }
180 
182 template<typename Arg>
183 inline typename std::enable_if<std::is_arithmetic<std::decay_t<Arg>>::value, std::string>::type to_string(Arg && arg)
184 {
185  return std::to_string(std::forward<Arg>(arg));
186 }
187 
188 
190 template<typename Char>
191 size_t strlen(Char const* str) {
192  return std::char_traits<Char>::length(str);
193 }
194 
195 
202 std::string FZ_PUBLIC_SYMBOL to_utf8(std::string_view const& in);
203 
210 std::string FZ_PUBLIC_SYMBOL to_utf8(std::wstring_view const& in);
211 
213 template<typename String, typename Arg>
214 inline auto toString(Arg&& arg) -> typename std::enable_if<std::is_same<String, std::string>::value, decltype(to_string(std::forward<Arg>(arg)))>::type
215 {
216  return to_string(std::forward<Arg>(arg));
217 }
218 
219 template<typename String, typename Arg>
220 inline auto toString(Arg&& arg) -> typename std::enable_if<std::is_same<String, std::wstring>::value, decltype(to_wstring(std::forward<Arg>(arg)))>::type
221 {
222  return to_wstring(std::forward<Arg>(arg));
223 }
224 
225 #if !defined(fzT) || defined(DOXYGEN)
226 #ifdef FZ_WINDOWS
227 
231 #define fzT(x) L ## x
232 #else
233 
237 #define fzT(x) x
238 #endif
239 #endif
240 
242 template<typename Char>
243 Char const* choose_string(char const* c, wchar_t const* w);
244 
245 template<> inline char const* choose_string(char const* c, wchar_t const*) { return c; }
246 template<> inline wchar_t const* choose_string(char const*, wchar_t const* w) { return w; }
247 
248 #if !defined(fzS) || defined(DOXYGEN)
249 
260 #define fzS(Char, s) fz::choose_string<Char>(s, L ## s)
261 #endif
262 
264 std::string FZ_PUBLIC_SYMBOL replaced_substrings(std::string const& in, std::string const& find, std::string const& replacement);
265 std::wstring FZ_PUBLIC_SYMBOL replaced_substrings(std::wstring const& in, std::wstring const& find, std::wstring const& replacement);
266 
268 bool FZ_PUBLIC_SYMBOL replace_substrings(std::string& in, std::string const& find, std::string const& replacement);
269 bool FZ_PUBLIC_SYMBOL replace_substrings(std::wstring& in, std::wstring const& find, std::wstring const& replacement);
270 
277 std::vector<std::string> FZ_PUBLIC_SYMBOL strtok(std::string_view const& tokens, std::string_view const& delims, bool const ignore_empty = true);
278 std::vector<std::wstring> FZ_PUBLIC_SYMBOL strtok(std::wstring_view const& tokens, std::wstring_view const& delims, bool const ignore_empty = true);
279 inline auto FZ_PUBLIC_SYMBOL strtok(std::string_view const& tokens, char const delim, bool const ignore_empty = true) {
280  return strtok(tokens, std::string_view(&delim, 1), ignore_empty);
281 }
282 inline auto FZ_PUBLIC_SYMBOL strtok(std::wstring_view const& tokens, wchar_t const delim, bool const ignore_empty = true) {
283  return strtok(tokens, std::wstring_view(&delim, 1), ignore_empty);
284 }
285 
294 std::vector<std::string_view> FZ_PUBLIC_SYMBOL strtok_view(std::string_view const& tokens, std::string_view const& delims, bool const ignore_empty = true);
295 std::vector<std::wstring_view> FZ_PUBLIC_SYMBOL strtok_view(std::wstring_view const& tokens, std::wstring_view const& delims, bool const ignore_empty = true);
296 inline auto FZ_PUBLIC_SYMBOL strtok_view(std::string_view const& tokens, char const delim, bool const ignore_empty = true) {
297  return strtok_view(tokens, std::string_view(&delim, 1), ignore_empty);
298 }
299 inline auto FZ_PUBLIC_SYMBOL strtok_view(std::wstring_view const& tokens, wchar_t const delim, bool const ignore_empty = true) {
300  return strtok_view(tokens, std::wstring_view(&delim, 1), ignore_empty);
301 }
302 
304 template<typename T, typename String>
305 T to_integral_impl(String const& s, T const errorval = T())
306 {
307  T ret{};
308 
309  auto it = s.cbegin();
310  if (it != s.cend() && (*it == '-' || *it == '+')) {
311  ++it;
312  }
313 
314  if (it == s.cend()) {
315  return errorval;
316  }
317 
318  for (; it != s.cend(); ++it) {
319  auto const& c = *it;
320  if (c < '0' || c > '9') {
321  return errorval;
322  }
323  ret *= 10;
324  ret += c - '0';
325  }
326 
327  if (!s.empty() && s.front() == '-') {
328  return ret *= static_cast<T>(-1);
329  }
330  else {
331  return ret;
332  }
333 }
334 
336 template<typename T>
337 T to_integral(std::string_view const& s, T const errorval = T()) {
338  return to_integral_impl<T>(s, errorval);
339 }
340 
341 template<typename T>
342 T to_integral(std::wstring_view const& s, T const errorval = T()) {
343  return to_integral_impl<T>(s, errorval);
344 }
345 
346 template<typename T, typename StringType>
347 T to_integral(std::basic_string_view<StringType> const& s, T const errorval = T()) {
348  return to_integral_impl<T>(s, errorval);
349 }
350 
351 
353 template<typename String>
354 bool str_is_ascii(String const& s) {
355  for (auto const& c : s) {
356  if (static_cast<std::make_unsigned_t<typename String::value_type>>(c) > 127) {
357  return false;
358  }
359  }
360 
361  return true;
362 }
363 
365 template<typename String, typename Chars>
366 void trim_impl(String & s, Chars const& chars, bool fromLeft, bool fromRight) {
367  size_t const first = fromLeft ? s.find_first_not_of(chars) : 0;
368  if (first == String::npos) {
369  s = String();
370  return;
371  }
372 
373  size_t const last = fromRight ? s.find_last_not_of(chars) : s.size();
374  if (last == String::npos) {
375  s = String();
376  return;
377  }
378 
379  // Invariant: If first exists, then last >= first
380  s = s.substr(first, last - first + 1);
381 }
382 
384 inline std::string FZ_PUBLIC_SYMBOL trimmed(std::string_view s, std::string_view const& chars = " \r\n\t", bool fromLeft = true, bool fromRight = true)
385 {
386  trim_impl(s, chars, fromLeft, fromRight);
387  return std::string(s);
388 }
389 
390 inline std::wstring FZ_PUBLIC_SYMBOL trimmed(std::wstring_view s, std::wstring_view const& chars = L" \r\n\t", bool fromLeft = true, bool fromRight = true)
391 {
392  trim_impl(s, chars, fromLeft, fromRight);
393  return std::wstring(s);
394 }
395 
396 inline std::string FZ_PUBLIC_SYMBOL ltrimmed(std::string_view s, std::string_view const& chars = " \r\n\t")
397 {
398  trim_impl(s, chars, true, false);
399  return std::string(s);
400 }
401 
402 inline std::wstring FZ_PUBLIC_SYMBOL ltrimmed(std::wstring_view s, std::wstring_view const& chars = L" \r\n\t")
403 {
404  trim_impl(s, chars, true, false);
405  return std::wstring(s);
406 }
407 
408 inline std::string FZ_PUBLIC_SYMBOL rtrimmed(std::string_view s, std::string_view const& chars = " \r\n\t")
409 {
410  trim_impl(s, chars, false, true);
411  return std::string(s);
412 }
413 
414 inline std::wstring FZ_PUBLIC_SYMBOL rtrimmed(std::wstring_view s, std::wstring_view const& chars = L" \r\n\t")
415 {
416  trim_impl(s, chars, false, true);
417  return std::wstring(s);
418 }
419 
420 
422 template<typename String, typename std::enable_if_t<std::is_same_v<typename String::value_type, char>, int> = 0>
423 inline void trim(String & s, std::string_view const& chars = " \r\n\t", bool fromLeft = true, bool fromRight = true)
424 {
425  trim_impl(s, chars, fromLeft, fromRight);
426 }
427 
428 template<typename String, typename std::enable_if_t<std::is_same_v<typename String::value_type, wchar_t>, int> = 0>
429 inline void trim(String & s, std::wstring_view const& chars = L" \r\n\t", bool fromLeft = true, bool fromRight = true)
430 {
431  trim_impl(s, chars, fromLeft, fromRight);
432 }
433 
434 template<typename String, typename std::enable_if_t<std::is_same_v<typename String::value_type, char>, int> = 0>
435 inline void ltrim(String& s, std::string_view const& chars = " \r\n\t")
436 {
437  trim_impl(s, chars, true, false);
438 }
439 
440 template<typename String, typename std::enable_if_t<std::is_same_v<typename String::value_type, wchar_t>, int> = 0>
441 inline void ltrim(String& s, std::wstring_view const& chars = L" \r\n\t")
442 {
443  trim_impl(s, chars, true, false);
444 }
445 
446 template<typename String, typename std::enable_if_t<std::is_same_v<typename String::value_type, char>, int> = 0>
447 inline void rtrim(String& s, std::string_view const& chars = " \r\n\t")
448 {
449  trim_impl(s, chars, false, true);
450 }
451 
452 template<typename String, typename std::enable_if_t<std::is_same_v<typename String::value_type, wchar_t>, int> = 0>
453 inline void rtrim(String & s, std::wstring_view const& chars = L" \r\n\t")
454 {
455  trim_impl(s, chars, false, true);
456 }
457 
462 template<bool insensitive_ascii = false, typename String>
463 bool starts_with(String const& s, String const& beginning)
464 {
465  if (beginning.size() > s.size()) {
466  return false;
467  }
468  if constexpr (insensitive_ascii) {
469  return std::equal(beginning.begin(), beginning.end(), s.begin(), [](typename String::value_type const& a, typename String::value_type const& b) {
470  return tolower_ascii(a) == tolower_ascii(b);
471  });
472  }
473  else {
474  return std::equal(beginning.begin(), beginning.end(), s.begin());
475  }
476 }
477 
482 template<bool insensitive_ascii = false, typename String>
483 bool ends_with(String const& s, String const& ending)
484 {
485  if (ending.size() > s.size()) {
486  return false;
487  }
488 
489  if constexpr (insensitive_ascii) {
490  return std::equal(ending.rbegin(), ending.rend(), s.rbegin(), [](typename String::value_type const& a, typename String::value_type const& b) {
491  return tolower_ascii(a) == tolower_ascii(b);
492  });
493  }
494  else {
495  return std::equal(ending.rbegin(), ending.rend(), s.rbegin());
496  }
497 }
498 
499 }
500 
501 #endif
std::wstring to_wstring_from_utf8(std::string const &in)
Converts from std::string in UTF-8 into std::wstring.
T to_integral(std::string_view const &s, T const errorval=T())
Converts string to integral type T. If string is not convertible, errorval is returned.
Definition: string.hpp:337
Comparator to be used for std::map for case-insentitive keys.
Definition: string.hpp:122
bool starts_with(String const &s, String const &beginning)
Tests whether the first string starts with the second string.
Definition: string.hpp:463
std::wstring to_wstring(std::string_view const &in)
Converts from std::string in system encoding into std::wstring.
Char toupper_ascii(Char c)
Converts ASCII lowercase characters to uppercase as if C-locale is used.
Definition: string.hpp:98
native_string to_native(std::string_view const &in)
Converts std::string to native_string.
bool equal_insensitive_ascii(String const &a, String const &b)
Locale-insensitive stricmp.
Definition: string.hpp:139
std::string to_utf8(std::string_view const &in)
Converts from std::string in native encoding into std::string in UTF-8.
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:159
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:183
std::vector< std::string_view > strtok_view(std::string_view const &tokens, std::string_view const &delims, bool const ignore_empty=true)
Tokenizes string.
std::string trimmed(std::string_view s, std::string_view const &chars=" \r\n\t", bool fromLeft=true, bool fromRight=true)
Return passed string with all leading and trailing whitespace removed.
Definition: string.hpp:384
Char tolower_ascii(Char c)
Converts ASCII uppercase characters to lowercase as if C-locale is used.
Definition: string.hpp:86
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.
size_t strlen(Char const *str)
Returns length of 0-terminated character sequence. Works with both narrow and wide-characters.
Definition: string.hpp:191
bool str_is_ascii(String const &s)
Returns true iff the string only has characters in the 7-bit ASCII range.
Definition: string.hpp:354
std::string str_tolower_ascii(std::string_view const &s)
tr_tolower_ascii does for strings what tolower_ascii does for individual characters ...
bool ends_with(String const &s, String const &ending)
Tests whether the first string ends with the second string.
Definition: string.hpp:483
std::wstring native_string
A string in the system's native character type and encoding. Note: This typedef changes depending on...
Definition: string.hpp:33
bool replace_substrings(std::string &in, std::string const &find, std::string const &replacement)
Modifies in, replacing all occurrences of find with replacement.
void trim(String &s, std::string_view const &chars=" \r\n\t", bool fromLeft=true, bool fromRight=true)
Remove all leading and trailing whitespace from string.
Definition: string.hpp:423
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:245
std::vector< std::string > strtok(std::string_view const &tokens, std::string_view const &delims, bool const ignore_empty=true)
Tokenizes string.
Sets some global macros and further includes string.hpp.
int stricmp(std::string_view const &a, std::string_view const &b)
Locale-sensitive stricmp.
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:214
std::string to_string(std::wstring_view const &in)
Converts from std::wstring into std::string in system encoding.