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>>
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 underlying_range, uint16_t const size_of_chunk) :
76 urange{std::move(underlying_range)},
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 &&, uint16_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 bool operator==(sentinel_t
const & )
noexcept
256 return this->outer_it->remaining == 0u || this->outer_it->urng_begin == this->outer_it->urng_end;
260 outer_it_type * outer_it{
nullptr};
264 using helper_it_t = input_helper_iterator<basic_input_iterator>;
267 template <
bool other_const_range>
268 friend class basic_input_iterator;
271 template <
typename outer_it_type>
272 friend class input_helper_iterator;
281 using value_type = std::ranges::subrange<helper_it_t, sentinel_t>;
283 using pointer = void;
285 using reference = value_type;
293 constexpr basic_input_iterator() =
default;
294 constexpr basic_input_iterator(basic_input_iterator
const &) =
default;
295 constexpr basic_input_iterator(basic_input_iterator &&) =
default;
296 constexpr basic_input_iterator & operator=(basic_input_iterator
const &) =
default;
297 constexpr basic_input_iterator & operator=(basic_input_iterator &&) =
default;
298 ~basic_input_iterator() =
default;
301 constexpr explicit basic_input_iterator(basic_input_iterator<!const_range> it)
noexcept
304 chunk_size{std::move(it.chunk_size)},
305 remaining{std::move(it.remaining)},
306 urng_begin{std::move(it.urng_begin)},
307 urng_end{std::move(it.urng_end)},
308 current_chunk{std::move(it.current_chunk)}
322 constexpr explicit basic_input_iterator(urng_it_t it_begin, sentinel_t it_end, uint16_t
const size_of_chunk) :
323 chunk_size{size_of_chunk},
324 remaining{size_of_chunk},
325 urng_begin{
std::
move(it_begin)},
328 current_chunk = std::ranges::subrange<helper_it_t, sentinel_t>{helper_it_t{*
this, it_begin}, it_end};
337 friend constexpr bool operator==(basic_input_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
339 return lhs.urng_begin == rhs;
343 friend constexpr bool operator==(basic_input_iterator
const & lhs, basic_input_iterator
const & rhs)
noexcept
345 return (lhs.urng_begin == rhs.urng_begin) && (lhs.remaining == rhs.remaining);
349 constexpr basic_input_iterator & operator++() noexcept
351 while (remaining > 0u && urng_begin != urng_end)
356 current_chunk = std::ranges::subrange<helper_it_t, sentinel_t>{helper_it_t{*
this, urng_begin}, urng_end};
357 remaining = chunk_size;
362 constexpr basic_input_iterator operator++(
int)
noexcept
364 basic_input_iterator tmp{*
this};
370 constexpr value_type operator*() const noexcept
372 return current_chunk;
383 urng_it_t urng_begin;
389 value_type current_chunk;
408template <std::ranges::input_range urng_t>
409 requires std::ranges::view<urng_t>
410template <
bool const_range>
411class chunk_view<urng_t>::basic_iterator :
public maybe_iterator_category<maybe_const_iterator_t<const_range, urng_t>>
415 using it_t = maybe_const_iterator_t<const_range, urng_t>;
417 using sentinel_t = maybe_const_sentinel_t<const_range, urng_t>;
420 template <
bool other_const_range>
421 friend class basic_iterator;
430 using value_type = std::ranges::subrange<it_t, it_t>;
432 using pointer = void;
434 using reference = value_type;
438 detail::iterator_concept_tag_t<it_t>>;
444 constexpr basic_iterator() =
default;
445 constexpr basic_iterator(basic_iterator
const &) =
default;
446 constexpr basic_iterator(basic_iterator &&) =
default;
447 constexpr basic_iterator & operator=(basic_iterator
const &) =
default;
448 constexpr basic_iterator & operator=(basic_iterator &&) =
default;
449 ~basic_iterator() =
default;
452 constexpr basic_iterator(basic_iterator<!const_range>
const & it)
noexcept
455 chunk_size{std::move(it.chunk_size)},
456 urng_begin{std::move(it.urng_begin)},
457 urng_end{std::move(it.urng_end)},
458 current_chunk{std::move(it.current_chunk)}
472 constexpr explicit basic_iterator(it_t it_start, sentinel_t it_end, uint16_t
const size_of_chunk) :
473 chunk_size{size_of_chunk},
474 urng_begin{
std::
move(it_start)},
477 current_chunk = value_type{it_start, get_next_end_of_chunk(it_start)};
486 friend constexpr bool operator==(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
488 return lhs.current_chunk.begin() == rhs;
492 friend constexpr bool operator==(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
494 return (lhs.current_chunk.begin() == rhs.current_chunk.begin()) && (lhs.chunk_size == rhs.chunk_size);
498 friend constexpr bool operator!=(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
500 return !(lhs == rhs);
504 friend constexpr bool operator!=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
506 return !(lhs == rhs);
510 friend constexpr bool operator<(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
512 return lhs.current_chunk.begin() < rhs.current_chunk.begin();
516 friend constexpr bool operator>(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
518 return lhs.current_chunk.begin() > rhs.current_chunk.begin();
522 friend constexpr bool operator<=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
524 return lhs.current_chunk.begin() <= rhs.current_chunk.begin();
528 friend constexpr bool operator>=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
530 return lhs.current_chunk.begin() >= rhs.current_chunk.begin();
536 constexpr basic_iterator & operator++() noexcept
538 current_chunk = value_type{current_chunk.end(), get_next_end_of_chunk(current_chunk.end())};
543 basic_iterator operator++(
int)
noexcept
545 basic_iterator tmp{*
this};
553 constexpr basic_iterator & operator--() noexcept
554 requires
std::bidirectional_iterator<it_t>
556 current_chunk = value_type{get_former_start_of_chunk(current_chunk.begin()), current_chunk.begin()};
563 constexpr basic_iterator operator--(
int)
noexcept
564 requires std::bidirectional_iterator<it_t>
566 basic_iterator tmp{*
this};
574 constexpr basic_iterator & operator+=(difference_type
const skip)
noexcept
575 requires std::random_access_iterator<it_t>
577 auto new_start_it = current_chunk.begin() + (chunk_size * skip);
578 current_chunk = value_type{new_start_it, get_next_end_of_chunk(new_start_it)};
585 constexpr basic_iterator operator+(difference_type
const skip)
const noexcept
586 requires std::random_access_iterator<it_t>
588 basic_iterator tmp{*
this};
595 friend constexpr basic_iterator operator+(difference_type
const skip, basic_iterator
const & it)
noexcept
596 requires std::random_access_iterator<it_t>
604 constexpr basic_iterator & operator-=(difference_type
const skip)
noexcept
605 requires std::random_access_iterator<it_t>
607 auto new_start_it = current_chunk.begin() - (chunk_size * skip);
608 current_chunk = value_type{new_start_it, get_next_end_of_chunk(new_start_it)};
616 constexpr basic_iterator operator-(difference_type
const skip)
const noexcept
617 requires std::random_access_iterator<it_t>
619 basic_iterator tmp{*
this};
626 friend constexpr basic_iterator operator-(difference_type
const skip, basic_iterator
const & it)
noexcept
627 requires std::random_access_iterator<it_t>
636 friend constexpr difference_type operator-(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
637 requires std::sized_sentinel_for<it_t, it_t>
639 return static_cast<difference_type
>((lhs.current_chunk.begin() - rhs.current_chunk.begin()) / lhs.chunk_size);
645 friend constexpr difference_type operator-(sentinel_t
const & , basic_iterator
const & rhs)
noexcept
646 requires std::sized_sentinel_for<sentinel_t, it_t>
648 return static_cast<difference_type
>((rhs.urng_end - rhs.current_chunk.begin() + rhs.chunk_size - 1)
655 friend constexpr difference_type operator-(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
656 requires std::sized_sentinel_for<sentinel_t, it_t>
664 constexpr reference operator[](difference_type
const n)
const
665 requires std::random_access_iterator<it_t>
671 constexpr value_type operator*() const noexcept
673 return current_chunk;
687 value_type current_chunk;
690 constexpr it_t get_next_end_of_chunk(it_t start_of_chunk)
const
703 if constexpr (std::sized_sentinel_for<sentinel_t, it_t>)
705 if (chunk_size >= std::abs(urng_end - start_of_chunk))
706 return std::ranges::next(start_of_chunk, urng_end);
708 return std::ranges::next(start_of_chunk, chunk_size);
712 for (uint16_t increments{}; increments != chunk_size && start_of_chunk != urng_end; ++increments)
715 return start_of_chunk;
720 constexpr it_t get_former_start_of_chunk(it_t end_of_chunk)
const
733 if constexpr (std::sized_sentinel_for<sentinel_t, it_t>)
735 if (chunk_size >= std::abs(urng_begin - end_of_chunk))
738 return std::ranges::prev(end_of_chunk, chunk_size);
742 for (uint16_t decrements{}; decrements != chunk_size && end_of_chunk != urng_begin; ++decrements)
759 constexpr auto operator()(uint16_t
const chunk_size)
const
761 return adaptor_from_functor{*
this, chunk_size};
769 template <std::ranges::range underlying_range_t>
770 constexpr auto operator()(underlying_range_t && urange, uint16_t
const chunk_size)
const
772 static_assert(std::ranges::input_range<underlying_range_t>,
773 "The range parameter to views::chunk must model std::ranges::input_range.");
775 return chunk_view{std::forward<underlying_range_t>(urange), chunk_size};
823inline 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: traits.hpp:146
constexpr auto chunk
Divide a range in chunks.
Definition: chunk.hpp:823
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.
The <ranges> header from C++20's standard library.
Additional non-standard concepts for ranges.