diff --git a/src/CLI2.cpp b/src/CLI2.cpp index 53d8366e2..cd57e4dbd 100644 --- a/src/CLI2.cpp +++ b/src/CLI2.cpp @@ -699,8 +699,19 @@ const std::vector CLI2::getWords () bool CLI2::canonicalize ( std::string& canonicalized, const std::string& category, - const std::string& value) const + const std::string& value) { + // Utilize a cache mapping of (category, value) -> canonicalized value. + // This cache does not need to be invalidated, because entities are defined + // only once per initialization of the Context object. + int cache_key = 31 * std::hash{} (category) + std::hash{} (value); + auto cache_result = _canonical_cache.find (cache_key); + if (cache_result != _canonical_cache.end()) + { + canonicalized = cache_result->second; + return true; + } + // Extract a list of entities for category. std::vector options; auto c = _entities.equal_range (category); @@ -710,6 +721,7 @@ bool CLI2::canonicalize ( if (value == e->second) { canonicalized = value; + _canonical_cache[cache_key] = value; return true; } @@ -721,6 +733,7 @@ bool CLI2::canonicalize ( if (autoComplete (value, options, matches, minimumMatchLength) == 1) { canonicalized = matches[0]; + _canonical_cache[cache_key] = matches[0]; return true; } diff --git a/src/CLI2.h b/src/CLI2.h index 6a276a758..b785c9f04 100644 --- a/src/CLI2.h +++ b/src/CLI2.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -77,7 +78,7 @@ public: void addContext (bool readable, bool writeable); void prepareFilter (); const std::vector getWords (); - bool canonicalize (std::string&, const std::string&, const std::string&) const; + bool canonicalize (std::string&, const std::string&, const std::string&); std::string getBinary () const; std::string getCommand (bool canonical = true) const; const std::string dump (const std::string& title = "CLI2 Parser") const; @@ -109,6 +110,7 @@ private: public: std::multimap _entities {}; std::map _aliases {}; + std::unordered_map _canonical_cache {}; std::vector _original_args {}; std::vector _args {};