| 894 | range_rsplits(string_type haystack, matcher_type needle) noexcept : matcher_(needle), haystack_(haystack) {} |
| 895 | |
| 896 | class iterator { |
| 897 | char const *start_; // Start of haystack (immutable) |
| 898 | char const *end_; // Current end position (moves backward) |
| 899 | size_type match_length_; // Length of current segment |
| 900 | matcher_type matcher_; |
| 901 | |
| 902 | public: |
| 903 | using iterator_category = std::forward_iterator_tag; |
| 904 | using difference_type = std::ptrdiff_t; |
| 905 | using value_type = string_view_type; |
| 906 | using pointer = string_view_type; // Needed for compatibility with STL container constructors. |
| 907 | using reference = string_view_type; // Needed for compatibility with STL container constructors. |
| 908 | |
| 909 | iterator(string_view_type haystack, matcher_type matcher) noexcept |
| 910 | : start_(haystack.data()), end_(haystack.data() + haystack.size()), match_length_(0), matcher_(matcher) { |
| 911 | auto position = matcher_(haystack); |
| 912 | match_length_ = |
| 913 | position != string_type::npos ? haystack.size() - position - matcher_.needle_length() : haystack.size(); |
| 914 | } |
| 915 | |
| 916 | iterator(string_view_type, matcher_type matcher, end_sentinel_type) noexcept |
| 917 | : start_(reinterpret_cast<char const *>(1)), end_(nullptr), match_length_(0), matcher_(matcher) {} |
| 918 | |
| 919 | pointer operator->() const noexcept = delete; |
| 920 | value_type operator*() const noexcept { return string_view_type(end_ - match_length_, match_length_); } |
| 921 | |
| 922 | iterator &operator++() noexcept { |
| 923 | end_ -= match_length_; |
| 924 | if (end_ < start_) return *this; |
| 925 | // If we were at the start (yielded final empty segment), signal termination |
| 926 | if (end_ == start_) { |
| 927 | end_ = nullptr; |
| 928 | start_ = reinterpret_cast<char const *>(1); |
| 929 | return *this; |
| 930 | } |
| 931 | // Skip delimiter |
| 932 | end_ -= matcher_.needle_length(); |
| 933 | if (end_ < start_) { |
| 934 | match_length_ = 0; |
| 935 | return *this; |
| 936 | } |
| 937 | // Find next delimiter (searching backwards) |
| 938 | string_view_type remaining(start_, static_cast<size_type>(end_ - start_)); |
| 939 | auto position = matcher_(remaining); |
| 940 | match_length_ = position != string_type::npos ? remaining.size() - position - matcher_.needle_length() |
| 941 | : remaining.size(); |
| 942 | return *this; |
| 943 | } |
| 944 | |
| 945 | iterator operator++(int) noexcept { |
| 946 | iterator temp = *this; |
| 947 | ++(*this); |
| 948 | return temp; |
| 949 | } |
| 950 | |
| 951 | bool operator!=(iterator const &other) const noexcept { return end_ != other.end_; } |
| 952 | bool operator==(iterator const &other) const noexcept { return end_ == other.end_; } |
| 953 | bool operator!=(end_sentinel_type) const noexcept { return end_ >= start_; } |
nothing calls this directly
no test coverage detected
searching dependent graphs…