Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:09:58

0001 /// \file
0002 // Range v3 library
0003 //
0004 //  Copyright Eric Niebler 2013-present
0005 //
0006 //  Use, modification and distribution is subject to the
0007 //  Boost Software License, Version 1.0. (See accompanying
0008 //  file LICENSE_1_0.txt or copy at
0009 //  http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // Project home: https://github.com/ericniebler/range-v3
0012 //
0013 
0014 #ifndef RANGES_V3_VIEW_SPLIT_WHEN_HPP
0015 #define RANGES_V3_VIEW_SPLIT_WHEN_HPP
0016 
0017 #include <type_traits>
0018 #include <utility>
0019 
0020 #include <meta/meta.hpp>
0021 
0022 #include <range/v3/range_fwd.hpp>
0023 
0024 #include <range/v3/algorithm/find_if_not.hpp>
0025 #include <range/v3/functional/bind_back.hpp>
0026 #include <range/v3/functional/invoke.hpp>
0027 #include <range/v3/iterator/default_sentinel.hpp>
0028 #include <range/v3/iterator/operations.hpp>
0029 #include <range/v3/range/access.hpp>
0030 #include <range/v3/range/concepts.hpp>
0031 #include <range/v3/range/traits.hpp>
0032 #include <range/v3/utility/static_const.hpp>
0033 #include <range/v3/view/all.hpp>
0034 #include <range/v3/view/facade.hpp>
0035 #include <range/v3/view/indirect.hpp>
0036 #include <range/v3/view/iota.hpp>
0037 #include <range/v3/view/take_while.hpp>
0038 #include <range/v3/view/view.hpp>
0039 
0040 #include <range/v3/detail/prologue.hpp>
0041 
0042 namespace ranges
0043 {
0044     /// \addtogroup group-views
0045     /// @{
0046 
0047     template<typename Rng, typename Fun>
0048     struct split_when_view
0049       : view_facade<split_when_view<Rng, Fun>,
0050                     is_finite<Rng>::value ? finite : range_cardinality<Rng>::value>
0051     {
0052     private:
0053         friend range_access;
0054         Rng rng_;
0055         semiregular_box_t<Fun> fun_;
0056 
0057         template<bool IsConst>
0058         struct cursor
0059         {
0060         private:
0061             friend range_access;
0062             friend split_when_view;
0063             friend struct cursor<!IsConst>;
0064             bool zero_;
0065             using CRng = meta::const_if_c<IsConst, Rng>;
0066             iterator_t<CRng> cur_;
0067             sentinel_t<CRng> last_;
0068             using fun_ref_t = semiregular_box_ref_or_val_t<Fun, IsConst>;
0069             fun_ref_t fun_;
0070 
0071             struct search_pred
0072             {
0073                 bool zero_;
0074                 iterator_t<CRng> first_;
0075                 sentinel_t<CRng> last_;
0076                 fun_ref_t fun_;
0077                 bool operator()(iterator_t<CRng> cur) const
0078                 {
0079                     return (zero_ && cur == first_) ||
0080                            (cur != last_ && !invoke(fun_, cur, last_).first);
0081                 }
0082             };
0083             using reference_ =
0084                 indirect_view<take_while_view<iota_view<iterator_t<CRng>>, search_pred>>;
0085             reference_ read() const
0086             {
0087                 return reference_{{views::iota(cur_), {zero_, cur_, last_, fun_}}};
0088             }
0089             void next()
0090             {
0091                 RANGES_EXPECT(cur_ != last_);
0092                 // If the last match consumed zero elements, bump the position.
0093                 if(zero_)
0094                 {
0095                     zero_ = false;
0096                     ++cur_;
0097                 }
0098                 for(; cur_ != last_; ++cur_)
0099                 {
0100                     auto p = invoke(fun_, cur_, last_);
0101                     if(p.first)
0102                     {
0103                         zero_ = (cur_ == p.second);
0104                         cur_ = p.second;
0105                         return;
0106                     }
0107                 }
0108             }
0109             bool equal(default_sentinel_t) const
0110             {
0111                 return cur_ == last_;
0112             }
0113             bool equal(cursor const & that) const
0114             {
0115                 return cur_ == that.cur_;
0116             }
0117             cursor(fun_ref_t fun, iterator_t<CRng> first, sentinel_t<CRng> last)
0118               : cur_(first)
0119               , last_(last)
0120               , fun_(fun)
0121             {
0122                 // For skipping an initial zero-length match
0123                 auto p = invoke(fun, first, last);
0124                 zero_ = p.first && first == p.second;
0125             }
0126 
0127         public:
0128             cursor() = default;
0129             template(bool Other)(
0130                 requires IsConst AND CPP_NOT(Other)) //
0131             cursor(cursor<Other> that)
0132               : cursor{std::move(that.cur_), std::move(that.last_), std::move(that.fun_)}
0133             {}
0134         };
0135         cursor<false> begin_cursor()
0136         {
0137             return {fun_, ranges::begin(rng_), ranges::end(rng_)};
0138         }
0139         template(bool Const = true)(
0140             requires Const AND range<meta::const_if_c<Const, Rng>> AND
0141                 invocable<Fun const &, iterator_t<meta::const_if_c<Const, Rng>>,
0142                           sentinel_t<meta::const_if_c<Const, Rng>>>)
0143         cursor<Const> begin_cursor() const
0144         {
0145             return {fun_, ranges::begin(rng_), ranges::end(rng_)};
0146         }
0147 
0148     public:
0149         split_when_view() = default;
0150         split_when_view(Rng rng, Fun fun)
0151           : rng_(std::move(rng))
0152           , fun_(std::move(fun))
0153         {}
0154     };
0155 
0156 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0157     template(typename Rng, typename Fun)(
0158         requires copy_constructible<Fun>)
0159     split_when_view(Rng &&, Fun)
0160         -> split_when_view<views::all_t<Rng>, Fun>;
0161 #endif
0162 
0163     namespace views
0164     {
0165         struct split_when_base_fn
0166         {
0167         private:
0168             template<typename Pred>
0169             struct predicate_pred_
0170             {
0171                 semiregular_box_t<Pred> pred_;
0172 
0173                 template(typename I, typename S)(
0174                     requires sentinel_for<S, I>)
0175                 std::pair<bool, I> operator()(I cur, S last) const
0176                 {
0177                     auto where = ranges::find_if_not(cur, last, std::ref(pred_));
0178                     return {cur != where, where};
0179                 }
0180             };
0181 
0182         public:
0183             template(typename Rng, typename Fun)(
0184                 requires viewable_range<Rng> AND forward_range<Rng> AND
0185                     invocable<Fun &, iterator_t<Rng>, sentinel_t<Rng>> AND
0186                     invocable<Fun &, iterator_t<Rng>, iterator_t<Rng>> AND
0187                     copy_constructible<Fun> AND
0188                     convertible_to<
0189                         invoke_result_t<Fun &, iterator_t<Rng>, sentinel_t<Rng>>,
0190                         std::pair<bool, iterator_t<Rng>>>)
0191             split_when_view<all_t<Rng>, Fun> operator()(Rng && rng, Fun fun) const //
0192             {
0193                 return {all(static_cast<Rng &&>(rng)), std::move(fun)};
0194             }
0195             template(typename Rng, typename Fun)(
0196                 requires viewable_range<Rng> AND forward_range<Rng> AND
0197                     predicate<Fun const &, range_reference_t<Rng>> AND
0198                     copy_constructible<Fun>)
0199             split_when_view<all_t<Rng>, predicate_pred_<Fun>> //
0200             operator()(Rng && rng, Fun fun) const
0201             {
0202                 return {all(static_cast<Rng &&>(rng)),
0203                         predicate_pred_<Fun>{std::move(fun)}};
0204             }
0205         };
0206 
0207         struct split_when_fn : split_when_base_fn
0208         {
0209             using split_when_base_fn::operator();
0210 
0211             template<typename T>
0212             constexpr auto operator()(T && t) const
0213             {
0214                 return make_view_closure(
0215                     bind_back(split_when_base_fn{}, static_cast<T &&>(t)));
0216             }
0217         };
0218 
0219         /// \relates split_when_fn
0220         /// \ingroup group-views
0221         RANGES_INLINE_VARIABLE(split_when_fn, split_when)
0222     } // namespace views
0223     /// @}
0224 } // namespace ranges
0225 
0226 #include <range/v3/detail/epilogue.hpp>
0227 #include <range/v3/detail/satisfy_boost_range.hpp>
0228 RANGES_SATISFY_BOOST_RANGE(::ranges::split_when_view)
0229 
0230 #endif