1
1
mirror of https://github.com/mawww/kakoune.git synced 2025-01-03 01:03:12 +03:00

Regex: make RegexIterator iterable and able to iter backwards

This commit is contained in:
Maxime Coste 2017-12-02 14:02:41 +08:00
parent 413f880e9e
commit b34bb6b794

View File

@ -139,7 +139,7 @@ bool regex_search(It begin, It end, MatchResults<It>& res, const Regex& re,
String option_to_string(const Regex& re); String option_to_string(const Regex& re);
void option_from_string(StringView str, Regex& re); void option_from_string(StringView str, Regex& re);
template<typename Iterator> template<typename Iterator, MatchDirection direction = MatchDirection::Forward>
struct RegexIterator struct RegexIterator
{ {
using ValueType = MatchResults<Iterator>; using ValueType = MatchResults<Iterator>;
@ -147,7 +147,8 @@ struct RegexIterator
RegexIterator() = default; RegexIterator() = default;
RegexIterator(Iterator begin, Iterator end, const Regex& re, RegexIterator(Iterator begin, Iterator end, const Regex& re,
RegexExecFlags flags = RegexExecFlags::None) RegexExecFlags flags = RegexExecFlags::None)
: m_regex{&re}, m_next_begin{begin}, m_begin{begin}, m_end{end}, m_flags{flags} : m_regex{&re}, m_next_pos{direction == MatchDirection::Forward ? begin : end},
m_begin{begin}, m_end{end}, m_flags{flags}
{ {
next(); next();
} }
@ -167,7 +168,7 @@ struct RegexIterator
return true; return true;
return lhs.m_regex == rhs.m_regex and return lhs.m_regex == rhs.m_regex and
lhs.m_next_begin == rhs.m_next_begin and lhs.m_next_pos == rhs.m_next_pos and
lhs.m_end == rhs.m_end and lhs.m_end == rhs.m_end and
lhs.m_flags == rhs.m_flags and lhs.m_flags == rhs.m_flags and
lhs.m_results == rhs.m_results; lhs.m_results == rhs.m_results;
@ -178,6 +179,9 @@ struct RegexIterator
return not (lhs == rhs); return not (lhs == rhs);
} }
RegexIterator begin() { return *this; }
RegexIterator end() { return {}; }
private: private:
void next() void next()
{ {
@ -186,19 +190,31 @@ private:
RegexExecFlags additional_flags{}; RegexExecFlags additional_flags{};
if (m_results.size() and m_results[0].first == m_results[0].second) if (m_results.size() and m_results[0].first == m_results[0].second)
additional_flags |= RegexExecFlags::NotInitialNull; additional_flags |= RegexExecFlags::NotInitialNull;
if (m_begin != m_next_begin)
if (direction == MatchDirection::Forward)
{
if (m_begin != m_next_pos)
additional_flags |= RegexExecFlags::NotBeginOfSubject | RegexExecFlags::PrevAvailable; additional_flags |= RegexExecFlags::NotBeginOfSubject | RegexExecFlags::PrevAvailable;
if (not regex_search(m_next_begin, m_end, m_results, *m_regex, if (not regex_search(m_next_pos, m_end, m_results, *m_regex,
m_flags | additional_flags)) m_flags | additional_flags))
m_regex = nullptr; m_regex = nullptr;
else else
m_next_begin = m_results[0].second; m_next_pos = m_results[0].second;
}
else
{
if (not regex_search<Iterator, MatchDirection::Backward>(m_begin, m_next_pos, m_results, *m_regex,
m_flags | additional_flags))
m_regex = nullptr;
else
m_next_pos = m_results[0].first;
}
} }
const Regex* m_regex = nullptr; const Regex* m_regex = nullptr;
MatchResults<Iterator> m_results; MatchResults<Iterator> m_results;
Iterator m_next_begin{}; Iterator m_next_pos{};
const Iterator m_begin{}; const Iterator m_begin{};
const Iterator m_end{}; const Iterator m_end{};
const RegexExecFlags m_flags = RegexExecFlags::None; const RegexExecFlags m_flags = RegexExecFlags::None;