25namespace seqan3::detail
39template <std::ranges::input_range urng_t>
40 requires std::ranges::view<urng_t>
41class chunk_view :
public std::ranges::view_interface<chunk_view<urng_t>>
48 std::ranges::range_difference_t<urng_t> chunk_size;
51 template <
bool const_range>
52 class basic_input_iterator;
55 template <
bool const_range>
63 requires std::default_initializable<urng_t>
65 chunk_view(chunk_view const & rhs) = default;
66 chunk_view(chunk_view && rhs) = default;
67 chunk_view & operator=(chunk_view const & rhs) = default;
68 chunk_view & operator=(chunk_view && rhs) = default;
69 ~chunk_view() = default;
75 constexpr explicit chunk_view(urng_t urng,
std::ranges::range_difference_t<urng_t> const size_of_chunk) :
76 urange{std::move(urng)},
77 chunk_size{size_of_chunk}
99 if constexpr (std::ranges::forward_range<urng_t>)
100 return basic_iterator<false>{
std::ranges::begin(urange), std::ranges::end(urange), chunk_size};
102 return basic_input_iterator<false>{
std::ranges::begin(urange), std::ranges::end(urange), chunk_size};
106 auto begin() const noexcept
109 if constexpr (std::ranges::forward_range<urng_t>)
110 return basic_iterator<true>{
std::ranges::cbegin(urange), std::ranges::cend(urange), chunk_size};
112 return basic_input_iterator<true>{
std::ranges::cbegin(urange), std::ranges::cend(urange), chunk_size};
132 return std::ranges::end(urange);
136 auto end() const noexcept
139 return std::ranges::cend(urange);
147 requires std::ranges::sized_range<urng_t>
149 using size_type = std::ranges::range_size_t<urng_t>;
150 return static_cast<size_type
>((std::ranges::size(urange) + chunk_size - 1) / chunk_size);
155 requires
std::ranges::sized_range<urng_t const>
157 using size_type = std::ranges::range_size_t<urng_t const>;
158 return static_cast<size_type
>((std::ranges::size(urange) + chunk_size - 1) / chunk_size);
163template <std::ranges::range rng_t>
164chunk_view(rng_t &&, std::ranges::range_difference_t<rng_t>
const &) -> chunk_view<seqan3::detail::all_t<rng_t>>;
187template <std::ranges::input_range urng_t>
188 requires std::ranges::view<urng_t>
189template <
bool const_range>
190class chunk_view<urng_t>::basic_input_iterator :
191 public maybe_iterator_category<maybe_const_iterator_t<const_range, urng_t>>
195 using urng_it_t = maybe_const_iterator_t<const_range, urng_t>;
198 using sentinel_t = maybe_const_sentinel_t<const_range, urng_t>;
212 template <
typename outer_it_type>
213 class input_helper_iterator :
public urng_it_t
219 constexpr input_helper_iterator() =
default;
220 constexpr input_helper_iterator(input_helper_iterator
const &) =
default;
221 constexpr input_helper_iterator(input_helper_iterator &&) =
default;
222 constexpr input_helper_iterator & operator=(input_helper_iterator
const &) =
default;
223 constexpr input_helper_iterator & operator=(input_helper_iterator &&) =
default;
224 ~input_helper_iterator() =
default;
227 constexpr explicit input_helper_iterator(outer_it_type & outer_iterator, urng_it_t urng_it) :
233 constexpr explicit input_helper_iterator(urng_it_t urng_it) : urng_it_t(
std::
move(urng_it))
238 input_helper_iterator & operator++() noexcept
240 --(outer_it->remaining);
241 urng_it_t::operator++();
246 input_helper_iterator operator++(
int)
noexcept
248 input_helper_iterator tmp{*
this};
254#if SEQAN3_COMPILER_IS_GCC && (__GNUC__ > 12)
256 friend constexpr bool operator==(input_helper_iterator
const & lhs, sentinel_t)
noexcept
258 return lhs.outer_it->remaining == 0u || lhs.outer_it->urng_begin == lhs.outer_it->urng_end;
262 bool operator==(sentinel_t
const & )
noexcept
264 return this->outer_it->remaining == 0u || this->outer_it->urng_begin == this->outer_it->urng_end;
269 outer_it_type * outer_it{
nullptr};
273 using helper_it_t = input_helper_iterator<basic_input_iterator>;
276 template <
bool other_const_range>
277 friend class basic_input_iterator;
280 template <
typename outer_it_type>
281 friend class input_helper_iterator;
290 using value_type = std::ranges::subrange<helper_it_t, sentinel_t>;
292 using pointer = void;
294 using reference = value_type;
302 constexpr basic_input_iterator() =
default;
303 constexpr basic_input_iterator(basic_input_iterator
const &) =
default;
304 constexpr basic_input_iterator(basic_input_iterator &&) =
default;
305 constexpr basic_input_iterator & operator=(basic_input_iterator
const &) =
default;
306 constexpr basic_input_iterator & operator=(basic_input_iterator &&) =
default;
307 ~basic_input_iterator() =
default;
310 constexpr explicit basic_input_iterator(basic_input_iterator<!const_range> it)
noexcept
313 chunk_size{std::move(it.chunk_size)},
314 remaining{std::move(it.remaining)},
315 urng_begin{std::move(it.urng_begin)},
316 urng_end{std::move(it.urng_end)},
317 current_chunk{std::move(it.current_chunk)}
331 constexpr explicit basic_input_iterator(urng_it_t it_begin,
333 std::ranges::range_difference_t<urng_t>
const size_of_chunk) :
334 chunk_size{size_of_chunk},
335 remaining{size_of_chunk},
336 urng_begin{
std::
move(it_begin)},
339 current_chunk = std::ranges::subrange<helper_it_t, sentinel_t>{helper_it_t{*
this, it_begin}, it_end};
348 friend constexpr bool operator==(basic_input_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
350 return lhs.urng_begin == rhs;
354 friend constexpr bool operator==(basic_input_iterator
const & lhs, basic_input_iterator
const & rhs)
noexcept
356 return (lhs.urng_begin == rhs.urng_begin) && (lhs.remaining == rhs.remaining);
360 constexpr basic_input_iterator & operator++() noexcept
362 while (remaining > 0u && urng_begin != urng_end)
367 current_chunk = std::ranges::subrange<helper_it_t, sentinel_t>{helper_it_t{*
this, urng_begin}, urng_end};
368 remaining = chunk_size;
373 constexpr basic_input_iterator operator++(
int)
noexcept
375 basic_input_iterator tmp{*
this};
381 constexpr value_type operator*() const noexcept
383 return current_chunk;
388 std::ranges::range_difference_t<urng_t> chunk_size;
391 std::ranges::range_difference_t<urng_t> remaining;
394 urng_it_t urng_begin;
400 value_type current_chunk;
419template <std::ranges::input_range urng_t>
420 requires std::ranges::view<urng_t>
421template <
bool const_range>
422class chunk_view<urng_t>::basic_iterator :
public maybe_iterator_category<maybe_const_iterator_t<const_range, urng_t>>
426 using it_t = maybe_const_iterator_t<const_range, urng_t>;
428 using sentinel_t = maybe_const_sentinel_t<const_range, urng_t>;
431 template <
bool other_const_range>
432 friend class basic_iterator;
441 using value_type = std::ranges::subrange<it_t, it_t>;
443 using pointer = void;
445 using reference = value_type;
449 detail::iterator_concept_tag_t<it_t>>;
455 constexpr basic_iterator() =
default;
456 constexpr basic_iterator(basic_iterator
const &) =
default;
457 constexpr basic_iterator(basic_iterator &&) =
default;
458 constexpr basic_iterator & operator=(basic_iterator
const &) =
default;
459 constexpr basic_iterator & operator=(basic_iterator &&) =
default;
460 ~basic_iterator() =
default;
463 constexpr basic_iterator(basic_iterator<!const_range>
const & it)
noexcept
466 chunk_size{std::move(it.chunk_size)},
467 urng_begin{std::move(it.urng_begin)},
468 urng_end{std::move(it.urng_end)},
469 current_chunk{std::move(it.current_chunk)}
483 constexpr explicit basic_iterator(it_t it_start,
485 std::ranges::range_difference_t<urng_t>
const size_of_chunk) :
486 chunk_size{size_of_chunk},
487 urng_begin{
std::
move(it_start)},
490 current_chunk = value_type{it_start, get_next_end_of_chunk(it_start)};
499 friend constexpr bool operator==(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
501 return lhs.current_chunk.begin() == rhs;
505 friend constexpr bool operator==(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
507 return (lhs.current_chunk.begin() == rhs.current_chunk.begin()) && (lhs.chunk_size == rhs.chunk_size);
511 friend constexpr bool operator!=(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
513 return !(lhs == rhs);
517 friend constexpr bool operator!=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
519 return !(lhs == rhs);
523 friend constexpr bool operator<(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
525 return lhs.current_chunk.begin() < rhs.current_chunk.begin();
529 friend constexpr bool operator>(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
531 return lhs.current_chunk.begin() > rhs.current_chunk.begin();
535 friend constexpr bool operator<=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
537 return lhs.current_chunk.begin() <= rhs.current_chunk.begin();
541 friend constexpr bool operator>=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
543 return lhs.current_chunk.begin() >= rhs.current_chunk.begin();
549 constexpr basic_iterator & operator++() noexcept
551 current_chunk = value_type{current_chunk.end(), get_next_end_of_chunk(current_chunk.end())};
556 basic_iterator operator++(
int)
noexcept
558 basic_iterator tmp{*
this};
566 constexpr basic_iterator & operator--() noexcept
567 requires
std::bidirectional_iterator<it_t>
569 current_chunk = value_type{get_former_start_of_chunk(current_chunk.begin()), current_chunk.begin()};
576 constexpr basic_iterator operator--(
int)
noexcept
577 requires std::bidirectional_iterator<it_t>
579 basic_iterator tmp{*
this};
587 constexpr basic_iterator & operator+=(difference_type
const skip)
noexcept
588 requires std::random_access_iterator<it_t>
590 auto new_start_it = current_chunk.begin() + (chunk_size * skip);
591 current_chunk = value_type{new_start_it, get_next_end_of_chunk(new_start_it)};
598 constexpr basic_iterator operator+(difference_type
const skip)
const noexcept
599 requires std::random_access_iterator<it_t>
601 basic_iterator tmp{*
this};
608 friend constexpr basic_iterator operator+(difference_type
const skip, basic_iterator
const & it)
noexcept
609 requires std::random_access_iterator<it_t>
617 constexpr basic_iterator & operator-=(difference_type
const skip)
noexcept
618 requires std::random_access_iterator<it_t>
620 auto new_start_it = current_chunk.begin() - (chunk_size * skip);
621 current_chunk = value_type{new_start_it, get_next_end_of_chunk(new_start_it)};
629 constexpr basic_iterator operator-(difference_type
const skip)
const noexcept
630 requires std::random_access_iterator<it_t>
632 basic_iterator tmp{*
this};
639 friend constexpr basic_iterator operator-(difference_type
const skip, basic_iterator
const & it)
noexcept
640 requires std::random_access_iterator<it_t>
649 friend constexpr difference_type operator-(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
650 requires std::sized_sentinel_for<it_t, it_t>
652 return static_cast<difference_type
>((lhs.current_chunk.begin() - rhs.current_chunk.begin()) / lhs.chunk_size);
658 friend constexpr difference_type operator-(sentinel_t
const & , basic_iterator
const & rhs)
noexcept
659 requires std::sized_sentinel_for<sentinel_t, it_t>
661 return static_cast<difference_type
>((rhs.urng_end - rhs.current_chunk.begin() + rhs.chunk_size - 1)
668 friend constexpr difference_type operator-(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
669 requires std::sized_sentinel_for<sentinel_t, it_t>
677 constexpr reference operator[](difference_type
const n)
const
678 requires std::random_access_iterator<it_t>
684 constexpr value_type operator*() const noexcept
686 return current_chunk;
691 std::ranges::range_difference_t<urng_t> chunk_size;
700 value_type current_chunk;
703 constexpr it_t get_next_end_of_chunk(it_t start_of_chunk)
const
716 if constexpr (std::sized_sentinel_for<sentinel_t, it_t>)
718 if (chunk_size >= std::abs(urng_end - start_of_chunk))
719 return std::ranges::next(start_of_chunk, urng_end);
721 return std::ranges::next(start_of_chunk, chunk_size);
725 for (std::ranges::range_difference_t<urng_t> increments{};
726 increments != chunk_size && start_of_chunk != urng_end;
732 return start_of_chunk;
737 constexpr it_t get_former_start_of_chunk(it_t end_of_chunk)
const
750 if constexpr (std::sized_sentinel_for<sentinel_t, it_t>)
752 if (chunk_size >= std::abs(urng_begin - end_of_chunk))
755 return std::ranges::prev(end_of_chunk, chunk_size);
759 for (std::ranges::range_difference_t<urng_t> decrements{};
760 decrements != chunk_size && end_of_chunk != urng_begin;
782 return adaptor_from_functor{*
this, chunk_size};
790 template <std::ranges::range urng_t>
791 constexpr auto operator()(urng_t && urange, std::ranges::range_difference_t<urng_t>
const chunk_size)
const
793 static_assert(std::ranges::input_range<urng_t>,
794 "The range parameter to views::chunk must model std::ranges::input_range.");
796 return chunk_view{std::forward<urng_t>(urange), chunk_size};
844inline constexpr auto chunk = detail::chunk_fn{};
Provides seqan3::detail::adaptor_from_functor.
Provides seqan3::detail::all.
Core alphabet concept and free function/type trait wrappers.
Provides various transformation traits used by the range module.
constexpr size_t size
The size of a type pack.
Definition: type_pack/traits.hpp:146
constexpr auto chunk
Divide a range in chunks.
Definition: chunk.hpp:844
Specifies requirements of an input range type for which the const version of that type satisfies the ...
Provides various transformation traits for use on iterators.
The SeqAn namespace for views.
Definition: char_strictly_to.hpp:22
SeqAn specific customisations in the standard namespace.
Additional non-standard concepts for ranges.