diff options
author | Nicholas Feinberg <pleasingfung@gmail.com> | 2014-08-14 21:01:06 -0700 |
---|---|---|
committer | Nicholas Feinberg <pleasingfung@gmail.com> | 2014-08-14 21:01:06 -0700 |
commit | 25930a6b86d330b8b402670286e55eb4cbff0a6c (patch) | |
tree | d6e92b4d964dadf7d757bba00c7dd7a72872cde6 /crawl-ref/source/strings.h | |
parent | f7fa7ed2a5c6619007a108d3c356a15153751a50 (diff) | |
download | crawl-ref-25930a6b86d330b8b402670286e55eb4cbff0a6c.tar.gz crawl-ref-25930a6b86d330b8b402670286e55eb4cbff0a6c.zip |
Refactor.
Diffstat (limited to 'crawl-ref/source/strings.h')
-rw-r--r-- | crawl-ref/source/strings.h | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/crawl-ref/source/strings.h b/crawl-ref/source/strings.h index ea6d51462f..fad53580f7 100644 --- a/crawl-ref/source/strings.h +++ b/crawl-ref/source/strings.h @@ -48,6 +48,60 @@ string &trim_string(string &str); string &trim_string_right(string &str); string trimmed_string(string s); +/** + * Find the enumerator e between begin and end that satisfies pred(e) and + * whose name, as given by namefunc(e), has the earliest occurrence of the + * substring spec. + * + * @param spec The substring to search for. + * @param begin The beginning of the enumerator range to search in. + * @param end One past the end of the enum range to search in. + * @param pred A function from Enum to bool. Enumerators that do not + * satisfy the predicate are ignored. + * @param namefunc A function from Enum to string or const char * giving + * 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. 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 < (size_t) end; ++i) + { + const Enum curr = static_cast<Enum>(i); + + if (!pred(curr)) + continue; + + const string name = lowercase_string(namefunc(curr)); + const size_t pos = name.find(spec); + const size_t len = name.length(); + + if (pos < bestpos || pos == 0 && len < bestlen) + { + // 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; + } + } + return selected; +} + template <typename Z> string comma_separated_line(Z start, Z end, const string &andc = " and ", const string &comma = ", ") |