refactor: 减少string_view滥用

This commit is contained in:
MistEO
2025-12-31 22:13:53 +08:00
parent b5dff5a285
commit da0445ddbc
6 changed files with 80 additions and 78 deletions

View File

@@ -23,7 +23,7 @@ const std::unordered_set<std::string>& asst::TaskData::get_templ_required() cons
return m_templ_required;
}
asst::TaskDerivedConstPtr asst::TaskData::get_raw(std::string_view name)
asst::TaskDerivedConstPtr asst::TaskData::get_raw(const std::string& name)
{
if (!generate_raw_task_and_base(name, true)) [[unlikely]] {
return nullptr;
@@ -35,15 +35,16 @@ asst::TaskDerivedConstPtr asst::TaskData::get_raw(std::string_view name)
// `@` 前面的字符长度
size_t name_len = name.find('@');
if (name_len == std::string_view::npos) [[unlikely]] {
if (name_len == std::string::npos) [[unlikely]] {
return nullptr;
}
return nullptr;
}
asst::TaskPtr asst::TaskData::get(std::string_view name)
asst::TaskPtr asst::TaskData::get(std::string_view name_view)
{
std::string name(name_view);
// 生成过的任务
if (auto it = m_all_tasks_info.find(name); it != m_all_tasks_info.cend()) {
return it->second;
@@ -76,7 +77,7 @@ bool asst::TaskData::lazy_parse(const json::value& json)
}
for (const auto& [name, task_json] : json.as_object()) {
std::string_view name_view = task_name_view(name);
const std::string& name_view = task_name_view(name);
if (task_json.contains("baseTask")) {
// 直接声明 baseTask 的任务不继承同名任务参数而是直接覆盖
m_json_all_tasks_info[name_view] = task_json.as_object();
@@ -106,10 +107,10 @@ bool asst::TaskData::lazy_parse(const json::value& json)
{
LogTraceScope("syntax_check");
bool validity = true;
std::queue<std::string_view> task_queue;
std::unordered_set<std::string_view> checking_task_set;
std::queue<std::string> task_queue;
std::unordered_set<std::string> checking_task_set;
for (std::string_view name : m_json_all_tasks_info | std::views::keys) {
for (const std::string& name : m_json_all_tasks_info | std::views::keys) {
m_task_status[name] = ToBeGenerate;
task_queue.push(name);
checking_task_set.insert(name);
@@ -121,7 +122,7 @@ bool asst::TaskData::lazy_parse(const json::value& json)
const size_t MAX_CHECKING_SIZE = 10000;
while (!task_queue.empty() && checking_task_set.size() <= MAX_CHECKING_SIZE) {
std::string_view name = task_queue.front();
const std::string& name = task_queue.front();
task_queue.pop();
auto task = get(name);
if (task == nullptr) [[unlikely]] {
@@ -130,9 +131,9 @@ bool asst::TaskData::lazy_parse(const json::value& json)
continue;
}
auto check_tasklist =
[&](const TaskList& task_list, std::string_view list_type, bool enable_justreturn_check = false) {
std::unordered_set<std::string_view> tasks_set {};
std::string justreturn_task_name = "";
[&](const TaskList& task_list, const std::string& list_type, bool enable_justreturn_check = false) {
std::unordered_set<std::string> tasks_set {};
std::string justreturn_task_name;
for (const std::string& task_name : task_list) {
if (tasks_set.contains(task_name)) [[unlikely]] {
continue;
@@ -292,7 +293,7 @@ bool asst::TaskData::parse(const json::value& json)
}
// 本来重构之后完全支持惰性加载,但是发现模板图片不支持(
for (std::string_view name : m_json_all_tasks_info | std::views::keys) {
for (const std::string& name : m_json_all_tasks_info | std::views::keys) {
generate_task_info(name);
}
@@ -305,25 +306,26 @@ void asst::TaskData::clear_tasks()
// 即运行期修改对已经获取的任务指针无效,但是不会导致崩溃;要想更新,需要重新获取任务指针
m_all_tasks_info.clear();
m_raw_all_tasks_info.clear();
for (std::string_view name : m_json_all_tasks_info | std::views::keys) {
for (const std::string& name : m_json_all_tasks_info | std::views::keys) {
m_task_status[task_name_view(name)] = ToBeGenerate;
}
}
void asst::TaskData::set_task_base(const std::string_view task_name, std::string base_task_name)
void asst::TaskData::set_task_base(const std::string& task_name, std::string base_task_name)
{
m_json_all_tasks_info[task_name_view(task_name)]["baseTask"] = std::move(base_task_name);
clear_tasks();
}
bool asst::TaskData::generate_raw_task_info(
std::string_view name,
std::string_view prefix,
std::string_view base,
const std::string& name,
const std::string& raw_prefix,
const std::string& base,
const json::value& json,
TaskDerivedType type)
{
TaskPipelineConstPtr base_task = base.empty() ? nullptr : get_raw(base);
std::string prefix = raw_prefix;
if (base_task == nullptr) {
base_task = default_task_info_ptr;
prefix = "";
@@ -359,7 +361,7 @@ bool asst::TaskData::generate_raw_task_info(
// name: 待生成的任务名
// must_true: 必须有名字为 name 的资源
// allow_implicit: 允许隐式生成(解决 A@B@LoadingText 时 B 不存在的问题)
bool asst::TaskData::generate_raw_task_and_base(std::string_view name, bool must_true, bool allow_implicit)
bool asst::TaskData::generate_raw_task_and_base(const std::string& name, bool must_true, bool allow_implicit)
{
switch (m_task_status[task_name_view(name)]) {
case NotToBeGenerate:
@@ -409,7 +411,7 @@ bool asst::TaskData::generate_raw_task_and_base(std::string_view name, bool must
// TemplateTask
for (size_t p = name.find('@'); p != std::string::npos; p = name.find('@', p + 1)) {
if (std::string_view base = name.substr(p + 1); generate_raw_task_and_base(base, false, false)) {
if (const std::string& base = name.substr(p + 1); generate_raw_task_and_base(base, false, false)) {
return generate_raw_task_info(name, name.substr(0, p), base, task_json, TaskDerivedType::Template);
}
}
@@ -425,7 +427,7 @@ bool asst::TaskData::generate_raw_task_and_base(std::string_view name, bool must
}
}
asst::TaskPtr asst::TaskData::generate_task_info(std::string_view name)
asst::TaskPtr asst::TaskData::generate_task_info(const std::string& name)
{
auto raw = get_raw(name);
if (!raw) [[unlikely]] {
@@ -554,7 +556,7 @@ asst::TaskPtr asst::TaskData::generate_task_info(std::string_view name)
}
asst::TaskPtr asst::TaskData::generate_match_task_info(
std::string_view name,
const std::string& name,
const json::value& task_json,
MatchTaskConstPtr default_ptr,
TaskDerivedType derived_type)
@@ -761,7 +763,7 @@ asst::TaskPtr asst::TaskData::generate_match_task_info(
}
asst::TaskPtr asst::TaskData::generate_ocr_task_info(
std::string_view name,
const std::string& name,
const json::value& task_json,
OcrTaskConstPtr default_ptr)
{
@@ -809,7 +811,7 @@ asst::TaskPtr asst::TaskData::generate_ocr_task_info(
}
asst::TaskPtr asst::TaskData::generate_feature_match_task_info(
std::string_view name,
const std::string& name,
const json::value& task_json,
FeatureMatchTaskConstPtr default_ptr,
TaskDerivedType derived_type)
@@ -845,14 +847,14 @@ asst::TaskPtr asst::TaskData::generate_feature_match_task_info(
asst::ResultOrError<asst::TaskData::RawCompileResult> asst::TaskData::compile_raw_tasklist(
const TaskList& raw_tasks,
std::string_view self_name,
std::function<TaskDerivedConstPtr(std::string_view)> get_raw,
const std::string& self_name,
std::function<TaskDerivedConstPtr(const std::string&)> get_raw,
bool allow_duplicate)
{
RawCompileResult ret { .task_changed = false, .symbols = {} };
std::unordered_set<std::string_view> tasks_set; // 记录任务列表中已有的任务(内容元素与 new_tasks 基本一致)
std::unordered_set<std::string> tasks_set; // 记录任务列表中已有的任务(内容元素与 new_tasks 基本一致)
for (std::string_view task_expr : raw_tasks) {
for (const std::string& task_expr : raw_tasks) {
if (task_expr.empty() || (!allow_duplicate && tasks_set.contains(task_expr))) {
ret.task_changed = true;
continue;
@@ -902,14 +904,14 @@ asst::ResultOrError<asst::TaskData::RawCompileResult> asst::TaskData::compile_ra
}
asst::ResultOrError<asst::TaskData::CompileResult>
asst::TaskData::compile_tasklist(const TaskList& raw_tasks, std::string_view self_name, bool allow_duplicate)
asst::TaskData::compile_tasklist(const TaskList& raw_tasks, const std::string& self_name, bool allow_duplicate)
{
CompileResult ret { .task_changed = false, .tasks = {} };
std::vector<TaskDataSymbol> new_symbols;
if (auto opt = compile_raw_tasklist(
raw_tasks,
self_name,
[&](std::string_view name) { return get_raw(name); },
[&](const std::string& name) { return get_raw(name); },
allow_duplicate);
!opt) {
return { std::nullopt, std::move(opt.error()) };
@@ -918,9 +920,9 @@ asst::ResultOrError<asst::TaskData::CompileResult>
new_symbols = std::move(opt.value().symbols);
ret.task_changed = opt.value().task_changed;
}
std::unordered_set<std::string_view> tasks_set;
std::unordered_set<std::string> tasks_set;
for (const auto& task : new_symbols) {
std::string_view task_name;
std::string task_name;
if (task == TaskDataSymbol::SharpSelf) {
task_name = self_name;
ret.task_changed = true;
@@ -948,10 +950,10 @@ asst::ResultOrError<asst::TaskData::CompileResult>
return ret;
}
std::string asst::TaskData::append_prefix(std::string_view task_name, std::string_view task_prefix)
std::string asst::TaskData::append_prefix(const std::string& task_name, std::string task_prefix)
{
if (task_prefix.ends_with('@')) [[unlikely]] {
task_prefix.remove_suffix(1);
task_prefix = task_prefix.substr(0, task_prefix.size() - 1);
}
if (task_prefix.empty()) [[unlikely]] {
return std::string(task_name);
@@ -965,22 +967,22 @@ std::string asst::TaskData::append_prefix(std::string_view task_name, std::strin
return std::string(task_prefix) + '@' + std::string(task_name);
}
asst::TaskList asst::TaskData::append_prefix(const TaskList& base_task_list, std::string_view task_prefix)
asst::TaskList asst::TaskData::append_prefix(const TaskList& base_task_list, std::string task_prefix)
{
if (task_prefix.ends_with('@')) [[unlikely]] {
task_prefix.remove_suffix(1);
task_prefix = task_prefix.substr(0, task_prefix.size() - 1);
}
if (task_prefix.empty()) {
return base_task_list;
}
TaskList task_list = {};
for (const std::string& base : base_task_list) {
std::string_view base_view = base;
const std::string& base_view = base;
size_t l = 0;
bool has_same_prefix = false;
// base 任务里已经存在相同前缀,则不加前缀
// https://github.com/MaaAssistantArknights/MaaAssistantArknights/pull/2116#issuecomment-1270115238
for (size_t r = base_view.find('@'); r != std::string_view::npos; r = base_view.find('@', l)) {
for (size_t r = base_view.find('@'); r != std::string::npos; r = base_view.find('@', l)) {
if (task_prefix == base_view.substr(l, r - l)) [[unlikely]] {
has_same_prefix = true;
break;
@@ -1048,7 +1050,7 @@ asst::TaskConstPtr asst::TaskData::_default_task_info()
#ifdef ASST_DEBUG
// 为了解决类似 beddc7c828126c678391e0b4da288db6d2c2d58a 导致的问题,加载的时候做一个语法检查
// 主要是处理是否包含未知键值的问题
bool asst::TaskData::syntax_check(std::string_view task_name, const json::value& task_json)
bool asst::TaskData::syntax_check(const std::string& task_name, const json::value& task_json)
{
// 以下按字典序排序
// clang-format off
@@ -1106,8 +1108,8 @@ bool asst::TaskData::syntax_check(std::string_view task_name, const json::value&
{ ProcessTaskAction::Input, { "inputText" } },
};
auto is_doc = [&](std::string_view key) {
return key.find("Doc") != std::string_view::npos || key.find("doc") != std::string_view::npos;
auto is_doc = [&](const std::string& key) {
return key.find("Doc") != std::string::npos || key.find("doc") != std::string::npos;
};
// 兜底策略,如果某个 key ("xxx") 不符合规范(可能是代码中使用到的参数,而不是任务流程)

View File

@@ -25,8 +25,8 @@ private:
_default_feature_match_task_info();
static inline const TaskConstPtr default_task_info_ptr = _default_task_info();
static std::string append_prefix(std::string_view task_name, std::string_view task_prefix);
static TaskList append_prefix(const TaskList& base_task_list, std::string_view task_prefix);
static std::string append_prefix(const std::string& task_name, std::string task_prefix);
static TaskList append_prefix(const TaskList& base_task_list, std::string task_prefix);
template <std::ranges::forward_range ListType>
requires(
@@ -44,7 +44,7 @@ private:
static inline std::unordered_set<std::string> m_task_names {};
static const std::string& task_name_view(std::string_view name) { return *m_task_names.emplace(name).first; }
static const std::string& task_name_view(const std::string& name) { return *m_task_names.emplace(name).first; }
struct RawCompileResult
{
@@ -54,30 +54,30 @@ private:
static ResultOrError<RawCompileResult> compile_raw_tasklist(
const TaskList& raw_tasks,
std::string_view self_name,
std::function<TaskDerivedConstPtr(std::string_view)> get_raw,
const std::string& self_name,
std::function<TaskDerivedConstPtr(const std::string&)> get_raw,
bool allow_duplicate);
private:
TaskPtr generate_task_info(std::string_view name);
TaskPtr generate_task_info(const std::string& name);
TaskPtr generate_match_task_info(
std::string_view name,
const std::string& name,
const json::value&,
MatchTaskConstPtr default_ptr,
TaskDerivedType derived_type);
TaskPtr generate_ocr_task_info(std::string_view name, const json::value&, OcrTaskConstPtr default_ptr);
TaskPtr generate_ocr_task_info(const std::string& name, const json::value&, OcrTaskConstPtr default_ptr);
TaskPtr generate_feature_match_task_info(
std::string_view name,
const std::string& name,
const json::value& task_json,
FeatureMatchTaskConstPtr default_ptr,
TaskDerivedType derived_type);
decltype(auto) insert_or_assign_raw_task(std::string_view task_name, TaskDerivedPtr task_info_ptr)
decltype(auto) insert_or_assign_raw_task(const std::string& task_name, TaskDerivedPtr task_info_ptr)
{
return m_raw_all_tasks_info.insert_or_assign(task_name_view(task_name), task_info_ptr);
}
decltype(auto) insert_or_assign_task(std::string_view task_name, TaskPtr task_info_ptr)
decltype(auto) insert_or_assign_task(const std::string& task_name, TaskPtr task_info_ptr)
{
return m_all_tasks_info.insert_or_assign(task_name_view(task_name), task_info_ptr);
}
@@ -89,25 +89,25 @@ private:
};
ResultOrError<CompileResult>
compile_tasklist(const TaskList& raw_tasks, std::string_view self_name, bool allow_duplicate);
compile_tasklist(const TaskList& raw_tasks, const std::string& self_name, bool allow_duplicate);
bool generate_raw_task_info(
std::string_view name,
std::string_view prefix,
std::string_view base_name,
const std::string& name,
const std::string& raw_prefix,
const std::string& base_name,
const json::value& task_json,
TaskDerivedType type);
bool generate_raw_task_and_base(std::string_view name, bool must_true, bool allow_implicit = true);
bool generate_raw_task_and_base(const std::string& name, bool must_true, bool allow_implicit = true);
#ifdef ASST_DEBUG
bool syntax_check(std::string_view task_name, const json::value& task_json);
bool syntax_check(const std::string& task_name, const json::value& task_json);
#endif
TaskDerivedConstPtr get_raw(std::string_view name);
TaskDerivedConstPtr get_raw(const std::string& name);
public:
virtual ~TaskData() override = default;
bool load(const std::filesystem::path& path) override;
virtual const std::unordered_set<std::string>& get_templ_required() const noexcept override;
void clear_tasks();
void set_task_base(const std::string_view task_name, std::string base_task_name);
void set_task_base(const std::string& task_name, std::string base_task_name);
bool lazy_parse(const json::value& json);
TaskPtr get(std::string_view name);
@@ -125,7 +125,7 @@ public:
// json[name][x] = y;
// Task.lazy_parse(json);
// ```
return std::dynamic_pointer_cast<TargetTaskInfoType>(get(name));
return std::dynamic_pointer_cast<TargetTaskInfoType>(get(std::string(name)));
}
protected:
@@ -140,10 +140,10 @@ protected:
virtual bool parse(const json::value& json) override;
std::unordered_set<std::string> m_templ_required;
std::unordered_map<std::string_view, TaskStatus> m_task_status;
std::unordered_map<std::string_view, json::object> m_json_all_tasks_info; // 原始的 json 信息
std::unordered_map<std::string_view, TaskDerivedPtr> m_raw_all_tasks_info; // 未展开虚任务的任务信息
std::unordered_map<std::string_view, TaskPtr> m_all_tasks_info; // 已展开虚任务的任务信息
std::unordered_map<std::string, TaskStatus> m_task_status;
std::unordered_map<std::string, json::object> m_json_all_tasks_info; // 原始的 json 信息
std::unordered_map<std::string, TaskDerivedPtr> m_raw_all_tasks_info; // 未展开虚任务的任务信息
std::unordered_map<std::string, TaskPtr> m_all_tasks_info; // 已展开虚任务的任务信息
};
inline static auto& Task = TaskData::get_instance();

View File

@@ -3,12 +3,12 @@
asst::TaskDataSymbol::SymbolsOrError asst::TaskDataSymbol::append_prefix(
const TaskDataSymbol& symbol,
const TaskDataSymbol& prefix,
std::string_view self_name,
std::function<TaskDerivedConstPtr(std::string_view)> get_raw,
const std::string& self_name,
std::function<TaskDerivedConstPtr(const std::string&)> get_raw,
std::function<SymbolsOrError(const TaskList&)> compile_tasklist)
{
// 注意A@#self 是 A 而不是 A@self_name, #self@A 是 self_name@A 而不是 A
std::string_view prefix_name;
std::string prefix_name;
if (prefix == SharpSelf) {
prefix_name = self_name;
}

View File

@@ -41,7 +41,7 @@ public:
Name,
};
static const inline std::unordered_map<std::string_view, Type> symbol_repr_to_type = {
static const inline std::unordered_map<std::string, Type> symbol_repr_to_type = {
{ "__END__", End },
{ ",", LambdaTaskSep },
{ "(", LParen },
@@ -92,7 +92,7 @@ public:
public:
bool operator==(Type other) const noexcept { return m_symbol == other; }
bool operator==(std::string_view other) const noexcept { return m_symbol == Name && m_name == other; }
bool operator==(const std::string& other) const noexcept { return m_symbol == Name && m_name == other; }
bool operator==(const TaskDataSymbol& other) const noexcept
{
@@ -127,7 +127,7 @@ public:
return pos == symbol_type_to_repr.end() ? symbol_type_to_repr.at(Name) : pos->second;
}
static Type type(std::string_view repr)
static Type type(const std::string& repr)
{
const auto pos = symbol_repr_to_type.find(repr);
return pos == symbol_repr_to_type.end() ? Name : pos->second;
@@ -136,8 +136,8 @@ public:
static SymbolsOrError append_prefix(
const TaskDataSymbol& symbol,
const TaskDataSymbol& prefix,
std::string_view self_name,
std::function<TaskDerivedConstPtr(std::string_view)> get_raw,
const std::string& self_name,
std::function<TaskDerivedConstPtr(const std::string&)> get_raw,
std::function<SymbolsOrError(const TaskList&)> compile_tasklist);
bool is_name() const noexcept { return m_symbol == Name; }

View File

@@ -1,11 +1,11 @@
#include "TaskDataSymbolStream.h"
asst::ResultOrError<bool> asst::TaskDataSymbolStream::parse(std::string_view task_expr)
asst::ResultOrError<bool> asst::TaskDataSymbolStream::parse(const std::string& task_expr)
{
bool task_changed = false;
auto emplace_symbol_if_not_empty = [&](const auto l, const auto r) {
if (l < r) {
auto symbol = std::string_view(l, r);
std::string symbol(l, r);
auto symbol_type = Symbol::type(symbol);
if (Symbol::is_sharp_type(symbol_type)) {
if (!m_symbolstream.empty() && m_symbolstream.back() == Symbol::Sharp) {
@@ -56,7 +56,7 @@ asst::ResultOrError<bool> asst::TaskDataSymbolStream::parse(std::string_view tas
case '@': {
emplace_symbol_if_not_empty(y_begin, p);
y_begin = p + 1;
auto symbol = TaskDataSymbol::type(std::string_view { std::addressof(*p), 1 });
auto symbol = TaskDataSymbol::type(std::string { std::addressof(*p), 1 });
if (symbol == TaskDataSymbol::Name) [[unlikely]] {
// should not happen
return { std::nullopt,
@@ -77,7 +77,7 @@ asst::ResultOrError<bool> asst::TaskDataSymbolStream::parse(std::string_view tas
}
asst::TaskDataSymbolStream::SymbolsOrError
asst::TaskDataSymbolStream::decode(AppendPrefixFunc append_prefix, std::string_view self_name) const
asst::TaskDataSymbolStream::decode(AppendPrefixFunc append_prefix, const std::string& self_name) const
{
/*
$name = 至少一位的任务名

View File

@@ -21,7 +21,7 @@ private:
Symbols m_symbolstream;
public:
ResultOrError<bool> parse(std::string_view task_expr);
SymbolsOrError decode(AppendPrefixFunc append_prefix, std::string_view self_name) const;
ResultOrError<bool> parse(const std::string& task_expr);
SymbolsOrError decode(AppendPrefixFunc append_prefix, const std::string& self_name) const;
};
} // namespace asst