Use flags and bit operations instead of bools in RankedMatch
full match is now the most important flag for comparison.
This commit is contained in:
parent
95c21a4ebd
commit
cbe38b2f96
16
src/flags.hh
16
src/flags.hh
|
@ -37,6 +37,9 @@ struct TestableFlags
|
||||||
Flags value;
|
Flags value;
|
||||||
constexpr operator bool() const { return (UnderlyingType<Flags>)value; }
|
constexpr operator bool() const { return (UnderlyingType<Flags>)value; }
|
||||||
constexpr operator Flags() const { return value; }
|
constexpr operator Flags() const { return value; }
|
||||||
|
|
||||||
|
bool operator==(const TestableFlags<Flags>& other) const { return value == other.value; }
|
||||||
|
bool operator!=(const TestableFlags<Flags>& other) const { return value != other.value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Flags, typename = EnableIfWithBitOps<Flags>>
|
template<typename Flags, typename = EnableIfWithBitOps<Flags>>
|
||||||
|
@ -58,6 +61,19 @@ constexpr Flags operator~(Flags lhs)
|
||||||
return (Flags)(~(UnderlyingType<Flags>)lhs);
|
return (Flags)(~(UnderlyingType<Flags>)lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Flags, typename = EnableIfWithBitOps<Flags>>
|
||||||
|
constexpr Flags operator^(Flags lhs, Flags rhs)
|
||||||
|
{
|
||||||
|
return (Flags)((UnderlyingType<Flags>) lhs ^ (UnderlyingType<Flags>) rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Flags, typename = EnableIfWithBitOps<Flags>>
|
||||||
|
Flags& operator^=(Flags& lhs, Flags rhs)
|
||||||
|
{
|
||||||
|
(UnderlyingType<Flags>&) lhs ^= (UnderlyingType<Flags>) rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // flags_hh_INCLUDED
|
#endif // flags_hh_INCLUDED
|
||||||
|
|
|
@ -70,9 +70,9 @@ static bool smartcase_eq(Codepoint query, Codepoint candidate)
|
||||||
return query == (islower(query) ? to_lower(candidate) : 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();
|
auto it = str.begin();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (auto subseq_it = subseq.begin(); subseq_it != subseq.end();)
|
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++;
|
index_sum += index++;
|
||||||
}
|
}
|
||||||
|
out_index_sum = index_sum;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,10 +104,17 @@ RankedMatch::RankedMatch(StringView candidate, StringView query, TestFunc func)
|
||||||
{
|
{
|
||||||
m_candidate = candidate;
|
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_word_boundary_match_count = count_word_boundaries_match(candidate, query);
|
||||||
m_only_word_boundary = m_word_boundary_match_count == query.length();
|
if (m_word_boundary_match_count == query.length())
|
||||||
m_prefix = std::equal(query.begin(), query.end(), candidate.begin());
|
m_flags |= Flags::OnlyWordBoundary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,19 +135,10 @@ bool RankedMatch::operator<(const RankedMatch& other) const
|
||||||
{
|
{
|
||||||
kak_assert((bool)*this and (bool)other);
|
kak_assert((bool)*this and (bool)other);
|
||||||
|
|
||||||
if (m_prefix != other.m_prefix)
|
const auto diff = m_flags ^ other.m_flags;
|
||||||
return m_prefix;
|
// flags are different, use their ordering to return the first match
|
||||||
|
if (diff != Flags::None)
|
||||||
if (m_first_char_match != other.m_first_char_match)
|
return (int)(m_flags & diff) > (int)(other.m_flags & diff);
|
||||||
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;
|
|
||||||
|
|
||||||
if (m_word_boundary_match_count != other.m_word_boundary_match_count)
|
if (m_word_boundary_match_count != other.m_word_boundary_match_count)
|
||||||
return m_word_boundary_match_count > other.m_word_boundary_match_count;
|
return m_word_boundary_match_count > other.m_word_boundary_match_count;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define ranked_match_hh_INCLUDED
|
#define ranked_match_hh_INCLUDED
|
||||||
|
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
|
#include "flags.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -32,14 +33,24 @@ private:
|
||||||
template<typename TestFunc>
|
template<typename TestFunc>
|
||||||
RankedMatch(StringView candidate, StringView query, TestFunc test);
|
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;
|
StringView m_candidate;
|
||||||
bool m_first_char_match = false;
|
Flags m_flags = Flags::None;
|
||||||
bool m_prefix = false;
|
|
||||||
int m_word_boundary_match_count = 0;
|
int m_word_boundary_match_count = 0;
|
||||||
int m_match_index_sum = 0;
|
int m_match_index_sum = 0;
|
||||||
bool m_only_word_boundary = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<> struct WithBitOps<RankedMatch::Flags> : std::true_type {};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ranked_match_hh_INCLUDED
|
#endif // ranked_match_hh_INCLUDED
|
||||||
|
|
Loading…
Reference in New Issue
Block a user