VCCC  2024.05
VisualCamp Common C++ library
split_view.hpp
Go to the documentation of this file.
1 //
2 // Created by yonggyulee on 2/3/24.
3 //
4 
5 #ifndef VCCC_RANGES_VIEWS_SPLIT_VIEW_HPP
6 #define VCCC_RANGES_VIEWS_SPLIT_VIEW_HPP
7 
8 #include <type_traits>
9 #include <utility>
10 
19 #include "vccc/__ranges/begin.hpp"
20 #include "vccc/__ranges/empty.hpp"
21 #include "vccc/__ranges/end.hpp"
27 #include "vccc/__ranges/view.hpp"
35 
36 namespace vccc {
37 namespace ranges {
38 
41 
46 template<typename V, typename Pattern>
47 class split_view : public view_interface<split_view<V, Pattern>> {
49  struct check_range : std::false_type {};
50  template<typename R>
51  struct check_range<R, true>
52  : conjunction<
53  constructible_from<V, views::all_t<R>>,
54  constructible_from<Pattern, single_view<range_value_t<R>>>
55  > {};
56 
57  public:
58  static_assert(view<V>::value, "Constraints not satisfied");
59  static_assert(view<Pattern>::value, "Constraints not satisfied");
60  static_assert(indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, equal_to>::value, "Constraints not satisfied");
61 
62  class sentinel;
63  class iterator;
64  friend class sentinel;
65  friend class iterator;
66 
67  class iterator {
68  public:
69  friend class sentinel;
70 
75 #if __cplusplus < 202002L
76  using pointer = void;
78 #endif
79 
80  iterator() = default;
81 
83  : parent_(vccc::addressof(parent)), cur_(std::move(current)), next_(std::move(next)), trailing_empty_(false) {}
84 
85  constexpr const iterator_t<V> base() const {
86  return cur_;
87  }
88 
89  // TODO: inspect
90  constexpr value_type operator*() const {
91  return {cur_, next_.begin()};
92  }
93 
94  constexpr iterator& operator++() {
95  const auto last = ranges::end(parent_->base_);
96  cur_ = next_.begin();
97  if (cur_ != last) {
98  cur_ = next_.end();
99  if (cur_ == last) {
100  trailing_empty_ = true;
101  next_ = {cur_, cur_};
102  } else {
103  next_ = parent_->find_next(cur_);
104  }
105  } else {
106  trailing_empty_ = false;
107  }
108 
109  return *this;
110  }
111 
112  constexpr iterator operator++(int) {
113  auto tmp = *this;
114  ++*this;
115  return tmp;
116  }
117 
118  friend constexpr bool operator==(const iterator& x, const iterator& y) {
119  return x.cur_ == y.cur_ and x.trailing_empty_ == y.trailing_empty_;
120  }
121 
122  friend constexpr bool operator!=(const iterator& x, const iterator& y) {
123  return !(x == y);
124  }
125 
126  private:
127  split_view* parent_ = nullptr;
128  iterator_t<V> cur_{};
129  subrange<iterator_t<V>> next_{};
130  bool trailing_empty_ = false;
131  };
132 
133  class sentinel {
134  public:
135  sentinel() = default;
136 
137  constexpr explicit sentinel(split_view& parent)
138  : end_(ranges::end(parent.base_)) {}
139 
140  friend constexpr bool operator==(const iterator& x, const sentinel& y) {
141  using namespace vccc::rel_ops;
142  return x.cur_ == y.end_ && !x.trailing_empty_;
143  }
144 
145  friend constexpr bool operator!=(const iterator& x, const sentinel& y) {
146  return !(x == y);
147  }
148 
149  friend constexpr bool operator==(const sentinel& y, const iterator& x) {
150  return x == y;
151  }
152 
153  friend constexpr bool operator!=(const sentinel& y, const iterator& x) {
154  return !(x == y);
155  }
156 
157  private:
158  sentinel_t<V> end_ = sentinel_t<V>();
159  };
160 
161  split_view() = default;
162 
163  constexpr explicit split_view(V base, Pattern pattern)
164  : base_(std::move(base)), pattern_(std::move(pattern)) {}
165 
167  constexpr explicit split_view(R&& r, range_value_t<R> e)
168  : base_(views::all(std::forward<R>(r)))
169  , pattern_(single_view<remove_cvref_t<decltype(std::move(e))>>{std::move(e)}) {}
170 
172  constexpr V base() const& {
173  return base_;
174  }
175 
176  constexpr V base() && {
177  return std::move(base_);
178  }
179 
180  constexpr iterator begin() {
181  auto first = ranges::begin(base_);
182  if (!cached_begin_.has_value())
183  cached_begin_.emplace(find_next(first));
184  return {*this, first, *cached_begin_};
185  }
186 
188  constexpr iterator end() {
189  return iterator{*this, ranges::end(base_), {}};
190  }
191 
193  constexpr sentinel end() {
194  return sentinel{*this};
195  }
196 
198  using I = iterator_t<V>;
199 
200  auto last = ranges::end(base_);
201  auto b_e = ranges::search(subrange<I>(it, last), pattern_);
202  auto b = b_e.begin();
203  auto e = b_e.end();
204 
205  if (b != last && ranges::empty(pattern_)) {
206  ++b;
207  ++e;
208  }
209 
210  return {std::move(b), std::move(e)};
211  }
212 
213  private:
214  V base_{};
215  Pattern pattern_{};
216  non_propagating_cache<subrange<iterator_t<V>>> cached_begin_{};
217 };
218 
219 namespace detail {
220 
222 struct same_with_range_value : std::false_type {};
223 template<typename R, typename POV>
224 struct same_with_range_value<R, POV, true> : same_as<range_value_t<R>, remove_cvref_t<POV>> {};
225 
227 constexpr auto make_split_view_impl(R&& r, range_value_t<R> patteern, std::true_type /* range_value_t */) {
228  return split_view<views::all_t<R>, single_view<range_value_t<R>>>(std::forward<R>(r), std::move(patteern));
229 }
230 
231 template<typename R, typename P>
232 constexpr auto make_split_view_impl(R&& r, P&& pattern, std::false_type /* range_value_t */) {
233  return split_view<views::all_t<R>, views::all_t<P>>(std::forward<R>(r), std::forward<P>(pattern));
234 }
235 
236 } // namespace detail
237 
238 template<typename R, typename P>
239 constexpr auto make_split_view(R&& r, P&& pattern) {
240  return detail::make_split_view_impl(
241  std::forward<R>(r), std::forward<P>(pattern), detail::same_with_range_value<R, P>{});
242 }
243 
244 #if __cplusplus >= 201703L
245 
246 template<typename R, typename P>
247 split_view(R&&, P&&)
248  -> split_view<
250  std::conditional_t<
252  single_view<range_value_t<R>>,
254  >
255  >;
256 
257 #endif
258 
260 
261 } // namespace ranges
262 } // namespace vccc
263 
264 #endif // VCCC_RANGES_VIEWS_SPLIT_VIEW_HPP
#define VCCC_ADDRESSOF_CONSTEXPR
Definition: addressof.hpp:14
Definition: single.hpp:38
Definition: split_view.hpp:67
constexpr const iterator_t< V > base() const
Definition: split_view.hpp:85
VCCC_ADDRESSOF_CONSTEXPR iterator(split_view &parent, iterator_t< V > current, subrange< iterator_t< V >> next)
Definition: split_view.hpp:82
void pointer
Definition: split_view.hpp:76
constexpr friend bool operator!=(const iterator &x, const iterator &y)
Definition: split_view.hpp:122
constexpr value_type operator*() const
Definition: split_view.hpp:90
constexpr friend bool operator==(const iterator &x, const iterator &y)
Definition: split_view.hpp:118
input_iterator_tag iterator_category
Definition: split_view.hpp:72
forward_iterator_tag iterator_concept
Definition: split_view.hpp:71
subrange< iterator_t< V > > value_type
Definition: split_view.hpp:73
constexpr iterator operator++(int)
Definition: split_view.hpp:112
range_difference_t< V > difference_type
Definition: split_view.hpp:74
constexpr iterator & operator++()
Definition: split_view.hpp:94
Definition: split_view.hpp:133
constexpr sentinel(split_view &parent)
Definition: split_view.hpp:137
constexpr friend bool operator!=(const iterator &x, const sentinel &y)
Definition: split_view.hpp:145
constexpr friend bool operator==(const iterator &x, const sentinel &y)
Definition: split_view.hpp:140
constexpr friend bool operator==(const sentinel &y, const iterator &x)
Definition: split_view.hpp:149
constexpr friend bool operator!=(const sentinel &y, const iterator &x)
Definition: split_view.hpp:153
split_view takes a view and a delimiter, and splits the view into subranges on the delimiter.
Definition: split_view.hpp:47
constexpr V base() const &
Definition: split_view.hpp:172
constexpr iterator end()
Definition: split_view.hpp:188
constexpr split_view(V base, Pattern pattern)
Definition: split_view.hpp:163
constexpr sentinel end()
Definition: split_view.hpp:193
constexpr V base() &&
Definition: split_view.hpp:176
constexpr subrange< iterator_t< V > > find_next(iterator_t< V > it)
Definition: split_view.hpp:197
constexpr iterator begin()
Definition: split_view.hpp:180
constexpr split_view(R &&r, range_value_t< R > e)
Definition: split_view.hpp:167
constexpr S end() const
Definition: subrange.hpp:213
constexpr I begin() const
Definition: subrange.hpp:204
helper class template for defining a view, using the curiously recurring template pattern
Definition: view_interface.hpp:78
constexpr VCCC_INLINE_OR_STATIC detail::search_niebloid search
Definition: search.hpp:87
constexpr VCCC_INLINE_OR_STATIC detail::next_niebloid next
Definition: next.hpp:65
std::forward_iterator_tag forward_iterator_tag
Definition: iterator_tag.hpp:17
std::input_iterator_tag input_iterator_tag
Definition: iterator_tag.hpp:15
constexpr T e
the mathematical constant
Definition: constants.hpp:37
std::enable_if_t< std::is_object< T >::value, T * > addressof(T &t) noexcept
Definition: addressof.hpp:33
constexpr VCCC_INLINE_OR_STATIC detail::empty_niebloid empty
checks whether a range is empty
Definition: empty.hpp:116
constexpr auto make_split_view(R &&r, P &&pattern)
Definition: split_view.hpp:239
typename sentinel< R >::type sentinel_t
Definition: sentinel_t.hpp:29
typename ranges::iterator< T >::type iterator_t
Definition: iterator_t.hpp:32
constexpr VCCC_INLINE_OR_STATIC detail::begin_niebloid begin
returns an iterator to the beginning of a range
Definition: begin.hpp:116
typename detail::all_t_impl< R >::type all_t
Calculates the suitable view type of a viewable_range type.
Definition: all.hpp:107
constexpr VCCC_INLINE_OR_STATIC detail::end_niebloid end
returns a sentinel indicating the end of a range
Definition: end.hpp:120
typename range_difference< R >::type range_difference_t
Used to obtain the difference type of the iterator type of range type R.
Definition: range_difference_t.hpp:41
constexpr VCCC_INLINE_OR_STATIC detail::all_adaptor_closure all
a view that includes all elements of a range
Definition: all.hpp:82
typename range_value< R >::type range_value_t
Used to obtain the value type of the iterator type of range type R.
Definition: range_value_t.hpp:42
typename remove_cvref< T >::type remove_cvref_t
Definition: remove_cvref.hpp:24
Definition: matrix.hpp:495
Definition: cxx20_rel_ops.hpp:17
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 0 > first
Definition: key_value.hpp:34
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
Definition: conjunction.hpp:22
specifies that the values referenced by two indirectly_readable types can be compared
Definition: indirectly_comparable.hpp:49
Definition: equal_to.hpp:20
specifies that a range is a view, that is, it has constant time copy/move/assignment
Definition: view.hpp:31