SeqAn3  3.2.0
The Modern C++ library for sequence analysis.
slice.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <concepts>
16 #include <iterator>
17 #include <ranges>
18 #include <span>
19 #include <stdexcept>
20 #include <type_traits>
21 
23 #include <seqan3/io/exception.hpp>
25 
26 namespace seqan3::detail
27 {
28 
29 // ============================================================================
30 // slice_fn (adaptor definition)
31 // ============================================================================
32 
34 struct slice_fn
35 {
37  constexpr auto operator()(ptrdiff_t begin_pos, ptrdiff_t end_pos) const noexcept
38  {
39  return detail::adaptor_from_functor{*this, begin_pos, end_pos};
40  }
41 
45  template <std::ranges::viewable_range urng_t>
46  constexpr auto operator()(urng_t && urange,
47  std::ranges::range_difference_t<urng_t> begin_pos,
48  std::ranges::range_difference_t<urng_t> end_pos) const
49  {
50  using position_t = std::ranges::range_difference_t<urng_t>;
51  if constexpr (std::ranges::sized_range<urng_t>)
52  {
53  position_t urange_size = static_cast<position_t>(std::ranges::size(urange));
54 
55  begin_pos = std::min(begin_pos, urange_size);
56  end_pos = std::min(end_pos, urange_size);
57  }
58  position_t target_size = end_pos - begin_pos;
59 
60  if (end_pos < begin_pos)
61  throw std::invalid_argument{"end_pos argument to seqan3::views::slice must be >= the begin_pos argument."};
62 
63  // SEQAN3_WORKAROUND_GCC_100139 == 1 if std::views::{take, drop} does not type reduce (e.g. keep in type
64  // std::basic_string_view, std::span, std::ranges::subrange).
65  // See https://github.com/seqan/seqan3/pull/2540/files#r617575294
66 #if SEQAN3_WORKAROUND_GCC_100139
67  // string_view
68  if constexpr (is_type_specialisation_of_v<std::remove_cvref_t<urng_t>, std::basic_string_view>)
69  {
70  return urange.substr(begin_pos, static_cast<size_t>(target_size));
71  }
72  // string const &
73  else if constexpr (is_type_specialisation_of_v<std::remove_cvref_t<urng_t>, std::basic_string>
75  {
76  return std::basic_string_view{std::ranges::data(urange) + begin_pos, static_cast<size_t>(target_size)};
77  }
78  // contiguous
79  else if constexpr (std::ranges::borrowed_range<urng_t> && std::ranges::contiguous_range<urng_t>
80  && std::ranges::sized_range<urng_t>)
81  {
82  return std::span{std::ranges::data(urange) + begin_pos, static_cast<size_t>(target_size)};
83  }
84  // random_access
85  else if constexpr (std::ranges::borrowed_range<urng_t> && std::ranges::random_access_range<urng_t>
86  && std::ranges::sized_range<urng_t>)
87  {
88  return std::ranges::subrange<std::ranges::iterator_t<urng_t>, std::ranges::iterator_t<urng_t>>{
89  std::ranges::begin(urange) + begin_pos,
90  std::ranges::begin(urange) + end_pos,
91  static_cast<size_t>(target_size)};
92  }
93  // std::views::drop
94  else
95  {
96  // urange | drop | take
97  return std::views::take(std::views::drop(std::forward<urng_t>(urange), begin_pos), target_size);
98  }
99 #else /*^^^ workaround / no workaround vvv*/
100  // urange | type_reduce | drop | take
101  return std::views::take(std::views::drop(seqan3::views::type_reduce(std::forward<urng_t>(urange)), begin_pos),
102  target_size);
103 #endif // SEQAN3_WORKAROUND_GCC_100139
104  }
105 };
106 
107 } // namespace seqan3::detail
108 
109 // ============================================================================
110 // views::slice (adaptor instance definition)
111 // ============================================================================
112 
113 namespace seqan3::views
114 {
178 inline constexpr auto slice = detail::slice_fn{};
179 
180 } // namespace seqan3::views
Provides seqan3::detail::adaptor_from_functor.
The <concepts> header from C++20's standard library.
constexpr size_t size
The size of a type pack.
Definition: type_pack/traits.hpp:146
constexpr auto slice
A view adaptor that returns a half-open interval on the underlying range.
Definition: slice.hpp:178
constexpr auto type_reduce
A view adaptor that behaves like std::views::all, but type erases certain ranges.
Definition: type_reduce.hpp:150
Provides exceptions used in the I/O module.
T is_const_v
T min(T... args)
The SeqAn namespace for views.
Definition: char_strictly_to.hpp:22
The <ranges> header from C++20's standard library.
Provides std::span from the C++20 standard library.
Provides seqan3::views::type_reduce.