From 86c5e8f75bbc4e7b6c805ade50dbcd8cf3a5672a Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 9 Jul 2021 17:03:22 +1000 Subject: [PATCH] Avoid temporary vector in expand_token Instead of return a vector, take the target vector as a parameter and push tokens to it. --- src/command_manager.cc | 59 +++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/command_manager.cc b/src/command_manager.cc index 113b4298..156ab0ab 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -321,10 +321,21 @@ Token parse_percent_token(Reader& reader, bool throw_on_unterminated) } } -template -std::conditional_t> -expand_token(Token&& token, const Context& context, const ShellContext& shell_context) +template> or std::is_same_v>> +void expand_token(Token&& token, const Context& context, const ShellContext& shell_context, Target& target) { + constexpr bool single = std::is_same_v; + auto set_target = [&](auto&& s) { + if constexpr (single) + target = std::move(s); + else if constexpr (std::is_same_v, String>) + target.push_back(std::move(s)); + else if constexpr (std::is_same_v&&>) + target.insert(target.end(), std::make_move_iterator(s.begin()), std::make_move_iterator(s.end())); + else + target.insert(target.end(), s.begin(), s.end()); + }; + auto&& content = token.content; switch (token.type) { @@ -337,32 +348,32 @@ expand_token(Token&& token, const Context& context, const ShellContext& shell_co if (not str.empty() and str.back() == '\n') str.resize(str.length() - 1, 0); - return {str}; + return set_target(std::move(str)); } case Token::Type::RegisterExpand: if constexpr (single) - return context.main_sel_register_value(content).str(); + return set_target(context.main_sel_register_value(content).str()); else - return RegisterManager::instance()[content].get(context) | gather>(); + return set_target(RegisterManager::instance()[content].get(context)); case Token::Type::OptionExpand: { auto& opt = context.options()[content]; if constexpr (single) - return opt.get_as_string(Quoting::Raw); + return set_target(opt.get_as_string(Quoting::Raw)); else - return opt.get_as_strings(); + return set_target(opt.get_as_strings()); } case Token::Type::ValExpand: { auto it = shell_context.env_vars.find(content); if (it != shell_context.env_vars.end()) - return {it->value}; + return set_target(it->value); auto val = ShellManager::instance().get_val(content, context); if constexpr (single) - return join(val, false, ' '); + return set_target(join(val, false, ' ')); else - return val; + return set_target(std::move(val)); } case Token::Type::ArgExpand: { @@ -370,26 +381,25 @@ expand_token(Token&& token, const Context& context, const ShellContext& shell_co if (content == '@') { if constexpr (single) - return join(params, ' ', false); + return set_target(join(params, ' ', false)); else - return Vector{params.begin(), params.end()}; + return set_target(params); } const int arg = str_to_int(content)-1; if (arg < 0) throw runtime_error("invalid argument index"); - return {arg < params.size() ? params[arg] : String{}}; + return set_target(arg < params.size() ? params[arg] : String{}); } case Token::Type::FileExpand: - return {read_file(content)}; + return set_target(read_file(content)); case Token::Type::RawEval: - return {expand(content, context, shell_context)}; + return set_target(expand(content, context, shell_context)); case Token::Type::Raw: case Token::Type::RawQuoted: - return {std::move(content)}; + return set_target(std::move(content)); default: kak_assert(false); } - return {}; } } @@ -463,7 +473,9 @@ String expand_impl(StringView str, const Context& context, else { res += reader.substr_from(beg); - res += postprocess(expand_token(parse_percent_token(reader, true), context, shell_context)); + String token; + expand_token(parse_percent_token(reader, true), context, shell_context, token); + res += postprocess(token); beg = reader.pos; } } @@ -532,7 +544,7 @@ void CommandManager::execute(StringView command_line, CommandParser parser(command_line); ByteCount command_pos{}; - Vector params; + Vector params; while (true) { Optional token = parser.read_token(true); @@ -568,12 +580,7 @@ void CommandManager::execute(StringView command_line, params.insert(params.end(), shell_context.params.begin(), shell_context.params.end()); else - { - auto tokens = expand_token(*std::move(token), context, shell_context); - params.insert(params.end(), - std::make_move_iterator(tokens.begin()), - std::make_move_iterator(tokens.end())); - } + expand_token(*std::move(token), context, shell_context, params); } }