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 { ...@@ -69,20 +69,20 @@ namespace mirrage::gui {
auto stream = std::stringstream{}; auto stream = std::stringstream{};
auto max_width = 0; auto max_width = 0;
for(auto& c : util::Console_command_container::list_all_commands()) { for(auto& c : util::Console_command_container::list_all_commands()) {
auto sep = c.second.api().find("|"); auto sep = c.second->api().find("|");
max_width = std::max(max_width, int(sep != std::string::npos ? sep : c.second.api().size())); 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()) { 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); stream << c.second->api().substr(0, sep);
for(int i = int(sep != std::string::npos ? sep : c.second.api().size()); i < max_width + 10; for(int i = int(sep != std::string::npos ? sep : c.second->api().size()); i < max_width + 10;
i++) i++)
stream << ' '; stream << ' ';
if(sep != std::string::npos) if(sep != std::string::npos)
stream << c.second.api().substr(sep + 1); stream << c.second->api().substr(sep + 1);
stream << "\n"; stream << "\n";
} }
......
...@@ -95,9 +95,9 @@ namespace mirrage::util { ...@@ -95,9 +95,9 @@ namespace mirrage::util {
static auto list_all_commands() -> const auto& { return all_commands(); } static auto list_all_commands() -> const auto& { return all_commands(); }
private: 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; return cmds;
} }
...@@ -118,46 +118,43 @@ namespace mirrage::util { ...@@ -118,46 +118,43 @@ namespace mirrage::util {
std::regex(R"xxx(\"((?:[^"]|\\")+(?!\\).)\"|([^ ]+))xxx", std::regex::optimize); std::regex(R"xxx(\"((?:[^"]|\\")+(?!\\).)\"|([^ ]+))xxx", std::regex::optimize);
auto name = api.substr(0, api.find(" ")); auto name = api.substr(0, api.find(" "));
auto c = all_commands().emplace(
std::piecewise_construct, auto cmd_callback = [api, f = std::forward<F>(f)](std::string_view cmd) {
std::forward_as_tuple(name), auto arg_iter = std::cregex_iterator(cmd.data(), cmd.data() + cmd.size(), split_args_regex);
std::forward_as_tuple(name, api, [api, f = std::forward<F>(f)](std::string_view cmd) { auto arg_end = std::cregex_iterator();
auto arg_iter =
std::cregex_iterator(cmd.data(), cmd.data() + cmd.size(), split_args_regex); util::foreach_function_arg_call(f, [&](auto type) -> util::maybe<typename decltype(type)::type> {
auto arg_end = std::cregex_iterator(); if(arg_iter == arg_end) {
LOG(plog::error) << "Not enough arguments.";
util::foreach_function_arg_call( return util::nothing;
f, [&](auto type) -> util::maybe<typename decltype(type)::type> { }
if(arg_iter == arg_end) {
LOG(plog::error) << "Not enough arguments."; auto curr = *arg_iter;
return util::nothing; arg_iter++;
}
if(curr[1].length() == 0) {
auto curr = *arg_iter; return util::from_string<typename decltype(type)::type>(
arg_iter++; cmd.substr(std::size_t(curr.position()), std::size_t(curr.length())));
if(curr[1].length() == 0) { } else { // quoted
return util::from_string<typename decltype(type)::type>( auto arg = std::string_view(curr[1].first, std::size_t(curr[1].length()));
cmd.substr(std::size_t(curr.position()), if(!arg.find("\\"))
std::size_t(curr.length()))); return util::from_string<typename decltype(type)::type>(arg);
else {
} else { // quoted // contains escape sequences we have to replace
auto arg = std::string_view(curr[1].first, auto arg_str = std::string(arg);
std::size_t(curr[1].length())); util::replace_inplace(arg_str, "\\\"", "\"");
if(!arg.find("\\")) util::replace_inplace(arg_str, "\\\\", "\\");
return util::from_string<typename decltype(type)::type>(arg); return util::from_string<typename decltype(type)::type>(arg_str);
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());
}));
_command_ids.emplace_back(c->second.id());
return *this; return *this;
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <mirrage/utils/log.hpp> #include <mirrage/utils/log.hpp>
#include <mirrage/utils/ranges.hpp> #include <mirrage/utils/ranges.hpp>
#include <mirrage/utils/small_vector.hpp>
namespace mirrage::util { namespace mirrage::util {
...@@ -9,7 +10,8 @@ namespace mirrage::util { ...@@ -9,7 +10,8 @@ namespace mirrage::util {
{ {
auto& cmds = all_commands(); auto& cmds = all_commands();
for(auto iter = cmds.begin(); iter != cmds.end();) { 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); iter = cmds.erase(iter);
} else { } else {
iter++; iter++;
...@@ -27,10 +29,17 @@ namespace mirrage::util { ...@@ -27,10 +29,17 @@ namespace mirrage::util {
return false; 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{}; auto args = arg_sep != std::string::npos ? cmd.substr(arg_sep) : std::string_view{};
for(auto& [key, value] : util::range(begin, end)) for(auto&& cmd : commands) {
value.call(args); LOG(plog::debug) << "CMD Call " << cmd << " to " << cmd->id();
cmd->call(args);
}
return true; return true;
} }
...@@ -42,7 +51,7 @@ namespace mirrage::util { ...@@ -42,7 +51,7 @@ namespace mirrage::util {
auto matches = std::vector<Console_command*>(); auto matches = std::vector<Console_command*>();
for(auto&& [key, value] : all_commands()) { for(auto&& [key, value] : all_commands()) {
if(cmd.size() <= key.size() && std::string_view(key.c_str(), cmd.size()) == cmd) { 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