1#ifndef LIBFILEZILLA_STRING_HEADER
2#define LIBFILEZILLA_STRING_HEADER
14template<
class CharT,
class BaseT>
18 using char_type = CharT;
20 using base_type = BaseT;
21 using base_traits = std::char_traits<base_type>;
23 static std::size_t length(char_type
const* s) {
24 return base_traits::length(
reinterpret_cast<base_type const*
>(s));
26 static int compare(char_type
const* s1, char_type
const* s2, std::size_t count) {
27 return base_traits::compare(
reinterpret_cast<base_type const*
>(s1),
reinterpret_cast<base_type const*
>(s2), count);
29 static char_type* copy(char_type* dest, char_type
const* src, std::size_t count) {
30 return reinterpret_cast<char_type*
>(base_traits::copy(
reinterpret_cast<base_type*
>(dest),
reinterpret_cast<base_type const*
>(src), count));
32 static void assign( char_type& c1, char_type
const& c2 )
noexcept {
35 static char_type
const* find(char_type
const* ptr, std::size_t count, char_type
const& ch) {
36 return reinterpret_cast<char_type const*
>(base_traits::find(
reinterpret_cast<base_type const*
>(ptr), count,
reinterpret_cast<base_type const&
>(ch)));
38 static bool eq(char_type a, char_type b) {
39 return base_traits::eq(
static_cast<base_type
>(a),
static_cast<base_type
>(b));
70typedef std::wstring_view native_string_view;
72#if defined(FZ_UNIX) || defined(FZ_MAC)
74typedef std::string_view native_string_view;
90template<
typename T,
typename std::enable_if_t<std::is_same_v<native_
string,
typename std::decay_t<T>>,
int> = 0>
101int FZ_PUBLIC_SYMBOL
stricmp(std::string_view
const& a, std::string_view
const& b);
102int FZ_PUBLIC_SYMBOL
stricmp(std::wstring_view
const& a, std::wstring_view
const& b);
121template<
typename Char>
123 if (c >=
'A' && c <=
'Z') {
124 return c + (
'a' -
'A');
130std::wstring::value_type FZ_PUBLIC_SYMBOL
tolower_ascii(std::wstring::value_type c);
133template<
typename Char>
135 if (c >=
'a' && c <=
'z') {
136 return c + (
'A' -
'a');
142std::wstring::value_type FZ_PUBLIC_SYMBOL
toupper_ascii(std::wstring::value_type c);
150std::string FZ_PUBLIC_SYMBOL str_toupper_ascii(std::string_view
const& s);
151std::wstring FZ_PUBLIC_SYMBOL str_toupper_ascii(std::wstring_view
const& s);
155template<
typename T,
typename =
void>
160 using type =
typename T::value_type;
163template<
typename CharT>
165 using type = std::remove_cv_t<CharT>;
168template<
typename CharT, std::
size_t N>
170 using type = std::remove_cv_t<CharT>;
173template<
typename CharT, std::
size_t N>
175 using type = std::remove_cv_t<CharT>;
189 using is_transparent = std::true_type;
191 template<
typename L,
typename R,
192 std::enable_if_t<std::is_same_v<string_value_type_t<L>, string_value_type_t<R>>>* =
nullptr>
193 bool operator()(L
const& lhs, R
const& rhs)
const {
194 std::basic_string_view<string_value_type_t<L>> lv(lhs);
195 std::basic_string_view<string_value_type_t<R>> rv(rhs);
197 return std::lexicographical_compare(lv.begin(), lv.end(), rv.begin(), rv.end(),
198 [](
auto const& a,
auto const& b) {
199 return tolower_ascii(a) < tolower_ascii(b);
209template<
typename A,
typename B,
210 std::enable_if_t<std::is_same_v<string_value_type_t<A>, string_value_type_t<B>>>* =
nullptr>
213 std::basic_string_view<string_value_type_t<A>> av(a);
214 std::basic_string_view<string_value_type_t<B>> bv(b);
216 return std::equal(av.cbegin(), av.cend(), bv.cbegin(), bv.cend(),
217 [](
auto const& a,
auto const& b) {
218 return tolower_ascii(a) == tolower_ascii(b);
227std::wstring FZ_PUBLIC_SYMBOL
to_wstring(std::string_view
const& in);
234inline auto to_wstring(T && in) ->
decltype(std::wstring(std::forward<T>(in)))
236 return std::wstring(std::forward<T>(in));
240template<
typename Arg>
241inline typename std::enable_if<std::is_arithmetic_v<std::decay_t<Arg>>, std::wstring>::type
to_wstring(Arg && arg)
243 return std::to_wstring(std::forward<Arg>(arg));
261std::string FZ_PUBLIC_SYMBOL
to_string(std::wstring_view
const& in);
268inline auto to_string(T && in) ->
decltype(std::string(std::forward<T>(in)))
270 return std::string(std::forward<T>(in));
275template<
typename Arg>
276inline typename std::enable_if<std::is_arithmetic_v<std::decay_t<Arg>>, std::string>::type
to_string(Arg && arg)
278 return std::to_string(std::forward<Arg>(arg));
283template<
typename Char>
285 return std::char_traits<Char>::length(str);
295std::string FZ_PUBLIC_SYMBOL
to_utf8(std::string_view
const& in);
303std::string FZ_PUBLIC_SYMBOL
to_utf8(std::wstring_view
const& in);
306template<
typename String,
typename Arg>
307inline auto toString(Arg&& arg) ->
typename std::enable_if<std::is_same_v<String, std::string>,
decltype(
to_string(std::forward<Arg>(arg)))>::type
309 return to_string(std::forward<Arg>(arg));
312template<
typename String,
typename Arg>
313inline auto toString(Arg&& arg) ->
typename std::enable_if<std::is_same_v<String, std::wstring>,
decltype(
to_wstring(std::forward<Arg>(arg)))>::type
318#if !defined(fzT) || defined(DOXYGEN)
335template<
typename Char>
338template<>
constexpr inline char const*
choose_string(
char const* c,
wchar_t const*) {
return c; }
339template<>
constexpr inline wchar_t const*
choose_string(
char const*,
wchar_t const* w) {
return w; }
341#if !defined(fzS) || defined(DOXYGEN)
353#define fzS(Char, s) fz::choose_string<Char>(s, L ## s)
360std::string FZ_PUBLIC_SYMBOL
replaced_substrings(std::string_view
const& in, std::string_view
const& find, std::string_view
const& replacement);
361std::wstring FZ_PUBLIC_SYMBOL
replaced_substrings(std::wstring_view
const& in, std::wstring_view
const& find, std::wstring_view
const& replacement);
365std::wstring FZ_PUBLIC_SYMBOL
replaced_substrings(std::wstring_view
const& in,
wchar_t find,
wchar_t replacement);
371bool FZ_PUBLIC_SYMBOL
replace_substrings(std::string& in, std::string_view
const& find, std::string_view
const& replacement);
372bool FZ_PUBLIC_SYMBOL
replace_substrings(std::wstring& in, std::wstring_view
const& find, std::wstring_view
const& replacement);
376bool FZ_PUBLIC_SYMBOL
replace_substrings(std::wstring& in,
wchar_t find,
wchar_t replacement);
404template <
typename String,
typename Delims>
407 using view_type = std::basic_string_view<std::decay_t<decltype(std::declval<String>()[0])>>;
416 constexpr strtokenizer(String &&
string, Delims &&delims,
bool ignore_empty)
417 : string_(std::forward<String>(string))
418 , delims_(std::forward<Delims>(delims))
419 , ignore_empty_(ignore_empty)
422 using value_type =
const view_type;
423 using pointer = value_type*;
424 using reference = value_type&;
425 using size_type = std::size_t;
426 using difference_type = std::ptrdiff_t;
432 using iterator_category = std::input_iterator_tag;
433 using difference_type = strtokenizer::difference_type;
434 using value_type = strtokenizer::value_type;
435 using pointer = strtokenizer::pointer;
436 using reference = strtokenizer::reference;
438 constexpr bool operator !=(
sentinel)
const
443 constexpr bool operator ==(
sentinel)
const
448 constexpr bool operator ==(iterator
const& op)
const
450 return s_.size() == op.s_.size();
453 constexpr bool operator !=(iterator
const& op)
const
455 return s_.size() != op.s_.size();
458 constexpr value_type operator*()
const
460 return s_.substr(0, pos_);
463 constexpr iterator &operator++()
466 if (pos_ != s_.size()) {
470 s_.remove_prefix(pos_);
472 pos_ = s_.find_first_of(t_->delims_);
474 if (pos_ == view_type::npos) {
479 if (pos_ != 0 || !t_->ignore_empty_) {
490 constexpr iterator(
const strtokenizer *t)
492 , s_(view_type(t_->string_))
493 , pos_(view_type::npos)
498 const strtokenizer *t_;
503 using const_value_type = value_type;
504 using const_pointer = pointer;
505 using const_reference = reference;
513 constexpr sentinel end()
const
518 constexpr const_iterator cbegin()
const
540template <
typename String,
typename Delims>
549std::vector<std::string> FZ_PUBLIC_SYMBOL
strtok(std::string_view
const& tokens, std::string_view
const& delims,
bool const ignore_empty =
true);
550std::vector<std::wstring> FZ_PUBLIC_SYMBOL
strtok(std::wstring_view
const& tokens, std::wstring_view
const& delims,
bool const ignore_empty =
true);
551inline auto FZ_PUBLIC_SYMBOL
strtok(std::string_view
const& tokens,
char const delim,
bool const ignore_empty =
true) {
552 return strtok(tokens, std::string_view(&delim, 1), ignore_empty);
554inline auto FZ_PUBLIC_SYMBOL
strtok(std::wstring_view
const& tokens,
wchar_t const delim,
bool const ignore_empty =
true) {
555 return strtok(tokens, std::wstring_view(&delim, 1), ignore_empty);
566std::vector<std::string_view> FZ_PUBLIC_SYMBOL
strtok_view(std::string_view
const& tokens, std::string_view
const& delims,
bool const ignore_empty =
true);
567std::vector<std::wstring_view> FZ_PUBLIC_SYMBOL
strtok_view(std::wstring_view
const& tokens, std::wstring_view
const& delims,
bool const ignore_empty =
true);
568inline auto FZ_PUBLIC_SYMBOL
strtok_view(std::string_view
const& tokens,
char const delim,
bool const ignore_empty =
true) {
569 return strtok_view(tokens, std::string_view(&delim, 1), ignore_empty);
571inline auto FZ_PUBLIC_SYMBOL
strtok_view(std::wstring_view
const& tokens,
wchar_t const delim,
bool const ignore_empty =
true) {
572 return strtok_view(tokens, std::wstring_view(&delim, 1), ignore_empty);
576template<
typename T,
typename String>
577bool to_integral_impl(String
const& s, T & v)
579 if constexpr (std::is_same_v<T, bool>) {
581 if (!to_integral_impl(s, w)) {
587 else if constexpr (std::is_enum_v<T>) {
588 return to_integral_impl<std::underlying_type_t<T>>(s,
reinterpret_cast<std::underlying_type_t<T>&
>(v));
593 auto it = s.cbegin();
594 if (it != s.cend() && (*it ==
'-' || *it ==
'+')) {
596 if constexpr (std::is_signed_v<T>) {
606 if (it == s.cend()) {
612 auto constexpr min = std::numeric_limits<T>::min();
613 auto constexpr min10 = min / 10;
614 for (; it != s.cend(); ++it) {
616 if (c <
'0' || c >
'9') {
623 auto digit = -
static_cast<T
>(c -
'0');
624 if (min - v > digit) {
631 auto constexpr max = std::numeric_limits<T>::max();
632 auto constexpr max10 = max / 10;
633 for (; it != s.cend(); ++it) {
635 if (c <
'0' || c >
'9') {
642 auto digit =
static_cast<T
>(c -
'0');
643 if (max - v < digit) {
657 if (!to_integral_impl<T>(s, out)) {
664T
to_integral(std::wstring_view
const& s, T
const errorval = T()) {
666 if (!to_integral_impl<T>(s, out)) {
672template<
typename T,
typename StringType>
673T
to_integral(std::basic_string_view<StringType>
const& s, T
const errorval = T()) {
675 if (!to_integral_impl<T>(s, out)) {
684 std::optional<T> ret;
686 if (to_integral_impl<T>(s, out)) {
694 std::optional<T> ret;
696 if (to_integral_impl<T>(s, out)) {
702template<
typename T,
typename StringType>
703std::optional<T>
to_integral_o(std::basic_string_view<StringType>
const& s) {
704 std::optional<T> ret;
706 if (to_integral_impl<T>(s, out)) {
714template<
typename String>
716 for (
auto const& c : s) {
717 if (
static_cast<std::make_unsigned_t<typename String::value_type>
>(c) > 127) {
726template<
typename String,
typename Chars>
727void trim_impl(String & s, Chars
const& chars,
bool fromLeft,
bool fromRight) {
728 size_t const first = fromLeft ? s.find_first_not_of(chars) : 0;
729 if (first == String::npos) {
734 size_t const last = fromRight ? s.find_last_not_of(chars) : s.size();
735 if (last == String::npos) {
741 s = s.substr(first, last - first + 1);
745inline std::string FZ_PUBLIC_SYMBOL
trimmed(std::string_view s, std::string_view
const& chars =
" \r\n\t",
bool fromLeft =
true,
bool fromRight =
true)
747 trim_impl(s, chars, fromLeft, fromRight);
748 return std::string(s);
751inline 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)
753 trim_impl(s, chars, fromLeft, fromRight);
754 return std::wstring(s);
757inline std::string FZ_PUBLIC_SYMBOL ltrimmed(std::string_view s, std::string_view
const& chars =
" \r\n\t")
759 trim_impl(s, chars,
true,
false);
760 return std::string(s);
763inline std::wstring FZ_PUBLIC_SYMBOL ltrimmed(std::wstring_view s, std::wstring_view
const& chars = L
" \r\n\t")
765 trim_impl(s, chars,
true,
false);
766 return std::wstring(s);
769inline std::string FZ_PUBLIC_SYMBOL rtrimmed(std::string_view s, std::string_view
const& chars =
" \r\n\t")
771 trim_impl(s, chars,
false,
true);
772 return std::string(s);
775inline std::wstring FZ_PUBLIC_SYMBOL rtrimmed(std::wstring_view s, std::wstring_view
const& chars = L
" \r\n\t")
777 trim_impl(s, chars,
false,
true);
778 return std::wstring(s);
783template<
typename String,
typename std::enable_if_t<std::is_same_v<
typename String::value_type,
char>,
int> = 0>
784inline void trim(String & s, std::string_view
const& chars =
" \r\n\t",
bool fromLeft =
true,
bool fromRight =
true)
786 trim_impl(s, chars, fromLeft, fromRight);
789template<
typename String,
typename std::enable_if_t<std::is_same_v<
typename String::value_type,
wchar_t>,
int> = 0>
790inline void trim(String & s, std::wstring_view
const& chars = L
" \r\n\t",
bool fromLeft =
true,
bool fromRight =
true)
792 trim_impl(s, chars, fromLeft, fromRight);
795template<
typename String,
typename std::enable_if_t<std::is_same_v<
typename String::value_type,
char>,
int> = 0>
796inline void ltrim(String& s, std::string_view
const& chars =
" \r\n\t")
798 trim_impl(s, chars,
true,
false);
801template<
typename String,
typename std::enable_if_t<std::is_same_v<
typename String::value_type,
wchar_t>,
int> = 0>
802inline void ltrim(String& s, std::wstring_view
const& chars = L
" \r\n\t")
804 trim_impl(s, chars,
true,
false);
807template<
typename String,
typename std::enable_if_t<std::is_same_v<
typename String::value_type,
char>,
int> = 0>
808inline void rtrim(String& s, std::string_view
const& chars =
" \r\n\t")
810 trim_impl(s, chars,
false,
true);
813template<
typename String,
typename std::enable_if_t<std::is_same_v<
typename String::value_type,
wchar_t>,
int> = 0>
814inline void rtrim(String & s, std::wstring_view
const& chars = L
" \r\n\t")
816 trim_impl(s, chars,
false,
true);
823template<
bool insensitive_ascii = false,
typename String,
typename Beginning>
824 std::enable_if_t<std::is_same_v<string_value_type_t<String>, string_value_type_t<Beginning>>,
827 std::basic_string_view<string_value_type_t<String>> sv(s);
828 std::basic_string_view<string_value_type_t<Beginning>> beginningv(beginning);
830 if (beginningv.size() > sv.size()) {
834 if constexpr (insensitive_ascii) {
835 return std::equal(beginningv.begin(), beginningv.end(), sv.begin(), [](
auto const& a,
auto const& b) {
836 return tolower_ascii(a) == tolower_ascii(b);
839 return std::equal(beginningv.begin(), beginningv.end(), sv.begin());
847template<
bool insensitive_ascii = false,
typename String,
typename Ending>
848 std::enable_if_t<std::is_same_v<string_value_type_t<String>, string_value_type_t<Ending>>,
851 std::basic_string_view<string_value_type_t<String>> sv(s);
852 std::basic_string_view<string_value_type_t<Ending>> endingv(ending);
854 if (endingv.size() > sv.size()) {
858 if constexpr (insensitive_ascii) {
859 return std::equal(endingv.rbegin(), endingv.rend(), sv.rbegin(), [](
auto const& a,
auto const& b) {
860 return tolower_ascii(a) == tolower_ascii(b);
864 return std::equal(endingv.rbegin(), endingv.rend(), sv.rbegin());
933inline native_string to_native_from_utf8(std::string_view s) {
941FZ_PUBLIC_SYMBOL
void wipe_conversion_cache();
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:406
constexpr strtokenizer(String &&string, Delims &&delims, bool ignore_empty)
strtokenizer class constructor.
Definition string.hpp:416
Sets some global macros and further includes string.hpp.
The namespace used by libfilezilla.
Definition apply.hpp:17
size_t strlen(Char const *str)
Returns length of 0-terminated character sequence. Works with both narrow and wide-characters.
Definition string.hpp:284
Char toupper_ascii(Char c)
Converts ASCII lowercase characters to uppercase as if C-locale is used.
Definition string.hpp:134
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.
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::enable_if_t< std::is_same_v< string_value_type_t< String >, string_value_type_t< Beginning > >, bool > starts_with(String const &s, Beginning const &beginning)
Tests whether the first string starts with the second string.
Definition string.hpp:825
Char tolower_ascii(Char c)
Converts ASCII uppercase characters to lowercase as if C-locale is used.
Definition string.hpp:122
bool str_is_ascii(String const &s)
Returns true iff the string only has characters in the 7-bit ASCII range.
Definition string.hpp:715
strtokenizer(String &&string, Delims &&delims, bool ignore_empty) -> strtokenizer< String, Delims >
strtokenizer class construction-guide.
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:307
constexpr Char const * choose_string(char const *c, wchar_t const *w)
Returns the function argument of the type matching the template argument.
bool equal_insensitive_ascii(A const &a, B const &b)
Locale-insensitive stricmp.
Definition string.hpp:211
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:784
bool is_valid_utf8(std::string_view s)
Verifies that the input data is valid UTF-8.
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:745
std::wstring to_wstring_from_utf8(std::string_view const &in)
Converts from std::string in UTF-8 into std::wstring.
std::string normalize_hyphens(std::string_view const &in)
std::wstring native_string
A string in the system's native character type and encoding. Note: This typedef changes depending on...
Definition string.hpp:69
std::enable_if_t< std::is_same_v< string_value_type_t< String >, string_value_type_t< Ending > >, bool > ends_with(String const &s, Ending const &ending)
Tests whether the first string ends with the second string.
Definition string.hpp:849
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.
std::string to_utf8(std::string_view const &in)
Converts from std::string in native encoding into std::string in UTF-8.
std::vector< std::string > strtok(std::string_view const &tokens, std::string_view const &delims, bool const ignore_empty=true)
Tokenizes string.
std::string to_string(std::wstring_view const &in)
Converts from std::wstring into std::string in system encoding.
std::wstring to_wstring(std::string_view const &in)
Converts from std::string in system encoding into std::wstring.
std::optional< T > to_integral_o(std::string_view const &s)
Converts string to integral type T. If string is not convertible, nullopt.
Definition string.hpp:683
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.
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.
int stricmp(std::string_view const &a, std::string_view const &b)
Locale-sensitive stricmp.
std::string str_tolower_ascii(std::string_view const &s)
tr_tolower_ascii does for strings what tolower_ascii does for individual characters
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.
native_string to_native(std::string_view const &in)
Converts std::string to native_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:655
Comparator to be used for std::map for case-insensitive keys.
Definition string.hpp:188
A type trait to identify the value_type of any string-like type.
Definition string.hpp:156
Definition string.hpp:431
Definition string.hpp:428