From 2b823338a8f6e2ce96c543c34a5abcb075cb8f9c Mon Sep 17 00:00:00 2001 From: Ken Matsui <26405363+ken-matsui@users.noreply.github.com> Date: Mon, 27 Jan 2025 19:56:27 -0500 Subject: [PATCH] Cli: reduce some computations of expandOpts --- src/Cli.cc | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/Cli.cc b/src/Cli.cc index a5479b1ec..1d9ef1c8f 100644 --- a/src/Cli.cc +++ b/src/Cli.cc @@ -459,22 +459,24 @@ Cli::parseArgs(const CliArgsView args) const noexcept { Result> Cli::expandOpts(const std::span args) const noexcept { - const auto getShortOpts = [](const Opts& opts) { - std::unordered_map shortOpts; - for (const Opt& opt : opts) { - if (opt.hasShort()) { - shortOpts.emplace(opt.shortName, opt); + struct ShortOpts { + std::unordered_map names; + std::size_t maxShortSize = 0; + + explicit ShortOpts(const Opts& opts) { + for (const Opt& opt : opts) { + if (opt.hasShort()) { + names.emplace(opt.shortName, opt); + maxShortSize = std::max(maxShortSize, opt.shortName.size()); + } } } - return shortOpts; }; std::optional> curSubcmd; std::reference_wrapper curLocalOpts = localOpts; - const std::unordered_map globalShortOpts = - getShortOpts(globalOpts); - std::unordered_map curLocalShortOpts = - getShortOpts(localOpts); + const ShortOpts globalShortOpts{ globalOpts }; + ShortOpts curLocalShortOpts{ localOpts }; std::vector expanded; for (std::size_t i = 0; i < args.size(); ++i) { @@ -489,7 +491,7 @@ Cli::expandOpts(const std::span args) const noexcept { curSubcmd = subcmds.at(arg); curLocalOpts = subcmds.at(arg).localOpts; - curLocalShortOpts = getShortOpts(curLocalOpts.get()); + curLocalShortOpts = ShortOpts{ curLocalOpts.get() }; continue; } @@ -548,10 +550,16 @@ Cli::expandOpts(const std::span args) const noexcept { // "-j1" => ["-j", "1"] // "-vvvrj1" => ["-vv", "-v", "-r", "-j", "1"] else if (arg.starts_with("-")) { + const std::size_t curMaxShortSize = std::max( + globalShortOpts.maxShortSize, curLocalShortOpts.maxShortSize + ); + bool handled = false; std::size_t left = 1; for (; left < arg.size(); ++left) { - for (std::size_t right = arg.size() - 1; right >= left; --right) { + const std::size_t rightStart = + std::min(curMaxShortSize, arg.size() - 1 - left) + left; + for (std::size_t right = rightStart; right >= left; --right) { // Start from the longest option name. const std::string optName = fmt::format("-{}", arg.substr(left, right - left + 1)); @@ -579,14 +587,14 @@ Cli::expandOpts(const std::span args) const noexcept { return Ok(); }; - auto opt = globalShortOpts.find(optName); - if (opt != globalShortOpts.end()) { + auto opt = globalShortOpts.names.find(optName); + if (opt != globalShortOpts.names.end()) { Try(handleShortOpt(opt->second)); handled = true; break; } - opt = curLocalShortOpts.find(optName); - if (opt != curLocalShortOpts.end()) { + opt = curLocalShortOpts.names.find(optName); + if (opt != curLocalShortOpts.names.end()) { Try(handleShortOpt(opt->second)); handled = true; break;