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 <vector>
9 
17 namespace fz {
18 
31 #ifdef FZ_WINDOWS
32 typedef std::wstring native_string;
33 #endif
34 #if defined(FZ_UNIX) || defined(FZ_MAC)
35 typedef std::string native_string;
36 #endif
37 
42 native_string FZ_PUBLIC_SYMBOL to_native(std::string const& in);
43 
48 native_string FZ_PUBLIC_SYMBOL to_native(std::wstring const& in);
49 
56 int FZ_PUBLIC_SYMBOL stricmp(std::string const& a, std::string const& b);
57 int FZ_PUBLIC_SYMBOL stricmp(std::wstring const& a, std::wstring const& b);
58 
76 template<typename Char>
77 Char tolower_ascii(Char c) {
78  if (c >= 'A' && c <= 'Z') {
79  return c + ('a' - 'A');
80  }
81  return c;
82 }
83 
84 template<>
85 std::wstring::value_type FZ_PUBLIC_SYMBOL tolower_ascii(std::wstring::value_type c);
86 
88 template<typename Char>
89 Char toupper_ascii(Char c) {
90  if (c >= 'a' && c <= 'z') {
91  return c + ('A' - 'a');
92  }
93  return c;
94 }
95 
96 template<>
97 std::wstring::value_type FZ_PUBLIC_SYMBOL toupper_ascii(std::wstring::value_type c);
98 
101  // Note: For UTF-8 strings it works on individual octets!
102 template<typename String>
103 String str_tolower_ascii(String const& s)
104 {
105  String ret = s;
106  for (auto& c : ret) {
107  c = tolower_ascii(c);
108  }
109  return ret;
110 }
111 
112 template<typename String>
113 String str_toupper_ascii(String const& s)
114 {
115  String ret = s;
116  for (auto& c : ret) {
117  c = toupper_ascii(c);
118  }
119  return ret;
120 }
121 
127 struct FZ_PUBLIC_SYMBOL less_insensitive_ascii final
128 {
129  template<typename T>
130  bool operator()(T const& lhs, T const& rhs) const {
131  return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(),
132  [](typename T::value_type const& a, typename T::value_type const& b) {
133  return tolower_ascii(a) < tolower_ascii(b);
134  }
135  );
136  }
137 };
138 
143 template<typename String>
144 bool equal_insensitive_ascii(String const& a, String const& b)
145 {
146  return std::equal(a.cbegin(), a.cend(), b.cbegin(), b.cend(),
147  [](typename String::value_type const& a, typename String::value_type const& b) {
148  return tolower_ascii(a) == tolower_ascii(b);
149  }
150  );
151 }
152 
159 std::wstring FZ_PUBLIC_SYMBOL to_wstring(std::string const& in);
160 
162 inline std::wstring FZ_PUBLIC_SYMBOL to_wstring(std::wstring const& in) { return in; }
163 
165 template<typename Arg>
166 inline typename std::enable_if<std::is_arithmetic<std::decay_t<Arg>>::value, std::wstring>::type to_wstring(Arg && arg)
167 {
168  return std::to_wstring(std::forward<Arg>(arg));
169 }
170 
171 
176 std::wstring FZ_PUBLIC_SYMBOL to_wstring_from_utf8(std::string const& in);
177 std::wstring FZ_PUBLIC_SYMBOL to_wstring_from_utf8(char const* s, size_t len);
178 
185 std::string FZ_PUBLIC_SYMBOL to_string(std::wstring const& in);
186 
188 inline std::string FZ_PUBLIC_SYMBOL to_string(std::string const& in) { return in; }
189 
191 template<typename Arg>
192 inline typename std::enable_if<std::is_arithmetic<std::decay_t<Arg>>::value, std::string>::type to_string(Arg && arg)
193 {
194  return std::to_string(std::forward<Arg>(arg));
195 }
196 
197 
199 template<typename Char>
200 size_t strlen(Char const* str) {
201  return std::char_traits<Char>::length(str);
202 }
203 
204 
211 std::string FZ_PUBLIC_SYMBOL to_utf8(std::string const& in);
212 
219 std::string FZ_PUBLIC_SYMBOL to_utf8(std::wstring const& in);
220 
222 template<typename String, typename Arg>
223 inline auto toString(Arg&& arg) -> typename std::enable_if<std::is_same<String, std::string>::value, decltype(to_string(std::forward<Arg>(arg)))>::type
224 {
225  return to_string(std::forward<Arg>(arg));
226 }
227 
228 template<typename String, typename Arg>
229 inline auto toString(Arg&& arg) -> typename std::enable_if<std::is_same<String, std::wstring>::value, decltype(to_wstring(std::forward<Arg>(arg)))>::type
230 {
231  return to_wstring(std::forward<Arg>(arg));
232 }
233 
234 #if !defined(fzT) || defined(DOXYGEN)
235 #ifdef FZ_WINDOWS
236 
240 #define fzT(x) L ## x
241 #else
242 
246 #define fzT(x) x
247 #endif
248 #endif
249 
251 template<typename Char>
252 Char const* choose_string(char const* c, wchar_t const* w);
253 
254 template<> inline char const* choose_string(char const* c, wchar_t const*) { return c; }
255 template<> inline wchar_t const* choose_string(char const*, wchar_t const* w) { return w; }
256 
257 #if !defined(fzS) || defined(DOXYGEN)
258 
269 #define fzS(Char, s) fz::choose_string<Char>(s, L ## s)
270 #endif
271 
273 std::string FZ_PUBLIC_SYMBOL replaced_substrings(std::string const& in, std::string const& find, std::string const& replacement);
274 std::wstring FZ_PUBLIC_SYMBOL replaced_substrings(std::wstring const& in, std::wstring const& find, std::wstring const& replacement);
275 
277 bool FZ_PUBLIC_SYMBOL replace_substrings(std::string& in, std::string const& find, std::string const& replacement);
278 bool FZ_PUBLIC_SYMBOL replace_substrings(std::wstring& in, std::wstring const& find, std::wstring const& replacement);
279 
281 template<typename String, typename Delim, typename Container = std::vector<String>>
282 Container strtok(String const& s, Delim const& delims)
283 {
284  Container ret;
285 
286  typename String::size_type start{}, pos{};
287  do {
288  pos = s.find_first_of(delims, start);
289 
290  // Not found, we're at ends;
291  if (pos == String::npos) {
292  if (start < s.size()) {
293  ret.emplace_back(s.substr(start));
294  }
295  }
296  else if (pos > start) {
297  // Non-empty substring
298  ret.emplace_back(s.substr(start, pos - start));
299  }
300  start = pos + 1;
301  } while (pos != String::npos);
302 
303  return ret;
304 }
305 
306 // Converts string to integral type T. If string is not convertible, T() is returned.
307 template<typename T, typename String>
308 T to_integral(String const& s, T const errorval = T())
309 {
310  T ret{};
311 
312  auto it = s.cbegin();
313  if (it != s.cend() && (*it == '-' || *it == '+')) {
314  ++it;
315  }
316 
317  if (it == s.cend()) {
318  return errorval;
319  }
320 
321  for (; it != s.cend(); ++it) {
322  auto const& c = *it;
323  if (c < '0' || c > '9') {
324  return errorval;
325  }
326  ret *= 10;
327  ret += c - '0';
328  }
329 
330  if (!s.empty() && s.front() == '-') {
331  return ret *= static_cast<T>(-1);
332  }
333  else {
334  return ret;
335  }
336 }
337 
339 template<typename String>
340 bool str_is_ascii(String const& s) {
341  for (auto const& c : s) {
342  if (static_cast<std::make_unsigned_t<typename String::value_type>>(c) > 127) {
343  return false;
344  }
345  }
346 
347  return true;
348 }
349 
351 template<typename String>
352 String trimmed(String const& s, String const& chars = fzS(typename String::value_type, " \r\n\t"), bool fromLeft = true, bool fromRight = true) {
353  size_t const first = fromLeft ? s.find_first_not_of(chars) : 0;
354  if (first == String::npos) {
355  return String();
356  }
357 
358  size_t const last = fromRight ? s.find_last_not_of(chars) : s.size();
359  if (last == String::npos) {
360  return String();
361  }
362  return s.substr(first, last - first + 1);
363 }
364 
365 template<typename String>
366 String ltrimmed(String const& s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
367  return trimmed(s, chars, true, false);
368 }
369 
370 template<typename String>
371 String rtrimmed(String const& s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
372  return trimmed(s, chars, false, true);
373 }
374 
376 template<typename String>
377 void trim(String & s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
378  s = trimmed(s, chars);
379 }
380 
381 template<typename String>
382 void ltrim(String & s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
383  s = trimmed(s, chars, true, false);
384 }
385 
386 template<typename String>
387 void rtrim(String & s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
388  s = trimmed(s, chars, false, true);
389 }
390 
395 template<bool insensitive_ascii = false, typename String>
396 bool starts_with(String const& s, String const& beginning)
397 {
398  if (beginning.size() > s.size()) {
399  return false;
400  }
401  if (insensitive_ascii) {
402  return std::equal(beginning.begin(), beginning.end(), s.begin(), [](typename String::value_type const& a, typename String::value_type const& b) {
403  return tolower_ascii(a) == tolower_ascii(b);
404  });
405  }
406  else {
407  return std::equal(beginning.begin(), beginning.end(), s.begin());
408  }
409 }
410 
415 template<bool insensitive_ascii = false, typename String>
416 bool ends_with(String const& s, String const& ending)
417 {
418  if (ending.size() > s.size()) {
419  return false;
420  }
421 
422  if (insensitive_ascii) {
423  return std::equal(ending.rbegin(), ending.rend(), s.rbegin(), [](typename String::value_type const& a, typename String::value_type const& b) {
424  return tolower_ascii(a) == tolower_ascii(b);
425  });
426  }
427  else {
428  return std::equal(ending.rbegin(), ending.rend(), s.rbegin());
429  }
430 }
431 
432 }
433 
434 #endif
std::wstring to_wstring_from_utf8(std::string const &in)
Converts from std::string in UTF-8 into std::wstring.
Comparator to be used for std::map for case-insentitive keys.
Definition: string.hpp:127
bool starts_with(String const &s, String const &beginning)
Tests whether the first string starts with the second string.
Definition: string.hpp:396
Char toupper_ascii(Char c)
Converts ASCII lowercase characters to uppercase as if C-locale is used.
Definition: string.hpp:89
bool equal_insensitive_ascii(String const &a, String const &b)
Locale-insensitive stricmp.
Definition: string.hpp:144
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:166
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:192
#define fzS(Char, s)
Macro to get const pointer to a string of the corresponding type.
Definition: string.hpp:269
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:77
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.
size_t strlen(Char const *str)
Returns length of 0-terminated character sequence. Works with both narrow and wide-characters.
Definition: string.hpp:200
bool str_is_ascii(String const &s)
Returns true iff the string only has characters in the 7-bit ASCII range.
Definition: string.hpp:340
Container strtok(String const &s, Delim const &delims)
Tokenizes string. Returns all non-empty substrings.
Definition: string.hpp:282
bool ends_with(String const &s, String const &ending)
Tests whether the first string ends with the second string.
Definition: string.hpp:416
String trimmed(String const &s, String const &chars=fz::choose_string< typename String::value_type >(" \r\n\t", L" \r\n\t"), bool fromLeft=true, bool fromRight=true)
Return passed string with all leading and trailing whitespace removed.
Definition: string.hpp:352
std::wstring native_string
A string in the system's native character type and encoding. Note: This typedef changes depending on...
Definition: string.hpp:32
bool replace_substrings(std::string &in, std::string const &find, std::string const &replacement)
Modifies in, replacing all occurrences of find with replacement.
std::string to_string(std::wstring const &in)
Converts from std::wstring into std::string in system encoding.
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:254
void trim(String &s, String const &chars=fz::choose_string< typename String::value_type >(" \r\n\t", L" \r\n\t"))
Remove all leading and trailing whitespace from string.
Definition: string.hpp:377
String str_tolower_ascii(String const &s)
tr_tolower_ascii does for strings what tolower_ascii does for individual characters ...
Definition: string.hpp:103
Sets some global macros and further includes string.hpp.
native_string to_native(std::string const &in)
Converts std::string to native_string.
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:223
std::wstring to_wstring(std::string const &in)
Converts from std::string in system encoding into std::wstring.