diff options
| author | Maxime Coste <mawww@kakoune.org> | 2017-12-02 14:02:41 +0800 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2017-12-02 14:02:41 +0800 |
| commit | b34bb6b794dd51372db7aa489e66ac5d2fde5eca (patch) | |
| tree | c2a5faf373b52e3d43fcdb5d3c1949d070998fd7 | |
| parent | 413f880e9e74e01b1b03692a04554a355fae2519 (diff) | |
Regex: make RegexIterator iterable and able to iter backwards
| -rw-r--r-- | src/regex.hh | 36 |
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; |
