Merge remote-tracking branch 'krobelus/faster-update-matches'
This commit is contained in:
commit
24d6072353
|
@ -2210,11 +2210,57 @@ private:
|
|||
m_regexes.insert({key, Regex{str, flags}});
|
||||
}
|
||||
|
||||
void add_matches(const Buffer& buffer, LineRange range, Cache& cache) const
|
||||
class MatchAdder
|
||||
{
|
||||
for (auto& [key, regex] : m_regexes)
|
||||
cache.matches[key];
|
||||
public:
|
||||
MatchAdder(RegionsHighlighter& region, const Buffer& buffer, Cache& cache) : m_buffer(buffer)
|
||||
{
|
||||
for (auto& [key, regex] : region.m_regexes)
|
||||
cache.matches[key];
|
||||
for (auto& [key, regex] : region.m_regexes)
|
||||
m_matchers.push_back(Matcher{cache.matches.get(key), regex});
|
||||
}
|
||||
|
||||
~MatchAdder()
|
||||
{
|
||||
// Move new matches into position.
|
||||
for (auto& [matches, regex, pivot, vm] : m_matchers)
|
||||
std::inplace_merge(matches.begin(), matches.begin() + pivot, matches.end(),
|
||||
[](const auto& lhs, const auto& rhs) { return lhs.line < rhs.line; });
|
||||
}
|
||||
|
||||
void add(LineRange range)
|
||||
{
|
||||
for (auto line = range.begin; line < range.end; ++line)
|
||||
{
|
||||
const StringView l = m_buffer[line];
|
||||
const auto flags = RegexExecFlags::NotEndOfLine; // buffer line already ends with \n
|
||||
|
||||
for (auto& [matches, regex, pivot, vm] : m_matchers)
|
||||
{
|
||||
auto extra_flags = RegexExecFlags::None;
|
||||
auto pos = l.begin();
|
||||
while (vm.exec(pos, l.end(), l.begin(), l.end(), flags | extra_flags))
|
||||
{
|
||||
ConstArrayView<const char*> captures = vm.captures();
|
||||
const bool with_capture = regex.mark_count() > 0 and captures[2] != nullptr and
|
||||
captures[1] - captures[0] < std::numeric_limits<uint16_t>::max();
|
||||
matches.push_back({
|
||||
line,
|
||||
(int)(captures[0] - l.begin()),
|
||||
(int)(captures[1] - l.begin()),
|
||||
(uint16_t)(with_capture ? captures[2] - captures[0] : 0),
|
||||
(uint16_t)(with_capture ? captures[3] - captures[2] : 0)
|
||||
});
|
||||
pos = captures[1];
|
||||
|
||||
extra_flags = (captures[0] == captures[1]) ? RegexExecFlags::NotInitialNull : RegexExecFlags::None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct Matcher
|
||||
{
|
||||
RegexMatchList& matches;
|
||||
|
@ -2222,48 +2268,10 @@ private:
|
|||
size_t pivot = matches.size();
|
||||
ThreadedRegexVM<const char*, RegexMode::Forward | RegexMode::Search> vm{*regex.impl()};
|
||||
};
|
||||
Vector<Matcher> matchers;
|
||||
for (auto& [key, regex] : m_regexes)
|
||||
matchers.push_back(Matcher{cache.matches.get(key), regex});
|
||||
|
||||
for (auto line = range.begin; line < range.end; ++line)
|
||||
{
|
||||
const StringView l = buffer[line];
|
||||
const auto flags = RegexExecFlags::NotEndOfLine; // buffer line already ends with \n
|
||||
|
||||
for (auto& [matches, regex, pivot, vm] : matchers)
|
||||
{
|
||||
auto extra_flags = RegexExecFlags::None;
|
||||
auto pos = l.begin();
|
||||
while (vm.exec(pos, l.end(), l.begin(), l.end(), flags | extra_flags))
|
||||
{
|
||||
ConstArrayView<const char*> captures = vm.captures();
|
||||
const bool with_capture = regex.mark_count() > 0 and captures[2] != nullptr and
|
||||
captures[1] - captures[0] < std::numeric_limits<uint16_t>::max();
|
||||
matches.push_back({
|
||||
line,
|
||||
(int)(captures[0] - l.begin()),
|
||||
(int)(captures[1] - l.begin()),
|
||||
(uint16_t)(with_capture ? captures[2] - captures[0] : 0),
|
||||
(uint16_t)(with_capture ? captures[3] - captures[2] : 0)
|
||||
});
|
||||
pos = captures[1];
|
||||
|
||||
extra_flags = (captures[0] == captures[1]) ? RegexExecFlags::NotInitialNull : RegexExecFlags::None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& [matches, regex, pivot, vm] : matchers)
|
||||
{
|
||||
auto pos = std::lower_bound(matches.begin(), matches.begin() + pivot, range.begin,
|
||||
[](const RegexMatch& m, LineCount l) { return m.line < l; });
|
||||
kak_assert(pos == matches.begin() + pivot or pos->line >= range.end); // We should not have had matches for range
|
||||
|
||||
// Move new matches into position.
|
||||
std::rotate(pos, matches.begin() + pivot, matches.end());
|
||||
}
|
||||
}
|
||||
const Buffer& m_buffer;
|
||||
Vector<Matcher> m_matchers;
|
||||
};
|
||||
|
||||
void update_changed_lines(const Buffer& buffer, ConstArrayView<LineModification> modifs, Cache& cache)
|
||||
{
|
||||
|
@ -2299,7 +2307,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool update_matches(Cache& cache, const Buffer& buffer, LineRange range)
|
||||
{
|
||||
const size_t buffer_timestamp = buffer.timestamp();
|
||||
|
@ -2315,7 +2322,7 @@ private:
|
|||
add_regex(region->m_recurse, region->match_capture());
|
||||
}
|
||||
|
||||
add_matches(buffer, range, cache);
|
||||
MatchAdder{*this, buffer, cache}.add(range);
|
||||
cache.ranges.reset(range);
|
||||
cache.buffer_timestamp = buffer_timestamp;
|
||||
cache.regions_timestamp = m_regions_timestamp;
|
||||
|
@ -2333,10 +2340,11 @@ private:
|
|||
modified = true;
|
||||
}
|
||||
|
||||
cache.ranges.add_range(range, [&, this](const LineRange& range) {
|
||||
MatchAdder matches{*this, buffer, cache};
|
||||
cache.ranges.add_range(range, [&](const LineRange& range) {
|
||||
if (range.begin == range.end)
|
||||
return;
|
||||
add_matches(buffer, range, cache);
|
||||
matches.add(range);
|
||||
modified = true;
|
||||
});
|
||||
return modified;
|
||||
|
|
|
@ -147,26 +147,27 @@ void LineRangeSet::update(ConstArrayView<LineModification> modifs)
|
|||
|
||||
void LineRangeSet::add_range(LineRange range, FunctionRef<void (LineRange)> on_new_range)
|
||||
{
|
||||
auto it = std::lower_bound(begin(), end(), range.begin,
|
||||
[](LineRange range, LineCount line) { return range.end < line; });
|
||||
if (it == end() or it->begin > range.end)
|
||||
auto insert_at = std::lower_bound(begin(), end(), range.begin,
|
||||
[](LineRange range, LineCount line) { return range.end < line; });
|
||||
if (insert_at == end() or insert_at->begin > range.end)
|
||||
on_new_range(range);
|
||||
else
|
||||
{
|
||||
auto pos = range.begin;
|
||||
while (it != end() and it->begin <= range.end)
|
||||
auto it = insert_at;
|
||||
for (; it != end() and it->begin <= range.end; ++it)
|
||||
{
|
||||
if (pos < it->begin)
|
||||
on_new_range({pos, it->begin});
|
||||
|
||||
range = LineRange{std::min(range.begin, it->begin), std::max(range.end, it->end)};
|
||||
pos = it->end;
|
||||
it = erase(it);
|
||||
}
|
||||
insert_at = erase(insert_at, it);
|
||||
if (pos < range.end)
|
||||
on_new_range({pos, range.end});
|
||||
}
|
||||
insert(it, range);
|
||||
insert(insert_at, range);
|
||||
}
|
||||
|
||||
void LineRangeSet::remove_range(LineRange range)
|
||||
|
|
Loading…
Reference in New Issue
Block a user