Commit 56f3c519 authored by Florian Oetke's avatar Florian Oetke
Browse files

fixed iterator invalidation in console_command processing

parent e4d4dcc3
Pipeline #3126 passed with stage
in 13 minutes and 11 seconds
......@@ -69,20 +69,20 @@ namespace mirrage::gui {
auto stream = std::stringstream{};
auto max_width = 0;
for(auto& c : util::Console_command_container::list_all_commands()) {
auto sep = c.second.api().find("|");
max_width = std::max(max_width, int(sep != std::string::npos ? sep : c.second.api().size()));
auto sep = c.second->api().find("|");
max_width = std::max(max_width, int(sep != std::string::npos ? sep : c.second->api().size()));
}
for(auto& c : util::Console_command_container::list_all_commands()) {
auto sep = c.second.api().find("|");
auto sep = c.second->api().find("|");
stream << c.second.api().substr(0, sep);
for(int i = int(sep != std::string::npos ? sep : c.second.api().size()); i < max_width + 10;
stream << c.second->api().substr(0, sep);
for(int i = int(sep != std::string::npos ? sep : c.second->api().size()); i < max_width + 10;
i++)
stream << ' ';
if(sep != std::string::npos)
stream << c.second.api().substr(sep + 1);
stream << c.second->api().substr(sep + 1);
stream << "\n";
}
......
......@@ -95,9 +95,9 @@ namespace mirrage::util {
static auto list_all_commands() -> const auto& { return all_commands(); }
private:
static auto all_commands() -> std::unordered_multimap<std::string, Console_command>&
static auto all_commands() -> std::unordered_multimap<std::string, std::unique_ptr<Console_command>>&
{
static std::unordered_multimap<std::string, Console_command> cmds;
static std::unordered_multimap<std::string, std::unique_ptr<Console_command>> cmds;
return cmds;
}
......@@ -118,46 +118,43 @@ namespace mirrage::util {
std::regex(R"xxx(\"((?:[^"]|\\")+(?!\\).)\"|([^ ]+))xxx", std::regex::optimize);
auto name = api.substr(0, api.find(" "));
auto c = all_commands().emplace(
std::piecewise_construct,
std::forward_as_tuple(name),
std::forward_as_tuple(name, api, [api, f = std::forward<F>(f)](std::string_view cmd) {
auto arg_iter =
std::cregex_iterator(cmd.data(), cmd.data() + cmd.size(), split_args_regex);
auto arg_end = std::cregex_iterator();
util::foreach_function_arg_call(
f, [&](auto type) -> util::maybe<typename decltype(type)::type> {
if(arg_iter == arg_end) {
LOG(plog::error) << "Not enough arguments.";
return util::nothing;
}
auto curr = *arg_iter;
arg_iter++;
if(curr[1].length() == 0) {
return util::from_string<typename decltype(type)::type>(
cmd.substr(std::size_t(curr.position()),
std::size_t(curr.length())));
} else { // quoted
auto arg = std::string_view(curr[1].first,
std::size_t(curr[1].length()));
if(!arg.find("\\"))
return util::from_string<typename decltype(type)::type>(arg);
else {
// contains escape sequences we have to replace
auto arg_str = std::string(arg);
util::replace_inplace(arg_str, "\\\"", "\"");
util::replace_inplace(arg_str, "\\\\", "\\");
return util::from_string<typename decltype(type)::type>(arg_str);
}
}
});
}));
_command_ids.emplace_back(c->second.id());
auto cmd_callback = [api, f = std::forward<F>(f)](std::string_view cmd) {
auto arg_iter = std::cregex_iterator(cmd.data(), cmd.data() + cmd.size(), split_args_regex);
auto arg_end = std::cregex_iterator();
util::foreach_function_arg_call(f, [&](auto type) -> util::maybe<typename decltype(type)::type> {
if(arg_iter == arg_end) {
LOG(plog::error) << "Not enough arguments.";
return util::nothing;
}
auto curr = *arg_iter;
arg_iter++;
if(curr[1].length() == 0) {
return util::from_string<typename decltype(type)::type>(
cmd.substr(std::size_t(curr.position()), std::size_t(curr.length())));
} else { // quoted
auto arg = std::string_view(curr[1].first, std::size_t(curr[1].length()));
if(!arg.find("\\"))
return util::from_string<typename decltype(type)::type>(arg);
else {
// contains escape sequences we have to replace
auto arg_str = std::string(arg);
util::replace_inplace(arg_str, "\\\"", "\"");
util::replace_inplace(arg_str, "\\\\", "\\");
return util::from_string<typename decltype(type)::type>(arg_str);
}
}
});
};
auto c = all_commands().emplace(std::move(name),
std::make_unique<Console_command>(name, api, cmd_callback));
_command_ids.emplace_back(c->second->id());
return *this;
}
......
......@@ -2,6 +2,7 @@
#include <mirrage/utils/log.hpp>
#include <mirrage/utils/ranges.hpp>
#include <mirrage/utils/small_vector.hpp>
namespace mirrage::util {
......@@ -9,7 +10,8 @@ namespace mirrage::util {
{
auto& cmds = all_commands();
for(auto iter = cmds.begin(); iter != cmds.end();) {
if(std::find(_command_ids.begin(), _command_ids.end(), iter->second.id()) != _command_ids.end()) {
if(std::find(_command_ids.begin(), _command_ids.end(), iter->second->id())
!= _command_ids.end()) {
iter = cmds.erase(iter);
} else {
iter++;
......@@ -27,10 +29,17 @@ namespace mirrage::util {
return false;
}
auto commands = util::small_vector<Console_command*, 1>();
for(auto& [key, value] : util::range(begin, end)) {
commands.emplace_back(value.get());
}
auto args = arg_sep != std::string::npos ? cmd.substr(arg_sep) : std::string_view{};
for(auto& [key, value] : util::range(begin, end))
value.call(args);
for(auto&& cmd : commands) {
LOG(plog::debug) << "CMD Call " << cmd << " to " << cmd->id();
cmd->call(args);
}
return true;
}
......@@ -42,7 +51,7 @@ namespace mirrage::util {
auto matches = std::vector<Console_command*>();
for(auto&& [key, value] : all_commands()) {
if(cmd.size() <= key.size() && std::string_view(key.c_str(), cmd.size()) == cmd) {
matches.emplace_back(&value);
matches.emplace_back(value.get());
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment