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 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,
324 std::ranges::range_difference_t<urng_t>
const size_of_chunk) :
325 chunk_size{size_of_chunk},
326 remaining{size_of_chunk},
327 urng_begin{
std::
move(it_begin)},
330 current_chunk = std::ranges::subrange<helper_it_t, sentinel_t>{helper_it_t{*
this, it_begin}, it_end};
339 friend constexpr bool operator==(basic_input_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
341 return lhs.urng_begin == rhs;
345 friend constexpr bool operator==(basic_input_iterator
const & lhs, basic_input_iterator
const & rhs)
noexcept
347 return (lhs.urng_begin == rhs.urng_begin) && (lhs.remaining == rhs.remaining);
351 constexpr basic_input_iterator & operator++() noexcept
353 while (remaining > 0u && urng_begin != urng_end)
358 current_chunk = std::ranges::subrange<helper_it_t, sentinel_t>{helper_it_t{*
this, urng_begin}, urng_end};
359 remaining = chunk_size;
364 constexpr basic_input_iterator operator++(
int)
noexcept
366 basic_input_iterator tmp{*
this};
372 constexpr value_type operator*() const noexcept
374 return current_chunk;
379 std::ranges::range_difference_t<urng_t> chunk_size;
382 std::ranges::range_difference_t<urng_t> remaining;
385 urng_it_t urng_begin;
391 value_type current_chunk;
410template <std::ranges::input_range urng_t>
411 requires std::ranges::view<urng_t>
412template <
bool const_range>
413class chunk_view<urng_t>::basic_iterator :
public maybe_iterator_category<maybe_const_iterator_t<const_range, urng_t>>
417 using it_t = maybe_const_iterator_t<const_range, urng_t>;
419 using sentinel_t = maybe_const_sentinel_t<const_range, urng_t>;
422 template <
bool other_const_range>
423 friend class basic_iterator;
432 using value_type = std::ranges::subrange<it_t, it_t>;
434 using pointer = void;
436 using reference = value_type;
440 detail::iterator_concept_tag_t<it_t>>;
446 constexpr basic_iterator() =
default;
447 constexpr basic_iterator(basic_iterator
const &) =
default;
448 constexpr basic_iterator(basic_iterator &&) =
default;
449 constexpr basic_iterator & operator=(basic_iterator
const &) =
default;
450 constexpr basic_iterator & operator=(basic_iterator &&) =
default;
451 ~basic_iterator() =
default;
454 constexpr basic_iterator(basic_iterator<!const_range>
const & it)
noexcept
457 chunk_size{std::move(it.chunk_size)},
458 urng_begin{std::move(it.urng_begin)},
459 urng_end{std::move(it.urng_end)},
460 current_chunk{std::move(it.current_chunk)}
474 constexpr explicit basic_iterator(it_t it_start,
476 std::ranges::range_difference_t<urng_t>
const size_of_chunk) :
477 chunk_size{size_of_chunk},
478 urng_begin{
std::
move(it_start)},
481 current_chunk = value_type{it_start, get_next_end_of_chunk(it_start)};
490 friend constexpr bool operator==(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
492 return lhs.current_chunk.begin() == rhs;
496 friend constexpr bool operator==(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
498 return (lhs.current_chunk.begin() == rhs.current_chunk.begin()) && (lhs.chunk_size == rhs.chunk_size);
502 friend constexpr bool operator!=(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
504 return !(lhs == rhs);
508 friend constexpr bool operator!=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
510 return !(lhs == rhs);
514 friend constexpr bool operator<(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
516 return lhs.current_chunk.begin() < rhs.current_chunk.begin();
520 friend constexpr bool operator>(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
522 return lhs.current_chunk.begin() > rhs.current_chunk.begin();
526 friend constexpr bool operator<=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
528 return lhs.current_chunk.begin() <= rhs.current_chunk.begin();
532 friend constexpr bool operator>=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
534 return lhs.current_chunk.begin() >= rhs.current_chunk.begin();
540 constexpr basic_iterator & operator++() noexcept
542 current_chunk = value_type{current_chunk.end(), get_next_end_of_chunk(current_chunk.end())};
547 basic_iterator operator++(
int)
noexcept
549 basic_iterator tmp{*
this};
557 constexpr basic_iterator & operator--() noexcept
558 requires
std::bidirectional_iterator<it_t>
560 current_chunk = value_type{get_former_start_of_chunk(current_chunk.begin()), current_chunk.begin()};
567 constexpr basic_iterator operator--(
int)
noexcept
568 requires std::bidirectional_iterator<it_t>
570 basic_iterator tmp{*
this};
578 constexpr basic_iterator & operator+=(difference_type
const skip)
noexcept
579 requires std::random_access_iterator<it_t>
581 auto new_start_it = current_chunk.begin() + (chunk_size * skip);
582 current_chunk = value_type{new_start_it, get_next_end_of_chunk(new_start_it)};
589 constexpr basic_iterator operator+(difference_type
const skip)
const noexcept
590 requires std::random_access_iterator<it_t>
592 basic_iterator tmp{*
this};
599 friend constexpr basic_iterator operator+(difference_type
const skip, basic_iterator
const & it)
noexcept
600 requires std::random_access_iterator<it_t>
608 constexpr basic_iterator & operator-=(difference_type
const skip)
noexcept
609 requires std::random_access_iterator<it_t>
611 auto new_start_it = current_chunk.begin() - (chunk_size * skip);
612 current_chunk = value_type{new_start_it, get_next_end_of_chunk(new_start_it)};
620 constexpr basic_iterator operator-(difference_type
const skip)
const noexcept
621 requires std::random_access_iterator<it_t>
623 basic_iterator tmp{*
this};
630 friend constexpr basic_iterator operator-(difference_type
const skip, basic_iterator
const & it)
noexcept
631 requires std::random_access_iterator<it_t>
640 friend constexpr difference_type operator-(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
641 requires std::sized_sentinel_for<it_t, it_t>
643 return static_cast<difference_type
>((lhs.current_chunk.begin() - rhs.current_chunk.begin()) / lhs.chunk_size);
649 friend constexpr difference_type operator-(sentinel_t
const & , basic_iterator
const & rhs)
noexcept
650 requires std::sized_sentinel_for<sentinel_t, it_t>
652 return static_cast<difference_type
>((rhs.urng_end - rhs.current_chunk.begin() + rhs.chunk_size - 1)
659 friend constexpr difference_type operator-(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
660 requires std::sized_sentinel_for<sentinel_t, it_t>
668 constexpr reference operator[](difference_type
const n)
const
669 requires std::random_access_iterator<it_t>
675 constexpr value_type operator*() const noexcept
677 return current_chunk;
682 std::ranges::range_difference_t<urng_t> chunk_size;
691 value_type current_chunk;
694 constexpr it_t get_next_end_of_chunk(it_t start_of_chunk)
const
707 if constexpr (std::sized_sentinel_for<sentinel_t, it_t>)
709 if (chunk_size >= std::abs(urng_end - start_of_chunk))
710 return std::ranges::next(start_of_chunk, urng_end);
712 return std::ranges::next(start_of_chunk, chunk_size);
716 for (std::ranges::range_difference_t<urng_t> increments{};
717 increments != chunk_size && start_of_chunk != urng_end;
723 return start_of_chunk;
728 constexpr it_t get_former_start_of_chunk(it_t end_of_chunk)
const
741 if constexpr (std::sized_sentinel_for<sentinel_t, it_t>)
743 if (chunk_size >= std::abs(urng_begin - end_of_chunk))
746 return std::ranges::prev(end_of_chunk, chunk_size);
750 for (std::ranges::range_difference_t<urng_t> decrements{};
751 decrements != chunk_size && end_of_chunk != urng_begin;
773 return adaptor_from_functor{*
this, chunk_size};
781 template <std::ranges::range urng_t>
782 constexpr auto operator()(urng_t && urange, std::ranges::range_difference_t<urng_t>
const chunk_size)
const
784 static_assert(std::ranges::input_range<urng_t>,
785 "The range parameter to views::chunk must model std::ranges::input_range.");
787 return chunk_view{std::forward<urng_t>(urange), chunk_size};
835inline 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:835
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.