diff --git a/src/MaaCore/Utils/StringMisc.hpp b/src/MaaCore/Utils/StringMisc.hpp index 4b0abc6f2f..422af3dda5 100644 --- a/src/MaaCore/Utils/StringMisc.hpp +++ b/src/MaaCore/Utils/StringMisc.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -29,8 +30,7 @@ namespace asst::utils template > concept IsSomeKindOfString = std::same_as || std::same_as; - template - requires IsSomeKindOfString + template inline constexpr void string_replace_all_in_place(StringT& str, detail::sv_type from, detail::sv_type to) { @@ -40,15 +40,13 @@ namespace asst::utils } } - template - requires IsSomeKindOfString + template inline constexpr void string_replace_all_in_place(StringT& str, const detail::sv_pair& replace_pair) { string_replace_all_in_place(str, replace_pair.first, replace_pair.second); } - template - requires IsSomeKindOfString + template inline constexpr void string_replace_all_in_place(StringT& str, std::initializer_list> replace_pairs) { @@ -61,7 +59,7 @@ namespace asst::utils // workaround for P2210R2 template requires(requires(Rng rng) { std::basic_string_view(std::addressof(*rng.begin()), ranges::distance(rng)); }) - inline auto make_string_view(Rng rng) + inline auto make_string_view(Rng&& rng) { return std::basic_string_view(std::addressof(*rng.begin()), ranges::distance(rng)); } @@ -73,8 +71,7 @@ namespace asst::utils return std::basic_string_view(std::addressof(*beg), std::distance(beg, end)); } #else - template - inline auto make_string_view(Rng rng) + inline auto make_string_view(ranges::contiguous_range auto&& rng) { return std::basic_string_view(rng.begin(), rng.end()); } @@ -87,8 +84,7 @@ namespace asst::utils } #endif - template - requires IsSomeKindOfString + template [[nodiscard]] inline constexpr auto string_replace_all(StringT&& src, detail::sv_type from, detail::sv_type to) { @@ -97,8 +93,7 @@ namespace asst::utils return result; } - template - requires IsSomeKindOfString + template [[nodiscard]] inline constexpr auto string_replace_all(StringT&& src, const detail::sv_pair& replace_pair) { std::decay_t result = std::forward(src); @@ -106,8 +101,7 @@ namespace asst::utils return result; } - template - requires IsSomeKindOfString + template [[nodiscard]] inline constexpr auto string_replace_all( StringT&& str, std::initializer_list> replace_pairs) { @@ -118,26 +112,41 @@ namespace asst::utils return result; } - template , + template , typename Pred = decltype([](CharT c) -> bool { return c != ' '; })> - requires IsSomeKindOfString inline void string_trim(StringT& str, Pred not_space = Pred {}) { str.erase(ranges::find_if(str | views::reverse, not_space).base(), str.end()); str.erase(str.begin(), ranges::find_if(str, not_space)); } - template > - requires IsSomeKindOfString - inline void tolowers(StringT& str) + inline void tolowers(IsSomeKindOfString auto& str) { + using CharT = ranges::range_value_t; ranges::for_each(str, [](CharT& ch) -> void { ch = static_cast(std::tolower(ch)); }); } - template > - requires IsSomeKindOfString - inline void touppers(StringT& str) + inline void touppers(IsSomeKindOfString auto& str) { + using CharT = ranges::range_value_t; ranges::for_each(str, [](CharT& ch) -> void { ch = static_cast(std::toupper(ch)); }); } + + template + requires(std::is_arithmetic_v) + inline bool chars_to_number(std::string_view integer, NumberT& result) noexcept + { + const char* first = integer.data(); + const char* last = first + integer.size(); + auto&& [p, ec] = std::from_chars(first, last, result); + if (ec != std::errc {}) { + return false; + } + if constexpr (FullMatch) { + if (p != last) { + return false; + } + } + return true; + } } // namespace asst::utils