/*============================================================================= Copyright (c) 2006 Eric Niebler Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #ifndef FUSION_SEGMENTED_ITERATOR_RANGE_EAN_05032006_1027 #define FUSION_SEGMENTED_ITERATOR_RANGE_EAN_05032006_1027 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace fusion { namespace detail { //////////////////////////////////////////////////////////////////////////// template struct reverse_cons; template struct reverse_cons, State> { typedef reverse_cons > reverse; typedef typename reverse::type type; static type call(cons const &cons, State const &state = State()) { return reverse::call(cons.cdr, fusion::make_cons(cons.car, state)); } }; template struct reverse_cons { typedef State type; static State const &call(nil const &, State const &state = State()) { return state; } }; //////////////////////////////////////////////////////////////////////////// // tags struct full_view {}; struct left_view {}; struct right_view {}; struct center_view {}; template struct segmented_view_tag; //////////////////////////////////////////////////////////////////////////// // a segmented view of that includes all elements either to the // right or the left of a segmented iterator. template struct segmented_view : sequence_base > { typedef segmented_view_tag fusion_tag; typedef fusion_sequence_tag tag; // this gets picked up by MPL typedef mpl::true_ is_view; typedef forward_traversal_tag category; explicit segmented_view(Cons1 const &cons) : cons(cons) {} typedef Cons1 cons_type; cons_type const &cons; }; // a segmented view that contains all the elements in between // two segmented iterators template struct segmented_view : sequence_base > { typedef segmented_view_tag fusion_tag; typedef fusion_sequence_tag tag; // this gets picked up by MPL typedef mpl::true_ is_view; typedef forward_traversal_tag category; segmented_view(Cons1 const &lcons, Cons2 const &rcons) : left_cons(lcons) , right_cons(rcons) {} typedef Cons1 left_cons_type; typedef Cons2 right_cons_type; left_cons_type const &left_cons; right_cons_type const &right_cons; }; //////////////////////////////////////////////////////////////////////////// // Used to transform a sequence of segments. The first segment is // bounded by RightCons, and the last segment is bounded by LeftCons // and all the others are passed through unchanged. template struct segments_transform { explicit segments_transform(RightCons const &cons_) : right_cons(cons_) , left_cons(cons_) {} segments_transform(RightCons const &right_cons_, LeftCons const &left_cons_) : right_cons(right_cons_) , left_cons(left_cons_) {} template struct result_; template struct result_ { typedef segmented_view type; }; template struct result_ { typedef segmented_view type; }; template struct result_ { typedef Second type; }; template struct result; template struct result : result_< typename remove_cv::type>::type , typename remove_cv::type>::type > {}; template segmented_view operator ()(right_view, Second &second) const { return segmented_view(this->right_cons); } template segmented_view operator ()(left_view, Second &second) const { return segmented_view(this->left_cons); } template Second &operator ()(full_view, Second &second) const { return second; } private: RightCons const &right_cons; LeftCons const &left_cons; }; } // namespace detail namespace extension { //////////////////////////////////////////////////////////////////////////// template struct is_segmented_impl > { template struct apply : mpl::true_ {}; }; //////////////////////////////////////////////////////////////////////////// template<> struct segments_impl > { template< typename Sequence , typename Cdr = typename Sequence::cons_type::cdr_type > struct apply { typedef typename Sequence::cons_type::car_type segmented_range; typedef typename result_of::size::type size; typedef typename mpl::prior::type size_minus_1; typedef detail::segments_transform tfx; typedef joint_view< single_view const , multiple_view const > mask; typedef transform_view type; static type call(Sequence &seq) { return type( mask( make_single_view(detail::right_view()) , make_multiple_view(detail::full_view()) ) , seq.cons.car , tfx(seq.cons.cdr) ); } }; template struct apply { typedef typename Sequence::cons_type::car_type segmented_range; typedef typename segmented_range::iterator_type begin; typedef typename segmented_range::sequence_non_ref_type sequence_type; typedef typename result_of::end::type end; typedef iterator_range range; typedef single_view type; static type call(Sequence &seq) { return type(range(seq.cons.car.where_, fusion::end(seq.cons.car.sequence))); } }; }; //////////////////////////////////////////////////////////////////////////// template<> struct segments_impl > { template< typename Sequence , typename Cdr = typename Sequence::cons_type::cdr_type > struct apply { typedef typename Sequence::cons_type::car_type right_segmented_range; typedef typename right_segmented_range::sequence_type sequence_type; typedef typename right_segmented_range::iterator_type iterator_type; typedef iterator_range< typename result_of::begin::type , typename result_of::next::type > segmented_range; typedef detail::segments_transform tfx; typedef typename result_of::size::type size; typedef typename mpl::prior::type size_minus_1; typedef joint_view< multiple_view const , single_view const > mask; typedef transform_view type; static type call(Sequence &seq) { return type( mask( make_multiple_view(detail::full_view()) , make_single_view(detail::left_view()) ) , segmented_range(fusion::begin(seq.cons.car.sequence), fusion::next(seq.cons.car.where_)) , tfx(seq.cons.cdr) ); } }; template struct apply { typedef typename Sequence::cons_type::car_type segmented_range; typedef typename segmented_range::sequence_non_ref_type sequence_type; typedef typename result_of::begin::type begin; typedef typename segmented_range::iterator_type end; typedef iterator_range range; typedef single_view type; static type call(Sequence &seq) { return type(range(fusion::begin(seq.cons.car.sequence), seq.cons.car.where_)); } }; }; //////////////////////////////////////////////////////////////////////////// template<> struct segments_impl > { template struct apply { typedef typename Sequence::right_cons_type right_cons_type; typedef typename Sequence::left_cons_type left_cons_type; typedef typename right_cons_type::car_type right_segmented_range; typedef typename left_cons_type::car_type left_segmented_range; typedef iterator_range< typename result_of::begin::type , typename result_of::next::type>::type > segmented_range; typedef typename mpl::minus< typename result_of::size::type , mpl::int_<2> >::type size_minus_2; BOOST_MPL_ASSERT_RELATION(0, <=, size_minus_2::value); typedef detail::segments_transform< typename left_cons_type::cdr_type , typename right_cons_type::cdr_type > tfx; typedef joint_view< multiple_view const , single_view const > left_mask; typedef joint_view< single_view const , left_mask const > mask; typedef transform_view type; static type call(Sequence &seq) { left_mask lmask( make_multiple_view(detail::full_view()) , make_single_view(detail::left_view()) ); return type( mask(make_single_view(detail::right_view()), lmask) , segmented_range(fusion::begin(seq.left_cons.car), fusion::next(fusion::begin(seq.right_cons.car))) , tfx(seq.left_cons.cdr, seq.right_cons.cdr) ); } }; }; } // specialize iterator_range for use with segmented iterators, so that // it presents a segmented view of the range. template struct iterator_range; template struct iterator_range, segmented_iterator > : sequence_base, segmented_iterator > > { typedef typename convert_iterator >::type begin_type; typedef typename convert_iterator >::type end_type; typedef typename detail::reverse_cons::type begin_cons_type; typedef typename detail::reverse_cons::type end_cons_type; typedef iterator_range_tag fusion_tag; typedef fusion_sequence_tag tag; // this gets picked up by MPL typedef typename traits::category_of::type category; typedef typename result_of::distance::type size; typedef mpl::true_ is_view; iterator_range(segmented_iterator const& first_, segmented_iterator const& last_) : first(convert_iterator >::call(first_)) , last(convert_iterator >::call(last_)) , first_cons(detail::reverse_cons::call(first_.cons())) , last_cons(detail::reverse_cons::call(last_.cons())) {} begin_type first; end_type last; begin_cons_type first_cons; end_cons_type last_cons; }; namespace detail { template struct same_segment : mpl::false_ {}; template struct same_segment, cons > : mpl::and_< traits::is_segmented , is_same > {}; //////////////////////////////////////////////////////////////////////////// template struct segments_gen; //////////////////////////////////////////////////////////////////////////// template struct segments_gen2 { typedef segments_gen gen; typedef typename gen::type type; static type call(Cons1 const &cons1, Cons2 const &cons2) { return gen::call(cons1.cdr, cons2.cdr); } }; template struct segments_gen2 { typedef segmented_view view; typedef typename result_of::segments::type type; static type call(Cons1 const &cons1, Cons2 const &cons2) { view v(cons1, cons2); return fusion::segments(v); } }; template struct segments_gen2, cons, false> { typedef iterator_range< typename Car1::iterator_type , typename Car2::iterator_type > range; typedef single_view type; static type call(cons const &cons1, cons const &cons2) { return type(range(cons1.car.where_, cons2.car.where_)); } }; //////////////////////////////////////////////////////////////////////////// template struct segments_gen : segments_gen2::value> {}; template struct segments_gen, nil> { typedef segmented_view > view; typedef typename result_of::segments::type type; static type call(cons const &cons, nil const &) { view v(cons); return fusion::segments(v); } }; template<> struct segments_gen { typedef nil type; static type call(nil const &, nil const &) { return nil(); } }; } // namespace detail namespace extension { template struct is_segmented_impl; // An iterator_range of segmented_iterators is segmented template<> struct is_segmented_impl { template struct is_segmented_iterator : mpl::false_ {}; template struct is_segmented_iterator > : mpl::true_ {}; template struct apply : mpl::and_< is_segmented_iterator , is_segmented_iterator > {}; }; template struct segments_impl; template<> struct segments_impl { template struct apply { typedef typename Sequence::begin_cons_type begin_cons; typedef typename Sequence::end_cons_type end_cons; typedef detail::segments_gen gen; typedef typename gen::type type; static type call(Sequence &sequence) { return gen::call(sequence.first_cons, sequence.last_cons); } }; }; } }} #endif