1 #ifndef LIBFILEZILLA_STRING_HEADER
2 #define LIBFILEZILLA_STRING_HEADER
35 typedef std::wstring_view native_string_view;
37 #if defined(FZ_UNIX) || defined(FZ_MAC)
39 typedef std::string_view native_string_view;
55 template<
typename T,
typename std::enable_if_t<std::is_same_v<native_
string,
typename std::decay_t<T>>,
int> = 0>
66 int FZ_PUBLIC_SYMBOL
stricmp(std::string_view
const& a, std::string_view
const& b);
67 int FZ_PUBLIC_SYMBOL
stricmp(std::wstring_view
const& a, std::wstring_view
const& b);
86 template<
typename Char>
88 if (c >=
'A' && c <=
'Z') {
89 return c + (
'a' -
'A');
95 std::wstring::value_type FZ_PUBLIC_SYMBOL
tolower_ascii(std::wstring::value_type c);
98 template<
typename Char>
100 if (c >=
'a' && c <=
'z') {
101 return c + (
'A' -
'a');
107 std::wstring::value_type FZ_PUBLIC_SYMBOL
toupper_ascii(std::wstring::value_type c);
115 std::string FZ_PUBLIC_SYMBOL str_toupper_ascii(std::string_view
const& s);
116 std::wstring FZ_PUBLIC_SYMBOL str_toupper_ascii(std::wstring_view
const& s);
126 bool operator()(T
const& lhs, T
const& rhs)
const {
127 return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(),
128 [](
typename T::value_type
const& a,
typename T::value_type
const& b) {
129 return tolower_ascii(a) < tolower_ascii(b);
141 return std::equal(a.cbegin(), a.cend(), b.cbegin(), b.cend(),
142 [](
auto const& a,
auto const& b) {
143 return tolower_ascii(a) == tolower_ascii(b);
149 return std::equal(a.cbegin(), a.cend(), b.cbegin(), b.cend(),
150 [](
auto const& a,
auto const& b) {
151 return tolower_ascii(a) == tolower_ascii(b);
160 std::wstring FZ_PUBLIC_SYMBOL
to_wstring(std::string_view
const& in);
166 template <
typename T>
167 inline auto to_wstring(T && in) -> decltype(std::wstring(std::forward<T>(in)))
169 return std::wstring(std::forward<T>(in));
173 template<
typename Arg>
174 inline typename std::enable_if<std::is_arithmetic_v<std::decay_t<Arg>>, std::wstring>::type
to_wstring(Arg && arg)
194 std::string FZ_PUBLIC_SYMBOL
to_string(std::wstring_view
const& in);
200 template <
typename T>
201 inline auto to_string(T && in) -> decltype(std::string(std::forward<T>(in)))
203 return std::string(std::forward<T>(in));
208 template<
typename Arg>
209 inline typename std::enable_if<std::is_arithmetic_v<std::decay_t<Arg>>, std::string>::type
to_string(Arg && arg)
216 template<
typename Char>
218 return std::char_traits<Char>::length(str);
228 std::string FZ_PUBLIC_SYMBOL
to_utf8(std::string_view
const& in);
236 std::string FZ_PUBLIC_SYMBOL
to_utf8(std::wstring_view
const& in);
239 template<
typename String,
typename Arg>
240 inline auto toString(Arg&& arg) ->
typename std::enable_if<std::is_same_v<String, std::string>, decltype(
to_string(std::forward<Arg>(arg)))>::type
242 return to_string(std::forward<Arg>(arg));
245 template<
typename String,
typename Arg>
246 inline auto toString(Arg&& arg) ->
typename std::enable_if<std::is_same_v<String, std::wstring>, decltype(
to_wstring(std::forward<Arg>(arg)))>::type
251 #if !defined(fzT) || defined(DOXYGEN)
257 #define fzT(x) L ## x
268 template<
typename Char>
271 template<>
inline char const*
choose_string(
char const* c,
wchar_t const*) {
return c; }
272 template<>
inline wchar_t const*
choose_string(
char const*,
wchar_t const* w) {
return w; }
274 #if !defined(fzS) || defined(DOXYGEN)
286 #define fzS(Char, s) fz::choose_string<Char>(s, L ## s)
293 std::string FZ_PUBLIC_SYMBOL
replaced_substrings(std::string_view
const& in, std::string_view
const& find, std::string_view
const& replacement);
294 std::wstring FZ_PUBLIC_SYMBOL
replaced_substrings(std::wstring_view
const& in, std::wstring_view
const& find, std::wstring_view
const& replacement);
297 std::string FZ_PUBLIC_SYMBOL
replaced_substrings(std::string_view
const& in,
char find,
char replacement);
298 std::wstring FZ_PUBLIC_SYMBOL
replaced_substrings(std::wstring_view
const& in,
wchar_t find,
wchar_t replacement);
304 bool FZ_PUBLIC_SYMBOL
replace_substrings(std::string& in, std::string_view
const& find, std::string_view
const& replacement);
305 bool FZ_PUBLIC_SYMBOL
replace_substrings(std::wstring& in, std::wstring_view
const& find, std::wstring_view
const& replacement);
309 bool FZ_PUBLIC_SYMBOL
replace_substrings(std::wstring& in,
wchar_t find,
wchar_t replacement);
337 template <
typename String,
typename Delims>
340 using view_type = std::basic_string_view<std::decay_t<decltype(std::declval<String>()[0])>>;
349 constexpr
strtokenizer(String &&
string, Delims &&delims,
bool ignore_empty)
350 : string_(std::forward<String>(string))
351 , delims_(std::forward<Delims>(delims))
352 , ignore_empty_(ignore_empty)
355 using value_type =
const view_type;
356 using pointer = value_type*;
357 using reference = value_type&;
358 using size_type = std::size_t;
359 using difference_type = std::ptrdiff_t;
365 using iterator_category = std::input_iterator_tag;
366 using difference_type = strtokenizer::difference_type;
367 using value_type = strtokenizer::value_type;
368 using pointer = strtokenizer::pointer;
369 using reference = strtokenizer::reference;
371 constexpr
bool operator !=(
sentinel)
const
376 constexpr
bool operator ==(
sentinel)
const
381 constexpr value_type operator*()
const
383 return s_.substr(0, pos_);
389 if (pos_ != s_.size()) {
393 s_.remove_prefix(pos_);
395 pos_ = s_.find_first_of(t_->delims_);
397 if (pos_ == view_type::npos) {
402 if (pos_ != 0 || !t_->ignore_empty_) {
415 , s_(view_type(t_->string_))
416 , pos_(view_type::npos)
426 using const_value_type = value_type;
427 using const_pointer = pointer;
428 using const_reference = reference;
436 constexpr sentinel end()
const
441 constexpr const_iterator cbegin()
const
446 constexpr sentinel cend()
const
463 template <
typename String,
typename Delims>
472 std::vector<std::string> FZ_PUBLIC_SYMBOL
strtok(std::string_view
const& tokens, std::string_view
const& delims,
bool const ignore_empty =
true);
473 std::vector<std::wstring> FZ_PUBLIC_SYMBOL
strtok(std::wstring_view
const& tokens, std::wstring_view
const& delims,
bool const ignore_empty =
true);
474 inline auto FZ_PUBLIC_SYMBOL
strtok(std::string_view
const& tokens,
char const delim,
bool const ignore_empty =
true) {
475 return strtok(tokens, std::string_view(&delim, 1), ignore_empty);
477 inline auto FZ_PUBLIC_SYMBOL
strtok(std::wstring_view
const& tokens,
wchar_t const delim,
bool const ignore_empty =
true) {
478 return strtok(tokens, std::wstring_view(&delim, 1), ignore_empty);
489 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);
490 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);
491 inline auto FZ_PUBLIC_SYMBOL
strtok_view(std::string_view
const& tokens,
char const delim,
bool const ignore_empty =
true) {
492 return strtok_view(tokens, std::string_view(&delim, 1), ignore_empty);
494 inline auto FZ_PUBLIC_SYMBOL
strtok_view(std::wstring_view
const& tokens,
wchar_t const delim,
bool const ignore_empty =
true) {
495 return strtok_view(tokens, std::wstring_view(&delim, 1), ignore_empty);
499 template<
typename T,
typename String>
500 T to_integral_impl(String
const& s, T
const errorval = T())
502 if constexpr (std::is_same_v<T, bool>) {
503 return static_cast<T
>(to_integral_impl<unsigned int>(s,
static_cast<unsigned int>(errorval))) != 0;
505 else if constexpr (std::is_enum_v<T>) {
506 return static_cast<T
>(to_integral_impl<std::underlying_type_t<T>>(s,
static_cast<std::underlying_type_t<T>
>(errorval)));
510 auto it = s.cbegin();
511 if (it != s.cend() && (*it ==
'-' || *it ==
'+')) {
515 if (it == s.cend()) {
519 for (; it != s.cend(); ++it) {
521 if (c < '0' || c >
'9') {
528 if (!s.empty() && s.front() ==
'-') {
529 ret *=
static_cast<T
>(-1);
537 T
to_integral(std::string_view
const& s, T
const errorval = T()) {
538 return to_integral_impl<T>(s, errorval);
542 T
to_integral(std::wstring_view
const& s, T
const errorval = T()) {
543 return to_integral_impl<T>(s, errorval);
546 template<
typename T,
typename StringType>
547 T
to_integral(std::basic_string_view<StringType>
const& s, T
const errorval = T()) {
548 return to_integral_impl<T>(s, errorval);
553 template<
typename String>
555 for (
auto const& c : s) {
556 if (
static_cast<std::make_unsigned_t<typename String::value_type>
>(c) > 127) {
565 template<
typename String,
typename Chars>
566 void trim_impl(String & s, Chars
const& chars,
bool fromLeft,
bool fromRight) {
567 size_t const first = fromLeft ? s.find_first_not_of(chars) : 0;
568 if (first == String::npos) {
573 size_t const last = fromRight ? s.find_last_not_of(chars) : s.size();
574 if (last == String::npos) {
580 s = s.substr(first, last - first + 1);
584 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)
586 trim_impl(s, chars, fromLeft, fromRight);
587 return std::string(s);
590 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)
592 trim_impl(s, chars, fromLeft, fromRight);
593 return std::wstring(s);
596 inline std::string FZ_PUBLIC_SYMBOL ltrimmed(std::string_view s, std::string_view
const& chars =
" \r\n\t")
598 trim_impl(s, chars,
true,
false);
599 return std::string(s);
602 inline std::wstring FZ_PUBLIC_SYMBOL ltrimmed(std::wstring_view s, std::wstring_view
const& chars = L
" \r\n\t")
604 trim_impl(s, chars,
true,
false);
605 return std::wstring(s);
608 inline std::string FZ_PUBLIC_SYMBOL rtrimmed(std::string_view s, std::string_view
const& chars =
" \r\n\t")
610 trim_impl(s, chars,
false,
true);
611 return std::string(s);
614 inline std::wstring FZ_PUBLIC_SYMBOL rtrimmed(std::wstring_view s, std::wstring_view
const& chars = L
" \r\n\t")
616 trim_impl(s, chars,
false,
true);
617 return std::wstring(s);
622 template<
typename String,
typename std::enable_if_t<std::is_same_v<
typename String::value_type,
char>,
int> = 0>
623 inline void trim(String & s, std::string_view
const& chars =
" \r\n\t",
bool fromLeft =
true,
bool fromRight =
true)
625 trim_impl(s, chars, fromLeft, fromRight);
628 template<
typename String,
typename std::enable_if_t<std::is_same_v<
typename String::value_type,
wchar_t>,
int> = 0>
629 inline void trim(String & s, std::wstring_view
const& chars = L
" \r\n\t",
bool fromLeft =
true,
bool fromRight =
true)
631 trim_impl(s, chars, fromLeft, fromRight);
634 template<
typename String,
typename std::enable_if_t<std::is_same_v<
typename String::value_type,
char>,
int> = 0>
635 inline void ltrim(String& s, std::string_view
const& chars =
" \r\n\t")
637 trim_impl(s, chars,
true,
false);
640 template<
typename String,
typename std::enable_if_t<std::is_same_v<
typename String::value_type,
wchar_t>,
int> = 0>
641 inline void ltrim(String& s, std::wstring_view
const& chars = L
" \r\n\t")
643 trim_impl(s, chars,
true,
false);
646 template<
typename String,
typename std::enable_if_t<std::is_same_v<
typename String::value_type,
char>,
int> = 0>
647 inline void rtrim(String& s, std::string_view
const& chars =
" \r\n\t")
649 trim_impl(s, chars,
false,
true);
652 template<
typename String,
typename std::enable_if_t<std::is_same_v<
typename String::value_type,
wchar_t>,
int> = 0>
653 inline void rtrim(String & s, std::wstring_view
const& chars = L
" \r\n\t")
655 trim_impl(s, chars,
false,
true);
662 template<
bool insensitive_ascii = false,
typename String>
665 if (beginning.size() > s.size()) {
668 if constexpr (insensitive_ascii) {
669 return std::equal(beginning.begin(), beginning.end(), s.begin(), [](
typename String::value_type
const& a,
typename String::value_type
const& b) {
670 return tolower_ascii(a) == tolower_ascii(b);
674 return std::equal(beginning.begin(), beginning.end(), s.begin());
682 template<
bool insensitive_ascii = false,
typename String>
685 if (ending.size() > s.size()) {
689 if constexpr (insensitive_ascii) {
690 return std::equal(ending.rbegin(), ending.rend(), s.rbegin(), [](
typename String::value_type
const& a,
typename String::value_type
const& b) {
691 return tolower_ascii(a) == tolower_ascii(b);
695 return std::equal(ending.rbegin(), ending.rend(), s.rbegin());
764 inline native_string to_native_from_utf8(std::string_view s) {
The buffer class is a simple buffer where data can be appended at the end and consumed at the front....
Definition: buffer.hpp:27
Small class to return filesystem errors.
Definition: fsresult.hpp:26
Container-like class that can be used to iterate over tokens in a string.
Definition: string.hpp:339
constexpr strtokenizer(String &&string, Delims &&delims, bool ignore_empty)
strtokenizer class constructor.
Definition: string.hpp:349
Sets some global macros and further includes string.hpp.
The namespace used by libfilezilla.
Definition: apply.hpp:17
strtokenizer(String &&string, Delims &&delims, bool ignore_empty) -> strtokenizer< String, Delims >
strtokenizer class construction-guide.
std::wstring to_wstring_from_utf8(std::string_view const &in)
Converts from std::string in UTF-8 into std::wstring.
bool utf16le_to_utf8_append(std::string &result, std::string_view data, uint32_t &state)
Just as utf16be_to_utf8_append but for little-endian UTF-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:271
bool ends_with(String const &s, String const &ending)
Tests whether the first string ends with the second string.
Definition: string.hpp:683
Char toupper_ascii(Char c)
Converts ASCII lowercase characters to uppercase as if C-locale is used.
Definition: string.hpp:99
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:584
bool is_valid_utf8(std::string_view s)
Verifies that the input data is valid UTF-8.
auto toString(Arg &&arg) -> typename std::enable_if< std::is_same_v< String, std::string >, 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:240
std::string normalize_hyphens(std::string_view const &in)
std::wstring to_wstring(std::string_view const &in)
Converts from std::string in system encoding into std::wstring.
Char tolower_ascii(Char c)
Converts ASCII uppercase characters to lowercase as if C-locale is used.
Definition: string.hpp:87
size_t strlen(Char const *str)
Returns length of 0-terminated character sequence. Works with both narrow and wide-characters.
Definition: string.hpp:217
std::wstring native_string
A string in the system's native character type and encoding. Note: This typedef changes depending on...
Definition: string.hpp:34
std::string replaced_substrings(std::string_view const &in, std::string_view const &find, std::string_view const &replacement)
Returns in with all occurrences of find in the input string replaced with replacement.
int stricmp(std::string_view const &a, std::string_view const &b)
Locale-sensitive stricmp.
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 str_tolower_ascii(std::string_view const &s)
tr_tolower_ascii does for strings what tolower_ascii does for individual characters
std::enable_if< std::is_arithmetic_v< std::decay_t< Arg > >, std::string >::type to_string(Arg &&arg)
Converts from arithmetic type to std::string.
Definition: string.hpp:209
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:623
bool str_is_ascii(String const &s)
Returns true iff the string only has characters in the 7-bit ASCII range.
Definition: string.hpp:554
std::string to_string(std::wstring_view const &in)
Converts from std::wstring into std::string in system encoding.
bool starts_with(String const &s, String const &beginning)
Tests whether the first string starts with the second string.
Definition: string.hpp:663
bool equal_insensitive_ascii(std::string_view a, std::string_view 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_v< std::decay_t< Arg > >, std::wstring >::type to_wstring(Arg &&arg)
Converts from arithmetic type to std::wstring.
Definition: string.hpp:174
void unicode_codepoint_to_utf8_append(std::string &result, uint32_t codepoint)
Encodes a valid Unicode codepoint as UTF-8 and appends it to the passed string.
bool replace_substrings(std::string &in, std::string_view const &find, std::string_view const &replacement)
Modifies in, replacing all occurrences of find with replacement.
std::vector< std::string > strtok(std::string_view const &tokens, std::string_view const &delims, bool const ignore_empty=true)
Tokenizes string.
bool utf16be_to_utf8_append(std::string &result, std::string_view data, uint32_t &state)
Converts from UTF-16-BE and appends it to the passed string.
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:537
native_string to_native(std::string_view const &in)
Converts std::string to native_string.
Comparator to be used for std::map for case-insensitive keys.
Definition: string.hpp:124
Definition: string.hpp:364
Definition: string.hpp:361