split_when.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_VIEW_SPLIT_WHEN_HPP
  14. #define RANGES_V3_VIEW_SPLIT_WHEN_HPP
  15. #include <type_traits>
  16. #include <utility>
  17. #include <meta/meta.hpp>
  18. #include <range/v3/range_fwd.hpp>
  19. #include <range/v3/algorithm/find_if_not.hpp>
  20. #include <range/v3/functional/bind_back.hpp>
  21. #include <range/v3/functional/invoke.hpp>
  22. #include <range/v3/iterator/default_sentinel.hpp>
  23. #include <range/v3/iterator/operations.hpp>
  24. #include <range/v3/range/access.hpp>
  25. #include <range/v3/range/concepts.hpp>
  26. #include <range/v3/range/traits.hpp>
  27. #include <range/v3/utility/static_const.hpp>
  28. #include <range/v3/view/all.hpp>
  29. #include <range/v3/view/facade.hpp>
  30. #include <range/v3/view/indirect.hpp>
  31. #include <range/v3/view/iota.hpp>
  32. #include <range/v3/view/take_while.hpp>
  33. #include <range/v3/view/view.hpp>
  34. #include <range/v3/detail/prologue.hpp>
  35. namespace ranges
  36. {
  37. /// \addtogroup group-views
  38. /// @{
  39. template<typename Rng, typename Fun>
  40. struct split_when_view
  41. : view_facade<split_when_view<Rng, Fun>,
  42. is_finite<Rng>::value ? finite : range_cardinality<Rng>::value>
  43. {
  44. private:
  45. friend range_access;
  46. Rng rng_;
  47. semiregular_box_t<Fun> fun_;
  48. template<bool IsConst>
  49. struct cursor
  50. {
  51. private:
  52. friend range_access;
  53. friend split_when_view;
  54. friend struct cursor<!IsConst>;
  55. bool zero_;
  56. using CRng = meta::const_if_c<IsConst, Rng>;
  57. iterator_t<CRng> cur_;
  58. sentinel_t<CRng> last_;
  59. using fun_ref_t = semiregular_box_ref_or_val_t<Fun, IsConst>;
  60. fun_ref_t fun_;
  61. struct search_pred
  62. {
  63. bool zero_;
  64. iterator_t<CRng> first_;
  65. sentinel_t<CRng> last_;
  66. fun_ref_t fun_;
  67. bool operator()(iterator_t<CRng> cur) const
  68. {
  69. return (zero_ && cur == first_) ||
  70. (cur != last_ && !invoke(fun_, cur, last_).first);
  71. }
  72. };
  73. using reference_ =
  74. indirect_view<take_while_view<iota_view<iterator_t<CRng>>, search_pred>>;
  75. reference_ read() const
  76. {
  77. return reference_{{views::iota(cur_), {zero_, cur_, last_, fun_}}};
  78. }
  79. void next()
  80. {
  81. RANGES_EXPECT(cur_ != last_);
  82. // If the last match consumed zero elements, bump the position.
  83. if(zero_)
  84. {
  85. zero_ = false;
  86. ++cur_;
  87. }
  88. for(; cur_ != last_; ++cur_)
  89. {
  90. auto p = invoke(fun_, cur_, last_);
  91. if(p.first)
  92. {
  93. zero_ = (cur_ == p.second);
  94. cur_ = p.second;
  95. return;
  96. }
  97. }
  98. }
  99. bool equal(default_sentinel_t) const
  100. {
  101. return cur_ == last_;
  102. }
  103. bool equal(cursor const & that) const
  104. {
  105. return cur_ == that.cur_;
  106. }
  107. cursor(fun_ref_t fun, iterator_t<CRng> first, sentinel_t<CRng> last)
  108. : cur_(first)
  109. , last_(last)
  110. , fun_(fun)
  111. {
  112. // For skipping an initial zero-length match
  113. auto p = invoke(fun, first, last);
  114. zero_ = p.first && first == p.second;
  115. }
  116. public:
  117. cursor() = default;
  118. template(bool Other)(
  119. requires IsConst AND CPP_NOT(Other)) //
  120. cursor(cursor<Other> that)
  121. : cursor{std::move(that.cur_), std::move(that.last_), std::move(that.fun_)}
  122. {}
  123. };
  124. cursor<false> begin_cursor()
  125. {
  126. return {fun_, ranges::begin(rng_), ranges::end(rng_)};
  127. }
  128. template(bool Const = true)(
  129. requires Const AND range<meta::const_if_c<Const, Rng>> AND
  130. invocable<Fun const &, iterator_t<meta::const_if_c<Const, Rng>>,
  131. sentinel_t<meta::const_if_c<Const, Rng>>>)
  132. cursor<Const> begin_cursor() const
  133. {
  134. return {fun_, ranges::begin(rng_), ranges::end(rng_)};
  135. }
  136. public:
  137. split_when_view() = default;
  138. split_when_view(Rng rng, Fun fun)
  139. : rng_(std::move(rng))
  140. , fun_(std::move(fun))
  141. {}
  142. };
  143. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  144. template(typename Rng, typename Fun)(
  145. requires copy_constructible<Fun>)
  146. split_when_view(Rng &&, Fun)
  147. -> split_when_view<views::all_t<Rng>, Fun>;
  148. #endif
  149. namespace views
  150. {
  151. struct split_when_base_fn
  152. {
  153. private:
  154. template<typename Pred>
  155. struct predicate_pred_
  156. {
  157. semiregular_box_t<Pred> pred_;
  158. template(typename I, typename S)(
  159. requires sentinel_for<S, I>)
  160. std::pair<bool, I> operator()(I cur, S last) const
  161. {
  162. auto where = ranges::find_if_not(cur, last, std::ref(pred_));
  163. return {cur != where, where};
  164. }
  165. };
  166. public:
  167. template(typename Rng, typename Fun)(
  168. requires viewable_range<Rng> AND forward_range<Rng> AND
  169. invocable<Fun &, iterator_t<Rng>, sentinel_t<Rng>> AND
  170. invocable<Fun &, iterator_t<Rng>, iterator_t<Rng>> AND
  171. copy_constructible<Fun> AND
  172. convertible_to<
  173. invoke_result_t<Fun &, iterator_t<Rng>, sentinel_t<Rng>>,
  174. std::pair<bool, iterator_t<Rng>>>)
  175. split_when_view<all_t<Rng>, Fun> operator()(Rng && rng, Fun fun) const //
  176. {
  177. return {all(static_cast<Rng &&>(rng)), std::move(fun)};
  178. }
  179. template(typename Rng, typename Fun)(
  180. requires viewable_range<Rng> AND forward_range<Rng> AND
  181. predicate<Fun const &, range_reference_t<Rng>> AND
  182. copy_constructible<Fun>)
  183. split_when_view<all_t<Rng>, predicate_pred_<Fun>> //
  184. operator()(Rng && rng, Fun fun) const
  185. {
  186. return {all(static_cast<Rng &&>(rng)),
  187. predicate_pred_<Fun>{std::move(fun)}};
  188. }
  189. };
  190. struct split_when_fn : split_when_base_fn
  191. {
  192. using split_when_base_fn::operator();
  193. template<typename T>
  194. constexpr auto operator()(T && t) const
  195. {
  196. return make_view_closure(
  197. bind_back(split_when_base_fn{}, static_cast<T &&>(t)));
  198. }
  199. };
  200. /// \relates split_when_fn
  201. /// \ingroup group-views
  202. RANGES_INLINE_VARIABLE(split_when_fn, split_when)
  203. } // namespace views
  204. /// @}
  205. } // namespace ranges
  206. #include <range/v3/detail/epilogue.hpp>
  207. #include <range/v3/detail/satisfy_boost_range.hpp>
  208. RANGES_SATISFY_BOOST_RANGE(::ranges::split_when_view)
  209. #endif