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 <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 
145 std::wstring FZ_PUBLIC_SYMBOL to_wstring(std::string const& in);
146 
148 inline std::wstring FZ_PUBLIC_SYMBOL to_wstring(std::wstring const& in) { return in; }
149 
151 template<typename Arg>
152 inline typename std::enable_if<std::is_arithmetic<std::decay_t<Arg>>::value, std::wstring>::type to_wstring(Arg && arg)
153 {
154  return std::to_wstring(std::forward<Arg>(arg));
155 }
156 
157 
162 std::wstring FZ_PUBLIC_SYMBOL to_wstring_from_utf8(std::string const& in);
163 std::wstring FZ_PUBLIC_SYMBOL to_wstring_from_utf8(char const* s, size_t len);
164 
171 std::string FZ_PUBLIC_SYMBOL to_string(std::wstring const& in);
172 
174 inline std::string FZ_PUBLIC_SYMBOL to_string(std::string const& in) { return in; }
175 
177 template<typename Arg>
178 inline typename std::enable_if<std::is_arithmetic<std::decay_t<Arg>>::value, std::string>::type to_string(Arg && arg)
179 {
180  return std::to_string(std::forward<Arg>(arg));
181 }
182 
183 
185 template<typename Char>
186 size_t strlen(Char const* str) {
187  return std::char_traits<Char>::length(str);
188 }
189 
190 
197 std::string FZ_PUBLIC_SYMBOL to_utf8(std::string const& in);
198 
205 std::string FZ_PUBLIC_SYMBOL to_utf8(std::wstring const& in);
206 
208 template<typename String, typename Arg>
209 inline auto toString(Arg&& arg) -> typename std::enable_if<std::is_same<String, std::string>::value, decltype(to_string(std::forward<Arg>(arg)))>::type
210 {
211  return to_string(std::forward<Arg>(arg));
212 }
213 
214 template<typename String, typename Arg>
215 inline auto toString(Arg&& arg) -> typename std::enable_if<std::is_same<String, std::wstring>::value, decltype(to_wstring(std::forward<Arg>(arg)))>::type
216 {
217  return to_wstring(std::forward<Arg>(arg));
218 }
219 
220 #if !defined(fzT) || defined(DOXYGEN)
221 #ifdef FZ_WINDOWS
222 
226 #define fzT(x) L ## x
227 #else
228 
232 #define fzT(x) x
233 #endif
234 #endif
235 
237 template<typename Char>
238 Char const* choose_string(char const* c, wchar_t const* w);
239 
240 template<> inline char const* choose_string(char const* c, wchar_t const*) { return c; }
241 template<> inline wchar_t const* choose_string(char const*, wchar_t const* w) { return w; }
242 
243 #if !defined(fzS) || defined(DOXYGEN)
244 
255 #define fzS(Char, s) fz::choose_string<Char>(s, L ## s)
256 #endif
257 
259 std::string FZ_PUBLIC_SYMBOL replaced_substrings(std::string const& in, std::string const& find, std::string const& replacement);
260 std::wstring FZ_PUBLIC_SYMBOL replaced_substrings(std::wstring const& in, std::wstring const& find, std::wstring const& replacement);
261 
263 void FZ_PUBLIC_SYMBOL replace_substrings(std::string& in, std::string const& find, std::string const& replacement);
264 void FZ_PUBLIC_SYMBOL replace_substrings(std::wstring& in, std::wstring const& find, std::wstring const& replacement);
265 
267 template<typename String, typename Delim, typename Container = std::vector<String>>
268 Container strtok(String const& s, Delim const& delims)
269 {
270  Container ret;
271 
272  typename String::size_type start{}, pos{};
273  do {
274  pos = s.find_first_of(delims, start);
275 
276  // Not found, we're at ends;
277  if (pos == String::npos) {
278  if (start < s.size()) {
279  ret.emplace_back(s.substr(start));
280  }
281  }
282  else if (pos > start) {
283  // Non-empty substring
284  ret.emplace_back(s.substr(start, pos - start));
285  }
286  start = pos + 1;
287  } while (pos != String::npos);
288 
289  return ret;
290 }
291 
292 // Converts string to integral type T. If string is not convertible, T() is returned.
293 template<typename T, typename String>
294 T to_integral(String const& s, T const errorval = T())
295 {
296  T ret{};
297 
298  auto it = s.cbegin();
299  if (it != s.cend() && (*it == '-' || *it == '+')) {
300  ++it;
301  }
302 
303  if (it == s.cend()) {
304  return errorval;
305  }
306 
307  for (; it != s.cend(); ++it) {
308  auto const& c = *it;
309  if (c < '0' || c > '9') {
310  return errorval;
311  }
312  ret *= 10;
313  ret += c - '0';
314  }
315 
316  if (!s.empty() && s.front() == '-') {
317  return ret *= static_cast<T>(-1);
318  }
319  else {
320  return ret;
321  }
322 }
323 
325 template<typename String>
326 bool str_is_ascii(String const& s) {
327  for (auto const& c : s) {
328  if (static_cast<std::make_unsigned_t<typename String::value_type>>(c) > 127) {
329  return false;
330  }
331  }
332 
333  return true;
334 }
335 
337 template<typename String>
338 String trimmed(String const& s, String const& chars = fzS(typename String::value_type, " \r\n\t"), bool fromLeft = true, bool fromRight = true) {
339  size_t const first = fromLeft ? s.find_first_not_of(chars) : 0;
340  if (first == String::npos) {
341  return String();
342  }
343 
344  size_t const last = fromRight ? s.find_last_not_of(chars) : s.size();
345  if (last == String::npos) {
346  return String();
347  }
348  return s.substr(first, last - first + 1);
349 }
350 
351 template<typename String>
352 String ltrimmed(String const& s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
353  return trimmed(s, chars, true, false);
354 }
355 
356 template<typename String>
357 String rtrimmed(String const& s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
358  return trimmed(s, chars, false, true);
359 }
360 
362 template<typename String>
363 void trim(String & s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
364  s = trimmed(s, chars);
365 }
366 
367 template<typename String>
368 void ltrim(String & s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
369  s = trimmed(s, chars, true, false);
370 }
371 
372 template<typename String>
373 void rtrim(String & s, String const& chars = fzS(typename String::value_type, " \r\n\t")) {
374  s = trimmed(s, chars, false, true);
375 }
376 
377 // Remove once C++20 is minimum required standard to build libfilezilla
378 template<typename String>
379 bool starts_with(String const& s, String const& beginning)
380 {
381  if (beginning.size() > s.size()) {
382  return false;
383  }
384  return std::equal(beginning.begin(), beginning.end(), s.begin());
385 }
386 
387 // Remove once C++20 is minimum required standard to build libfilezilla
388 template<typename String>
389 bool ends_with(String const& s, String const& ending)
390 {
391  if (ending.size() > s.size()) {
392  return false;
393  }
394  return std::equal(ending.rbegin(), ending.rend(), s.rbegin());
395 }
396 
397 }
398 
399 #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
Char toupper_ascii(Char c)
Converts ASCII lowercase characters to uppercase as if C-locale is used.
Definition: string.hpp:89
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:152
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:178
#define fzS(Char, s)
Macro to get const pointer to a string of the corresponding type.
Definition: string.hpp:255
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.
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:186
bool str_is_ascii(String const &s)
Returns true iff the string only has characters in the 7-bit ASCII range.
Definition: string.hpp:326
Container strtok(String const &s, Delim const &delims)
Tokenizes string. Returns all non-empty substrings.
Definition: string.hpp:268
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:32
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:240
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:363
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:209
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:338
std::wstring to_wstring(std::string const &in)
Converts from std::string in system encoding into std::wstring.