From cbe38b2f962443f5fefcbbb5f7552f50c0e841fc Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 29 Aug 2016 23:56:22 +0100 Subject: [PATCH] Use flags and bit operations instead of bools in RankedMatch full match is now the most important flag for comparison. --- src/flags.hh | 16 ++++++++++++++++ src/ranked_match.cc | 35 +++++++++++++++++------------------ src/ranked_match.hh | 17 ++++++++++++++--- 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/flags.hh b/src/flags.hh index 6b72ba05..824d37ca 100644 --- a/src/flags.hh +++ b/src/flags.hh @@ -37,6 +37,9 @@ struct TestableFlags Flags value; constexpr operator bool() const { return (UnderlyingType)value; } constexpr operator Flags() const { return value; } + + bool operator==(const TestableFlags& other) const { return value == other.value; } + bool operator!=(const TestableFlags& other) const { return value != other.value; } }; template> @@ -58,6 +61,19 @@ constexpr Flags operator~(Flags lhs) return (Flags)(~(UnderlyingType)lhs); } +template> +constexpr Flags operator^(Flags lhs, Flags rhs) +{ + return (Flags)((UnderlyingType) lhs ^ (UnderlyingType) rhs); +} + +template> +Flags& operator^=(Flags& lhs, Flags rhs) +{ + (UnderlyingType&) lhs ^= (UnderlyingType) rhs; + return lhs; +} + } #endif // flags_hh_INCLUDED diff --git a/src/ranked_match.cc b/src/ranked_match.cc index 67be7038..d61d95f5 100644 --- a/src/ranked_match.cc +++ b/src/ranked_match.cc @@ -70,9 +70,9 @@ static bool smartcase_eq(Codepoint query, Codepoint candidate) return query == (islower(query) ? to_lower(candidate) : candidate); } -static bool subsequence_match_smart_case(StringView str, StringView subseq, int& index_sum) +static bool subsequence_match_smart_case(StringView str, StringView subseq, int& out_index_sum) { - index_sum = 0; + int index_sum = 0; auto it = str.begin(); int index = 0; for (auto subseq_it = subseq.begin(); subseq_it != subseq.end();) @@ -88,6 +88,7 @@ static bool subsequence_match_smart_case(StringView str, StringView subseq, int& } index_sum += index++; } + out_index_sum = index_sum; return true; } @@ -103,10 +104,17 @@ RankedMatch::RankedMatch(StringView candidate, StringView query, TestFunc func) { m_candidate = candidate; - m_first_char_match = smartcase_eq(query[0], candidate[0]); + if (smartcase_eq(query[0], candidate[0])) + m_flags |= Flags::FirstCharMatch; + if (std::equal(query.begin(), query.end(), candidate.begin())) + { + m_flags |= Flags::Prefix; + if (query.length() == candidate.length()) + m_flags |= Flags::FullMatch; + } m_word_boundary_match_count = count_word_boundaries_match(candidate, query); - m_only_word_boundary = m_word_boundary_match_count == query.length(); - m_prefix = std::equal(query.begin(), query.end(), candidate.begin()); + if (m_word_boundary_match_count == query.length()) + m_flags |= Flags::OnlyWordBoundary; } } @@ -127,19 +135,10 @@ bool RankedMatch::operator<(const RankedMatch& other) const { kak_assert((bool)*this and (bool)other); - if (m_prefix != other.m_prefix) - return m_prefix; - - if (m_first_char_match != other.m_first_char_match) - return m_first_char_match; - - if (m_only_word_boundary and other.m_only_word_boundary) - { - if (m_word_boundary_match_count != other.m_word_boundary_match_count) - return m_word_boundary_match_count > other.m_word_boundary_match_count; - } - else if (m_only_word_boundary or other.m_only_word_boundary) - return m_only_word_boundary; + const auto diff = m_flags ^ other.m_flags; + // flags are different, use their ordering to return the first match + if (diff != Flags::None) + return (int)(m_flags & diff) > (int)(other.m_flags & diff); if (m_word_boundary_match_count != other.m_word_boundary_match_count) return m_word_boundary_match_count > other.m_word_boundary_match_count; diff --git a/src/ranked_match.hh b/src/ranked_match.hh index 0e0e49c4..35d76e15 100644 --- a/src/ranked_match.hh +++ b/src/ranked_match.hh @@ -2,6 +2,7 @@ #define ranked_match_hh_INCLUDED #include "string.hh" +#include "flags.hh" namespace Kakoune { @@ -32,14 +33,24 @@ private: template RankedMatch(StringView candidate, StringView query, TestFunc test); + enum class Flags : int + { + None = 0, + // Order is important, the highest bit has precedence for comparison + OnlyWordBoundary = 1 << 0, + FirstCharMatch = 1 << 1, + Prefix = 1 << 2, + FullMatch = 1 << 3, + }; + StringView m_candidate; - bool m_first_char_match = false; - bool m_prefix = false; + Flags m_flags = Flags::None; int m_word_boundary_match_count = 0; int m_match_index_sum = 0; - bool m_only_word_boundary = false; }; +template<> struct WithBitOps : std::true_type {}; + } #endif // ranked_match_hh_INCLUDED