summaryrefslogtreecommitdiff
path: root/src/regex.hh
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2017-12-02 14:02:41 +0800
committerMaxime Coste <mawww@kakoune.org>2017-12-02 14:02:41 +0800
commitb34bb6b794dd51372db7aa489e66ac5d2fde5eca (patch)
treec2a5faf373b52e3d43fcdb5d3c1949d070998fd7 /src/regex.hh
parent413f880e9e74e01b1b03692a04554a355fae2519 (diff)
Regex: make RegexIterator iterable and able to iter backwards
Diffstat (limited to 'src/regex.hh')
-rw-r--r--src/regex.hh36
1 files changed, 26 insertions, 10 deletions
diff --git a/src/regex.hh b/src/regex.hh
index 11926d64..7fda8f0b 100644
--- a/src/regex.hh
+++ b/src/regex.hh
@@ -139,7 +139,7 @@ bool regex_search(It begin, It end, MatchResults<It>& res, const Regex& re,
String option_to_string(const Regex& re);
void option_from_string(StringView str, Regex& re);
-template<typename Iterator>
+template<typename Iterator, MatchDirection direction = MatchDirection::Forward>
struct RegexIterator
{
using ValueType = MatchResults<Iterator>;
@@ -147,7 +147,8 @@ struct RegexIterator
RegexIterator() = default;
RegexIterator(Iterator begin, Iterator end, const Regex& re,
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();
}
@@ -167,7 +168,7 @@ struct RegexIterator
return true;
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_flags == rhs.m_flags and
lhs.m_results == rhs.m_results;
@@ -178,6 +179,9 @@ struct RegexIterator
return not (lhs == rhs);
}
+ RegexIterator begin() { return *this; }
+ RegexIterator end() { return {}; }
+
private:
void next()
{
@@ -186,19 +190,31 @@ private:
RegexExecFlags additional_flags{};
if (m_results.size() and m_results[0].first == m_results[0].second)
additional_flags |= RegexExecFlags::NotInitialNull;
- if (m_begin != m_next_begin)
- additional_flags |= RegexExecFlags::NotBeginOfSubject | RegexExecFlags::PrevAvailable;
- if (not regex_search(m_next_begin, m_end, m_results, *m_regex,
- m_flags | additional_flags))
- m_regex = nullptr;
+ if (direction == MatchDirection::Forward)
+ {
+ if (m_begin != m_next_pos)
+ additional_flags |= RegexExecFlags::NotBeginOfSubject | RegexExecFlags::PrevAvailable;
+
+ if (not regex_search(m_next_pos, m_end, m_results, *m_regex,
+ m_flags | additional_flags))
+ m_regex = nullptr;
+ else
+ m_next_pos = m_results[0].second;
+ }
else
- m_next_begin = m_results[0].second;
+ {
+ 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;
MatchResults<Iterator> m_results;
- Iterator m_next_begin{};
+ Iterator m_next_pos{};
const Iterator m_begin{};
const Iterator m_end{};
const RegexExecFlags m_flags = RegexExecFlags::None;