@@ -4637,7 +4637,7 @@ template <typename> constexpr bool is_range = false;
4637
4637
4638
4638
template <typename BeginIterator, typename EndIterator, typename RE, typename ResultIterator = BeginIterator> struct regex_range {
4639
4639
BeginIterator _begin;
4640
- const EndIterator _end;
4640
+ EndIterator _end;
4641
4641
4642
4642
constexpr CTRE_FORCE_INLINE regex_range(BeginIterator begin, EndIterator end) noexcept: _begin{begin}, _end{end} { }
4643
4643
@@ -4653,7 +4653,7 @@ template <typename... Ts> constexpr bool is_range<regex_range<Ts...>> = true;
4653
4653
4654
4654
template <typename BeginIterator, typename EndIterator, typename RE, typename ResultIterator = BeginIterator> struct regex_split_range {
4655
4655
BeginIterator _begin;
4656
- const EndIterator _end;
4656
+ EndIterator _end;
4657
4657
4658
4658
constexpr CTRE_FORCE_INLINE regex_split_range(BeginIterator begin, EndIterator end) noexcept: _begin{begin}, _end{end} { }
4659
4659
@@ -4667,6 +4667,96 @@ template <typename BeginIterator, typename EndIterator, typename RE, typename Re
4667
4667
4668
4668
template <typename... Ts> constexpr bool is_range<regex_split_range<Ts...>> = true;
4669
4669
4670
+ template <typename First, typename Last, typename RE> struct multi_subject_range {
4671
+ static constexpr bool is_input = std::is_same_v<std::iterator_traits<First>::iterator_category, std::input_iterator_tag>;
4672
+
4673
+ struct end_iterator { };
4674
+
4675
+ struct iterator {
4676
+ using value_type = decltype(RE::exec(std::declval<typename std::iterator_traits<First>::value_type>()));
4677
+ using iterator_category = std::forward_iterator_tag;
4678
+ using pointer = void;
4679
+ using reference = const value_type &;
4680
+ using difference_type = ssize_t;
4681
+
4682
+ First first{};
4683
+ Last last{};
4684
+ value_type current_result{};
4685
+
4686
+ constexpr CTRE_FORCE_INLINE iterator(First f, Last l) noexcept: first{f}, last{l}, current_result{find_first()} {
4687
+
4688
+ }
4689
+
4690
+ constexpr CTRE_FORCE_INLINE value_type find_first() noexcept {
4691
+ while (first != last) {
4692
+ if (auto res = RE::exec(*first)) return res;
4693
+ else ++first;
4694
+ }
4695
+ return {};
4696
+ }
4697
+
4698
+ constexpr CTRE_FORCE_INLINE const value_type & operator*() const noexcept {
4699
+ return current_result;
4700
+ }
4701
+
4702
+ constexpr CTRE_FORCE_INLINE iterator & operator++() noexcept {
4703
+ ++first;
4704
+ current_result = find_first();
4705
+ return *this;
4706
+ }
4707
+ constexpr CTRE_FORCE_INLINE iterator operator++(int) noexcept {
4708
+ auto previous = *this;
4709
+ this->operator++();
4710
+ return previous;
4711
+ }
4712
+
4713
+ friend constexpr CTRE_FORCE_INLINE bool operator==(const iterator & left, const iterator & right) noexcept {
4714
+ return left.first == right.first;
4715
+ }
4716
+ friend constexpr CTRE_FORCE_INLINE bool operator!=(const iterator & left, const iterator & right) noexcept {
4717
+ return !(left.first == right.first);
4718
+ }
4719
+ friend constexpr CTRE_FORCE_INLINE bool operator<(const iterator & left, const iterator & right) noexcept {
4720
+ return left.first < right.first;
4721
+ }
4722
+ friend constexpr CTRE_FORCE_INLINE bool operator>(const iterator & left, const iterator & right) noexcept {
4723
+ return left.first > right.first;
4724
+ }
4725
+ friend constexpr CTRE_FORCE_INLINE bool operator<=(const iterator & left, const iterator & right) noexcept {
4726
+ return left.first <= right.first;
4727
+ }
4728
+ friend constexpr CTRE_FORCE_INLINE bool operator>=(const iterator & left, const iterator & right) noexcept {
4729
+ return left.first >= right.first;
4730
+ }
4731
+ friend constexpr CTRE_FORCE_INLINE bool operator==(const iterator & left, end_iterator) noexcept {
4732
+ return left.first == left.last;
4733
+ }
4734
+ friend constexpr CTRE_FORCE_INLINE bool operator==(end_iterator, const iterator & right) noexcept {
4735
+ return right.first == right.last;
4736
+ }
4737
+ friend constexpr CTRE_FORCE_INLINE bool operator!=(const iterator & left, end_iterator) noexcept {
4738
+ return left.first != left.last;
4739
+ }
4740
+ friend constexpr CTRE_FORCE_INLINE bool operator!=(end_iterator, const iterator & right) noexcept {
4741
+ return right.first == right.last;
4742
+ }
4743
+ };
4744
+
4745
+ iterator everything;
4746
+
4747
+ constexpr CTRE_FORCE_INLINE multi_subject_range(First f, Last l) noexcept: everything{f,l} { }
4748
+
4749
+ constexpr CTRE_FORCE_INLINE auto begin() const noexcept {
4750
+ return everything;
4751
+ }
4752
+ constexpr CTRE_FORCE_INLINE auto end() const noexcept {
4753
+ return end_iterator{};
4754
+ }
4755
+ };
4756
+
4757
+ // this is not regex range!
4758
+ template <typename... Ts> constexpr bool is_range<multi_subject_range<Ts...>> = true;
4759
+
4670
4760
}
4671
4761
4672
4762
#if __cpp_lib_ranges >= 201911
@@ -4681,9 +4771,6 @@ namespace std::ranges {
4681
4771
#endif
4682
4772
4683
4773
#include <string_view>
4684
- #if __cpp_lib_ranges >= 201911
4685
- #include <ranges>
4686
- #endif
4687
4774
4688
4775
namespace ctre {
4689
4776
@@ -4824,6 +4911,9 @@ template <typename RE, typename Method, typename Modifier> struct regular_expres
4824
4911
template <typename ResultIterator, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec_with_result_iterator(IteratorBegin begin, IteratorEnd end) noexcept {
4825
4912
return Method::template exec<Modifier, ResultIterator>(begin, end, RE{});
4826
4913
}
4914
+ template <typename Range> constexpr CTRE_FORCE_INLINE static auto multi_exec(Range && range) noexcept {
4915
+ return multi_subject_range<decltype(range.begin()), decltype(range.end()), regular_expression>{range.begin(), range.end()};
4916
+ }
4827
4917
constexpr CTRE_FORCE_INLINE static auto exec() noexcept {
4828
4918
return Method::template exec();
4829
4919
}
@@ -4927,14 +5017,9 @@ template <typename Range, typename RE, typename Modifier> constexpr auto operato
4927
5017
4928
5018
template <typename Range, typename RE, typename Modifier> constexpr auto operator|(Range && range, regular_expression<RE, iterator_method, Modifier> re) noexcept = delete;
4929
5019
4930
- // range filter style API support for tokenize/range/split operations
4931
- #if __cpp_lib_ranges >= 201911
4932
5020
template <typename Range, typename RE, typename Method, typename Modifier> constexpr auto operator|(Range && range, regular_expression<RE, Method, Modifier> re) noexcept {
4933
- return std::forward<Range>(range) | std::ranges::views::filter([](const decltype(*range.begin()) & item) -> bool{
4934
- return regular_expression<RE, Method, Modifier>{}.exec(item);
4935
- });
5021
+ return re.multi_exec(std::forward<Range>(range));
4936
5022
}
4937
- #endif
4938
5023
4939
5024
#if CTRE_CNTTP_COMPILER_CHECK
4940
5025
#define CTRE_REGEX_INPUT_TYPE ctll::fixed_string
0 commit comments