////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2025-2026. Distributed under 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) // // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_CONTAINER_EXPERIMENTAL_SEGMENTED_REVERSE_COPY_HPP #define BOOST_CONTAINER_EXPERIMENTAL_SEGMENTED_REVERSE_COPY_HPP #ifndef BOOST_CONFIG_HPP # include #endif #if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif #include #include #include #include namespace boost { namespace container { template OutIter segmented_reverse_copy(BidirIter first, BidirIter last, OutIter result); namespace detail_algo { ////////////////////////////////////////////////////////////////////////////// // Bounded destination helper: reverse-copies from [first, last) into // [dst_first, dst_last), reading backward from last toward first, // writing forward into dst. // Returns segduo where .first is the updated source // read position (last, moved backward) and .second is the updated dst. // When dst_last is unreachable_sentinel_t the destination-full check // is optimised away, giving the same code as an unbounded loop. ////////////////////////////////////////////////////////////////////////////// template BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c >::type segmented_reverse_copy_dst_bounded (BidirIter first, BidirIter last, DstIter dst_first, DstSent dst_last, DstTag, SrcCat) { BOOST_CONTAINER_SEGMENTED_UNROLL(4) while(first != last) { if(dst_first == dst_last) goto out_path; --last; *dst_first = *last; ++dst_first; } out_path: return segduo(last, dst_first); } template BOOST_CONTAINER_FORCEINLINE typename iterator_enable_if_tag >::type segmented_reverse_copy_dst_bounded (RASrcIter first, RASrcIter last, RADstIter dst_first, RADstIter dst_last, const non_segmented_iterator_tag &, const std::random_access_iterator_tag &src_tag) { typedef typename iterator_traits::difference_type difference_type; const difference_type src_n = last - first; const difference_type dst_n = difference_type(dst_last - dst_first); const difference_type n = src_n < dst_n ? src_n : dst_n; return (segmented_reverse_copy_dst_bounded)(last - n, last, dst_first, unreachable_sentinel_t(), non_segmented_iterator_tag(), src_tag); } template segduo segmented_reverse_copy_dst_bounded (BidirIter first, BidirIter last, SegDstIter dst_first, SegDstIter dst_last, segmented_iterator_tag, SrcCat) { typedef segmented_iterator_traits dst_traits; typedef typename dst_traits::local_iterator dst_local_iterator; typedef typename dst_traits::segment_iterator dst_segment_iterator; typedef typename segmented_iterator_traits::is_segmented_iterator dst_is_local_seg_t; dst_segment_iterator sfirst = dst_traits::segment(dst_first); const dst_segment_iterator slast = dst_traits::segment(dst_last); if(sfirst == slast) { segduo r = (segmented_reverse_copy_dst_bounded) (first, last, dst_traits::local(dst_first), dst_traits::local(dst_last), dst_is_local_seg_t(), SrcCat()); return segduo(r.first, dst_traits::compose(sfirst, r.second)); } else { segduo r = (segmented_reverse_copy_dst_bounded) (first, last, dst_traits::local(dst_first), dst_traits::end(sfirst), dst_is_local_seg_t(), SrcCat()); last = r.first; if(first == last) return segduo(last, dst_traits::compose(sfirst, r.second)); for(++sfirst; sfirst != slast; ++sfirst) { r = (segmented_reverse_copy_dst_bounded) (first, last, dst_traits::begin(sfirst), dst_traits::end(sfirst), dst_is_local_seg_t(), SrcCat()); last = r.first; if(first == last) return segduo(last, dst_traits::compose(sfirst, r.second)); } r = (segmented_reverse_copy_dst_bounded) (first, last, dst_traits::begin(slast), dst_traits::local(dst_last), dst_is_local_seg_t(), SrcCat()); return segduo(r.first, dst_traits::compose(sfirst, r.second)); } } ////////////////////////////////////////////////////////////////////////////// // Destination dispatch: routes to bounded helper. // Non-segmented destination: single unbounded call (unreachable_sentinel_t). // Segmented destination: loop over destination segments, bounded per segment. ////////////////////////////////////////////////////////////////////////////// template BOOST_CONTAINER_FORCEINLINE DstIter segmented_reverse_copy_dst_dispatch (BidirIter first, BidirIter last, DstIter result, const non_segmented_iterator_tag &, Cat) { return (segmented_reverse_copy_dst_bounded) (first, last, result, unreachable_sentinel_t(), non_segmented_iterator_tag(), Cat()).second; } template SegDstIter segmented_reverse_copy_dst_dispatch (BidirIter first, BidirIter last, SegDstIter result, const segmented_iterator_tag &, Cat) { typedef segmented_iterator_traits dst_traits; typedef typename dst_traits::local_iterator dst_local_iterator; typedef typename dst_traits::segment_iterator dst_segment_iterator; typedef typename segmented_iterator_traits::is_segmented_iterator dst_is_local_seg_t; if(first == last) return result; dst_segment_iterator dst_seg = dst_traits::segment(result); dst_local_iterator dst_local = dst_traits::local(result); while(1) { const dst_local_iterator dst_end = dst_traits::end(dst_seg); const segduo r = (segmented_reverse_copy_dst_bounded) (first, last, dst_local, dst_end, dst_is_local_seg_t(), Cat()); last = r.first; if(first != last) { ++dst_seg; dst_local = dst_traits::begin(dst_seg); } else return dst_traits::compose(dst_seg, r.second); } } ////////////////////////////////////////////////////////////////////////////// // Source dispatch: walks the source (read pointer) segments in reverse ////////////////////////////////////////////////////////////////////////////// template BOOST_CONTAINER_FORCEINLINE typename algo_enable_if_c::type segmented_reverse_copy_dispatch(BidirIter first, BidirIter last, OutIter result, Tag, Cat) { #if !defined(BOOST_CONTAINER_DISABLE_MULTI_SEGMENTED_ALGO) typedef segmented_iterator_traits dst_traits; return (segmented_reverse_copy_dst_dispatch) (first, last, result, typename dst_traits::is_segmented_iterator(), Cat()); #else return (segmented_reverse_copy_dst_dispatch) (first, last, result, non_segmented_iterator_tag(), Cat()); #endif } template OutIter segmented_reverse_copy_dispatch (SegIter first, SegIter last, OutIter result, segmented_iterator_tag, Cat) { typedef segmented_iterator_traits traits; typedef typename traits::local_iterator local_iterator; typedef typename traits::segment_iterator segment_iterator; typedef typename segmented_iterator_traits ::is_segmented_iterator is_local_seg_t; typedef typename iterator_traits::iterator_category local_cat_t; segment_iterator const sfirst = traits::segment(first); segment_iterator slast = traits::segment(last); if(sfirst == slast) { return (segmented_reverse_copy_dispatch)(traits::local(first), traits::local(last), result, is_local_seg_t(), local_cat_t()); } else { result = (segmented_reverse_copy_dispatch)(traits::begin(slast), traits::local(last), result, is_local_seg_t(), local_cat_t()); for (--slast; slast != sfirst; --slast) result = (segmented_reverse_copy_dispatch)(traits::begin(slast), traits::end(slast), result, is_local_seg_t(), local_cat_t()); return (segmented_reverse_copy_dispatch)(traits::local(first), traits::end(sfirst), result, is_local_seg_t(), local_cat_t()); } } } // namespace detail_algo //! Copies elements from [first, last) to the range beginning at \c result //! in reverse order. When the source range uses segmented iterators, //! exploits segmentation by walking segments in reverse order, processing //! each local range without per-element segment-boundary overhead. //! When the output range also uses segmented iterators, walks output //! segments as well (dual-segmented / multi-segmented dispatch). //! Returns the output iterator past the last element written. template BOOST_CONTAINER_FORCEINLINE OutIter segmented_reverse_copy(BidirIter first, BidirIter last, OutIter result) { typedef segmented_iterator_traits traits; return detail_algo::segmented_reverse_copy_dispatch (first, last, result, typename traits::is_segmented_iterator(), typename iterator_traits::iterator_category()); } } // namespace container } // namespace boost #include #endif // BOOST_CONTAINER_EXPERIMENTAL_SEGMENTED_REVERSE_COPY_HPP