Fix caching of regex highlighter matches

The previous method was constantly invalidating cache when used in
conjunction with region highlighters.
This commit is contained in:
Maxime Coste 2015-02-15 19:42:48 +00:00
parent 8e6cfd3f09
commit 53f1c35013

View File

@ -70,6 +70,9 @@ void apply_highlighter(const Context& context,
ByteCoord begin, ByteCoord end, ByteCoord begin, ByteCoord end,
Highlighter& highlighter) Highlighter& highlighter)
{ {
if (begin == end)
return;
using LineIterator = DisplayBuffer::LineList::iterator; using LineIterator = DisplayBuffer::LineList::iterator;
LineIterator first_line; LineIterator first_line;
Vector<DisplayLine::iterator> insert_pos; Vector<DisplayLine::iterator> insert_pos;
@ -202,14 +205,14 @@ public:
{ {
} }
void highlight(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer, BufferRange) override void highlight(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer, BufferRange range) override
{ {
if (flags != HighlightFlags::Highlight) if (flags != HighlightFlags::Highlight)
return; return;
Vector<Optional<Face>> faces(m_faces.size()); Vector<Optional<Face>> faces(m_faces.size());
auto& cache = update_cache_ifn(context.buffer(), display_buffer.range()); auto& cache = update_cache_ifn(context.buffer(), display_buffer.range(), range);
for (auto& match : cache.m_matches) for (auto& match : cache)
{ {
for (size_t n = 0; n < match.size(); ++n) for (size_t n = 0; n < match.size(); ++n)
{ {
@ -269,9 +272,10 @@ public:
private: private:
struct Cache struct Cache
{ {
std::pair<LineCount, LineCount> m_range;
size_t m_timestamp = 0; size_t m_timestamp = 0;
Vector<Vector<BufferRange, MemoryDomain::Highlight>, MemoryDomain::Highlight> m_matches; using MatchesList = Vector<Vector<BufferRange, MemoryDomain::Highlight>, MemoryDomain::Highlight>;
using RangeAndMatches = std::pair<BufferRange, MatchesList>;
Vector<RangeAndMatches, MemoryDomain::Highlight> m_matches;
}; };
BufferSideCache<Cache> m_cache; BufferSideCache<Cache> m_cache;
@ -280,39 +284,53 @@ private:
bool m_force_update = false; bool m_force_update = false;
Cache& update_cache_ifn(const Buffer& buffer, const BufferRange& range) Cache::MatchesList& update_cache_ifn(const Buffer& buffer, const BufferRange& display_range,
const BufferRange& buffer_range)
{ {
Cache& cache = m_cache.get(buffer); Cache& cache = m_cache.get(buffer);
auto& matches = cache.m_matches;
LineCount first_line = range.first.line; if (m_force_update or cache.m_timestamp != buffer.timestamp())
LineCount last_line = std::min(buffer.line_count()-1, range.second.line); {
matches.clear();
if (not m_force_update and cache.m_timestamp = buffer.timestamp();
buffer.timestamp() == cache.m_timestamp and }
first_line >= cache.m_range.first and
last_line <= cache.m_range.second)
return cache;
m_force_update = false; m_force_update = false;
cache.m_range.first = std::max(0_line, first_line - 10); const LineCount line_offset = 3;
cache.m_range.second = std::min(buffer.line_count()-1, last_line+10); BufferRange range{std::max(buffer_range.first.line, display_range.first.line - line_offset),
cache.m_timestamp = buffer.timestamp(); std::min(buffer_range.second.line, display_range.second.line + line_offset)};
cache.m_matches.clear(); auto it = std::upper_bound(matches.begin(), matches.end(), range,
[](const BufferRange& lhs, const Cache::RangeAndMatches& rhs)
{ return lhs.first < rhs.first.second; });
if (it == matches.end() or it->first.first > range.second)
it = matches.insert(it, Cache::RangeAndMatches{range, {}});
else if (it->first.first <= range.first and it->first.second >= range.second)
return it->second;
else
{
range.first = std::min(range.first, it->first.first);
range.second = std::max(range.second, it->first.second);
it->first = range;
it->second.clear();
}
auto& match_list = it->second;
using RegexIt = RegexIterator<BufferIterator>; using RegexIt = RegexIterator<BufferIterator>;
RegexIt re_it{buffer.iterator_at(cache.m_range.first), RegexIt re_it{buffer.iterator_at(range.first),
buffer.iterator_at(cache.m_range.second+1), m_regex}; buffer.iterator_at(range.second), m_regex};
RegexIt re_end; RegexIt re_end;
for (; re_it != re_end; ++re_it) for (; re_it != re_end; ++re_it)
{ {
cache.m_matches.emplace_back(); match_list.emplace_back();
auto& match = cache.m_matches.back(); auto& match = match_list.back();
for (auto& sub : *re_it) for (auto& sub : *re_it)
match.emplace_back(sub.first.coord(), sub.second.coord()); match.emplace_back(sub.first.coord(), sub.second.coord());
} }
return cache; return match_list;
} }
}; };