mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-20 10:57:45 +08:00
Merge pull request #2168 from MaaAssistantArknights/feat/string_split_view
feat: 删除 `asst::utils::string_split_view`, 使用 `asst::views::split`
This commit is contained in:
@@ -26,7 +26,10 @@ namespace asst::http
|
||||
bool _analyze_status_line(std::string_view status_line)
|
||||
{
|
||||
size_t _word_count = 0;
|
||||
for (const auto& word : utils::string_split(status_line, " ")) {
|
||||
for (std::string_view word :
|
||||
views::split(status_line, ' ') | views::transform([&](const auto& rng) -> std::string_view {
|
||||
return utils::make_string_view(rng);
|
||||
})) {
|
||||
++_word_count;
|
||||
if (_word_count == 1) {
|
||||
if (!_accepted_protocol_version.contains(word)) {
|
||||
@@ -78,10 +81,14 @@ namespace asst::http
|
||||
requires std::is_constructible_v<std::string, Args...>
|
||||
Response(Args&&... args) : m_raw_data(std::forward<Args>(args)...)
|
||||
{
|
||||
constexpr std::string_view delim = "\r\n";
|
||||
std::string_view this_view = m_raw_data;
|
||||
bool _is_status_line = true;
|
||||
bool _is_data_line = false;
|
||||
for (const auto& line : utils::string_split(this_view, "\r\n")) {
|
||||
for (std::string_view line :
|
||||
views::split(this_view, delim) | views::transform([&](const auto& rng) -> std::string_view {
|
||||
return utils::make_string_view(rng);
|
||||
})) {
|
||||
// status
|
||||
if (_is_status_line) {
|
||||
if (!_analyze_status_line(line)) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
@@ -25,6 +26,22 @@ namespace asst::utils
|
||||
template <typename char_t = char>
|
||||
using pair_of_string_view = std::pair<std::basic_string_view<char_t>, std::basic_string_view<char_t>>;
|
||||
|
||||
#ifdef ASST_USE_RANGES_RANGE_V3
|
||||
// workaround for P2210R2
|
||||
template <ranges::forward_range Rng>
|
||||
requires(requires(Rng rng) { std::basic_string_view(std::addressof(*rng.begin()), ranges::distance(rng)); })
|
||||
inline auto make_string_view(Rng rng)
|
||||
{
|
||||
return std::basic_string_view(std::addressof(*rng.begin()), ranges::distance(rng));
|
||||
}
|
||||
#else
|
||||
template <ranges::contiguous_range Rng>
|
||||
inline auto make_string_view(Rng rng)
|
||||
{
|
||||
return std::basic_string_view(rng.begin(), rng.end());
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename char_t>
|
||||
inline void _string_replace_all(std::basic_string<char_t>& str, std::basic_string_view<char_t> old_value,
|
||||
std::basic_string_view<char_t> new_value)
|
||||
@@ -95,175 +112,6 @@ namespace asst::utils
|
||||
return str;
|
||||
}
|
||||
|
||||
// 延迟求值的 string_split,分隔符可以为字符或字符串
|
||||
template <typename char_t>
|
||||
class string_split_view : public ranges::view_interface<string_split_view<char_t>>
|
||||
{
|
||||
private:
|
||||
using base_string_view = std::basic_string_view<char_t>;
|
||||
using base_string = std::basic_string<char_t>;
|
||||
using string_iter = typename base_string_view::const_iterator;
|
||||
base_string_view _rng {};
|
||||
base_string_view _pat {};
|
||||
base_string_view _nxt {};
|
||||
|
||||
class _iterator
|
||||
{
|
||||
private:
|
||||
string_split_view* _pre = nullptr;
|
||||
string_iter _cur = {};
|
||||
base_string_view _nxt = {};
|
||||
bool _trailing_empty = false;
|
||||
|
||||
public:
|
||||
using iterator_concept = std::forward_iterator_tag;
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using value_type = base_string_view;
|
||||
using difference_type = typename base_string_view::difference_type;
|
||||
|
||||
_iterator() = default;
|
||||
|
||||
constexpr _iterator(string_split_view& prev, string_iter curr, base_string_view next) noexcept
|
||||
: _pre(std::addressof(prev)), _cur(curr), _nxt(next)
|
||||
{}
|
||||
|
||||
[[nodiscard]] constexpr string_iter base() const noexcept { return _cur; }
|
||||
|
||||
[[nodiscard]] constexpr value_type operator*() const noexcept { return { _cur, _nxt.cbegin() }; }
|
||||
|
||||
constexpr _iterator& operator++()
|
||||
{
|
||||
auto _end = _pre->_rng.cend();
|
||||
|
||||
if (_cur = _nxt.cbegin(); _cur == _end) {
|
||||
_trailing_empty = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (_cur = _nxt.cend(); _cur == _end) {
|
||||
_trailing_empty = true;
|
||||
_nxt = { _cur, _cur };
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (size_t _len = _pre->_pat.length(); !_len) {
|
||||
auto _beg = _cur + 1;
|
||||
_nxt = { _beg, _beg };
|
||||
}
|
||||
else if (const auto _pos = base_string_view(_cur, _end).find(_pre->_pat);
|
||||
_pos == base_string_view::npos) {
|
||||
_nxt = { _end, _end };
|
||||
}
|
||||
else {
|
||||
auto _beg = _cur + _pos;
|
||||
_nxt = { _beg, _beg + _pre->_pat.length() };
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr _iterator operator++(int)
|
||||
{
|
||||
auto _tmp = *this;
|
||||
++*this;
|
||||
return _tmp;
|
||||
}
|
||||
|
||||
friend constexpr bool operator==(const _iterator& _lhs, const _iterator& _rhs) noexcept
|
||||
{
|
||||
return _lhs._cur == _rhs._cur && _lhs._trailing_empty == _rhs._trailing_empty;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
string_split_view() = default;
|
||||
|
||||
template <typename rng_t, typename pat_t>
|
||||
requires std::convertible_to<pat_t, base_string_view>
|
||||
constexpr string_split_view(rng_t&& rang, pat_t&& patt) noexcept
|
||||
: _rng(std::forward<rng_t>(rang)), _pat(std::forward<pat_t>(patt))
|
||||
{}
|
||||
|
||||
template <typename rng_t>
|
||||
constexpr string_split_view(rng_t&&, char_t&&)
|
||||
{
|
||||
// 摆烂辣!解决不了临时变量导致 _pat 悬垂的问题
|
||||
ASST_STATIC_ASSERT_FALSE("please use `views::split` instead ^_^", rng_t);
|
||||
}
|
||||
|
||||
template <typename rng_t>
|
||||
constexpr string_split_view(rng_t&& rang, const char_t& elem) noexcept
|
||||
: _rng(std::forward<rng_t>(rang)), _pat(&elem, 1)
|
||||
{}
|
||||
|
||||
[[nodiscard]] constexpr const base_string_view& base() const noexcept { return _rng; }
|
||||
|
||||
[[nodiscard]] constexpr auto begin()
|
||||
{
|
||||
const auto _beg = _rng.cbegin(), _end = _rng.cend();
|
||||
|
||||
if (_nxt.empty()) {
|
||||
if (size_t _len = _pat.length(); !_len) {
|
||||
auto _cur = _beg + 1;
|
||||
_nxt = { _cur, _cur };
|
||||
}
|
||||
else if (const auto _pos = _rng.find(_pat); _pos == base_string_view::npos) {
|
||||
_nxt = { _end, _end };
|
||||
}
|
||||
else {
|
||||
auto _cur = _beg + _pos;
|
||||
_nxt = { _cur, _cur + _pat.length() };
|
||||
}
|
||||
}
|
||||
return _iterator { *this, _beg, _nxt };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto end() { return _iterator { *this, _rng.cend(), {} }; }
|
||||
};
|
||||
|
||||
template <ranges::range str_t, class pat_t>
|
||||
string_split_view(str_t, pat_t) -> string_split_view<typename str_t::value_type>;
|
||||
|
||||
template <class str_t, class pat_t>
|
||||
string_split_view(str_t*, pat_t) -> string_split_view<typename std::remove_cv<str_t>::type>;
|
||||
|
||||
struct _string_split_fn
|
||||
{
|
||||
template <ranges::range str_t, class pat_t>
|
||||
[[nodiscard]] constexpr auto operator()(str_t&& _str, pat_t&& _pat) const
|
||||
noexcept(noexcept(string_split_view(std::forward<str_t>(_str), std::forward<pat_t>(_pat))))
|
||||
requires requires { string_split_view(static_cast<str_t&&>(_str), static_cast<pat_t&&>(_pat)); }
|
||||
{
|
||||
return string_split_view(std::forward<str_t>(_str), std::forward<pat_t>(_pat));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr _string_split_fn string_split;
|
||||
|
||||
// // 以低内存开销拆分一个字符串;注意当 src 析构后,返回值将失效
|
||||
// template <typename str_t, typename char_t = typename str_t::value_type, typename delimiter_t>
|
||||
// requires std::convertible_to<str_t, std::basic_string_view<char_t>> &&
|
||||
// std::convertible_to<delimiter_t, std::basic_string_view<char_t>>
|
||||
// inline std::vector<std::basic_string_view<char_t>> string_split(const str_t& src, delimiter_t delimiter,
|
||||
// size_t split_count = -1)
|
||||
// {
|
||||
// std::basic_string_view<char_t> delimiter_view = delimiter;
|
||||
// std::basic_string_view<char_t> str = src;
|
||||
// typename std::basic_string<char_t>::size_type pos1 = 0;
|
||||
// typename std::basic_string<char_t>::size_type pos2 = str.find(delimiter_view);
|
||||
// std::vector<std::basic_string_view<char_t>> result;
|
||||
|
||||
// while (split_count-- && pos2 != str.npos) {
|
||||
// result.emplace_back(str.substr(pos1, pos2 - pos1));
|
||||
|
||||
// pos1 = pos2 + delimiter_view.length();
|
||||
// pos2 = str.find(delimiter_view, pos1);
|
||||
// }
|
||||
// if (pos1 != str.length()) result.emplace_back(str.substr(pos1));
|
||||
|
||||
// return result;
|
||||
// }
|
||||
|
||||
inline std::string get_format_time()
|
||||
{
|
||||
char buff[128] = { 0 };
|
||||
@@ -437,18 +285,3 @@ namespace asst::utils
|
||||
}
|
||||
}
|
||||
} // namespace asst::utils
|
||||
|
||||
#if defined(ASST_USE_RANGES_RANGE_V3) || defined(ASST_USE_RANGES_STL)
|
||||
#ifdef ASST_USE_RANGES_RANGE_V3
|
||||
namespace ranges
|
||||
#else // ASST_USE_RANGES_STL
|
||||
namespace std::ranges
|
||||
#endif
|
||||
{
|
||||
template <typename R>
|
||||
inline constexpr bool enable_view<asst::utils::string_split_view<R>> = enable_view<std::basic_string_view<R>>;
|
||||
template <typename R>
|
||||
inline constexpr bool enable_borrowed_range<asst::utils::string_split_view<R>> =
|
||||
enable_borrowed_range<std::basic_string_view<R>>;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -628,8 +628,15 @@ bool update_battle_chars_info(const std::filesystem::path& input_dir, const std:
|
||||
|
||||
bool update_recruitment_data(const std::filesystem::path& input_dir, const std::filesystem::path& output, bool is_base)
|
||||
{
|
||||
using namespace asst::utils;
|
||||
using asst::ranges::find_if, asst::views::filter;
|
||||
using asst::ranges::find_if, asst::ranges::range;
|
||||
using asst::views::filter, asst::views::split, asst::views::transform, asst::views::drop_while;
|
||||
using asst::utils::_string_replace_all;
|
||||
|
||||
auto not_empty = []<range Rng>(Rng str) -> bool { return !str.empty(); };
|
||||
auto make_string_view = []<range Rng>(Rng str) -> std::string_view {
|
||||
return asst::utils::make_string_view(str);
|
||||
};
|
||||
|
||||
const auto& recruitment_file = input_dir / "gacha_table.json";
|
||||
const auto& operators_file = input_dir / "character_table.json";
|
||||
|
||||
@@ -645,28 +652,19 @@ bool update_recruitment_data(const std::filesystem::path& input_dir, const std::
|
||||
std::string recruitment_details = recruitment_opt->at("recruitDetail").as_string();
|
||||
remove_xml(recruitment_details);
|
||||
_string_replace_all(recruitment_details, "\\n", "");
|
||||
auto splited = string_split(recruitment_details, "★");
|
||||
bool is_useless = true;
|
||||
auto not_empty = [](std::string_view str) -> bool { return !str.empty(); };
|
||||
for (auto s : splited | filter(not_empty)) {
|
||||
if (s.find("Lancet-2") != std::string_view::npos) {
|
||||
is_useless = false;
|
||||
}
|
||||
if (is_useless) {
|
||||
continue;
|
||||
}
|
||||
#if 0
|
||||
std::string_view s1 = (string_split(s, "\n") | filter(not_empty)).front();
|
||||
#else
|
||||
std::string_view s1;
|
||||
if (auto s_splited = string_split(s, "\n") | filter(not_empty); !s_splited.empty()) {
|
||||
s1 = s_splited.front();
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
for (auto n : string_split(s1, "/") | filter(not_empty)) {
|
||||
constexpr std::string_view star_delim = "★";
|
||||
|
||||
auto items =
|
||||
// 按照 ★ 分割
|
||||
recruitment_details | split(star_delim) | filter(not_empty) | transform(make_string_view) |
|
||||
// 忽略 Lancet-2 之前的东西
|
||||
drop_while([&](std::string_view str) { return str.find("Lancet-2") == std::string_view::npos; }) |
|
||||
// 按照 \n 分割,若非空则取第一个元素
|
||||
transform([&](auto str) { return str | split('\n') | filter(not_empty); }) | filter(not_empty) |
|
||||
transform([&](auto strs) { return make_string_view(strs.front()); });
|
||||
|
||||
for (std::string_view s : items) {
|
||||
for (std::string_view n : s | split('/') | filter(not_empty) | transform(make_string_view)) {
|
||||
std::string name(n);
|
||||
trim(name);
|
||||
chars_list.emplace_back(name);
|
||||
|
||||
Reference in New Issue
Block a user