diff options
author | Neil Moore <neil@s-z.org> | 2014-07-12 12:20:51 -0400 |
---|---|---|
committer | Neil Moore <neil@s-z.org> | 2014-07-12 12:40:59 -0400 |
commit | 6a3dccaebf65a0c63c2e4007869fed7bb4e9b9ac (patch) | |
tree | b6da49021c88e4de35ab82aa906c4fcec490f559 | |
parent | 342abdf7a4efb2539a5f39343aeb519f2b623f7f (diff) | |
download | crawl-ref-6a3dccaebf65a0c63c2e4007869fed7bb4e9b9ac.tar.gz crawl-ref-6a3dccaebf65a0c63c2e4007869fed7bb4e9b9ac.zip |
Prefer closer prefixes in find_earliest_match.
If multiple strings contain the spec as a prefix, choose the shortest
such string, so that a spec of "vamp" prefers "vampire" to "vampire
bat".
-rw-r--r-- | crawl-ref/source/libutil.h | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h index b9557bb824..b5d29b6b68 100644 --- a/crawl-ref/source/libutil.h +++ b/crawl-ref/source/libutil.h @@ -192,16 +192,19 @@ string unwrap_desc(string desc); * the name of the enumerator. * @return The enumerator that satisfies pred and whose name contains the * spec substring beginning at the earliest position. If no such - * enumerator exists, returns end. Exact matches are preferred to - * prefix matches but otherwise ties are broken in an unspecified - * manner. + * enumerator exists, returns end. If there are multiple strings + * containing the spec as a prefix, returns the shortest such string + * (so exact matches are preferred); otherwise ties are broken in + * an unspecified manner. */ template<class Enum, class Pred, class NameFunc> Enum find_earliest_match(string spec, Enum begin, Enum end, Pred pred, NameFunc namefunc) { Enum selected = end; + const size_t speclen = spec.length(); size_t bestpos = string::npos; + size_t bestlen = string::npos; for (size_t i = begin; i < end; ++i) { const Enum curr = static_cast<Enum>(i); @@ -211,15 +214,18 @@ Enum find_earliest_match(string spec, Enum begin, Enum end, const string name = lowercase_string(namefunc(curr)); const size_t pos = name.find(spec); + const size_t len = name.length(); - if (pos < bestpos) + if (pos < bestpos || pos == 0 && len < bestlen) { - // Exact match is better than prefix match. - if (name == spec) + // Exit early if we found an exact match. + if (pos == 0 && len == speclen) return curr; // npos is never less than bestpos, so the spec was found. bestpos = pos; + if (pos == 0) + bestlen = len; selected = curr; } } |