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