xref: /freebsd/contrib/llvm-project/libcxx/include/__algorithm/for_each_n_segment.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef _LIBCPP___ALGORITHM_FOR_EACH_N_SEGMENT_H
10 #define _LIBCPP___ALGORITHM_FOR_EACH_N_SEGMENT_H
11 
12 #include <__config>
13 #include <__iterator/iterator_traits.h>
14 #include <__iterator/segmented_iterator.h>
15 
16 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
17 #  pragma GCC system_header
18 #endif
19 
20 _LIBCPP_BEGIN_NAMESPACE_STD
21 
22 // __for_each_n_segment optimizes linear iteration over segmented iterators. It processes a segmented
23 // input range [__first, __first + __n) by applying the functor __func to each element within the segment.
24 // The return value of __func is ignored, and the function returns an iterator pointing to one past the
25 // last processed element in the input range.
26 
27 template <class _SegmentedIterator, class _Size, class _Functor>
28 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator
__for_each_n_segment(_SegmentedIterator __first,_Size __orig_n,_Functor __func)29 __for_each_n_segment(_SegmentedIterator __first, _Size __orig_n, _Functor __func) {
30   static_assert(__is_segmented_iterator<_SegmentedIterator>::value &&
31                     __has_random_access_iterator_category<
32                         typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value,
33                 "__for_each_n_segment only works with segmented iterators with random-access local iterators");
34   if (__orig_n <= 0)
35     return __first;
36 
37   using _Traits        = __segmented_iterator_traits<_SegmentedIterator>;
38   using __local_iter_t = typename _Traits::__local_iterator;
39   using __difference_t = typename std::iterator_traits<__local_iter_t>::difference_type;
40   __difference_t __n   = __orig_n;
41   auto __seg           = _Traits::__segment(__first);
42   auto __local_first   = _Traits::__local(__first);
43   __local_iter_t __local_last;
44 
45   while (__n > 0) {
46     __local_last    = _Traits::__end(__seg);
47     auto __seg_size = __local_last - __local_first;
48     if (__n <= __seg_size) {
49       __local_last = __local_first + __n;
50       __func(__local_first, __local_last);
51       break;
52     }
53     __func(__local_first, __local_last);
54     __n -= __seg_size;
55     __local_first = _Traits::__begin(++__seg);
56   }
57 
58   return _Traits::__compose(__seg, __local_last);
59 }
60 
61 _LIBCPP_END_NAMESPACE_STD
62 
63 #endif // _LIBCPP___ALGORITHM_FOR_EACH_N_SEGMENT_H
64