SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
slice.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2021, 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 <seqan3/std/concepts>
16 #include <seqan3/std/iterator>
17 #include <seqan3/std/ranges>
18 #include <seqan3/std/span>
19 #include <stdexcept>
20 #include <seqan3/std/type_traits>
21 
24 #include <seqan3/io/exception.hpp>
26 
27 namespace seqan3::detail
28 {
29 
30 // ============================================================================
31 // slice_fn (adaptor definition)
32 // ============================================================================
33 
35 struct slice_fn
36 {
38  constexpr auto operator()(ptrdiff_t begin_pos, ptrdiff_t end_pos) const noexcept
39  {
40  return detail::adaptor_from_functor{*this, begin_pos, end_pos};
41  }
42 
46  template <std::ranges::viewable_range urng_t>
47  constexpr auto operator()(urng_t && urange,
48  std::ranges::range_difference_t<urng_t> begin_pos,
49  std::ranges::range_difference_t<urng_t> end_pos) const
50  {
51  using position_t = std::ranges::range_difference_t<urng_t>;
52  if constexpr (std::ranges::sized_range<urng_t>)
53  {
54  position_t urange_size = static_cast<position_t>(std::ranges::size(urange));
55 
56  begin_pos = std::min(begin_pos, urange_size);
57  end_pos = std::min(end_pos, urange_size);
58  }
59  position_t target_size = end_pos - begin_pos;
60 
61  if (end_pos < begin_pos)
62  throw std::invalid_argument{"end_pos argument to seqan3::views::slice must be >= the begin_pos argument."};
63 
64  // SEQAN3_WORKAROUND_GCC_100139 == 1 if std::views::{take, drop} does not type reduce (e.g. keep in type
65  // std::basic_string_view, std::span, std::ranges::subrange).
66  // See https://github.com/seqan/seqan3/pull/2540/files#r617575294
67 #if SEQAN3_WORKAROUND_GCC_100139
68  // string_view
69  if constexpr (is_type_specialisation_of_v<std::remove_cvref_t<urng_t>, std::basic_string_view>)
70  {
71  return urange.substr(begin_pos, static_cast<size_t>(target_size));
72  }
73  // string const &
74  else if constexpr (is_type_specialisation_of_v<std::remove_cvref_t<urng_t>, std::basic_string> &&
76  {
77  return std::basic_string_view{std::ranges::data(urange) + begin_pos, static_cast<size_t>(target_size)};
78  }
79  // contiguous
80  else if constexpr (std::ranges::borrowed_range<urng_t> &&
81  std::ranges::contiguous_range<urng_t> &&
82  std::ranges::sized_range<urng_t>)
83  {
84  return std::span{std::ranges::data(urange) + begin_pos, static_cast<size_t>(target_size)};
85  }
86  // random_access
87  else if constexpr (std::ranges::borrowed_range<urng_t> &&
88  std::ranges::random_access_range<urng_t> &&
89  std::ranges::sized_range<urng_t>)
90  {
91  return std::ranges::subrange<std::ranges::iterator_t<urng_t>, std::ranges::iterator_t<urng_t>>
92  {
93  std::ranges::begin(urange) + begin_pos,
94  std::ranges::begin(urange) + end_pos,
95  static_cast<size_t>(target_size)
96  };
97  }
98  // std::views::drop
99  else
100  {
101  // urange | drop | take
102  return std::views::take(std::views::drop(std::forward<urng_t>(urange), begin_pos), target_size);
103  }
104 #else // ^^^ workaround / no workaround vvv
105  // urange | type_reduce | drop | take
106  return std::views::take(std::views::drop(seqan3::views::type_reduce(std::forward<urng_t>(urange)),
107  begin_pos),
108  target_size);
109 #endif // SEQAN3_WORKAROUND_GCC_100139
110  }
111 };
112 
113 } // namespace seqan3::detail
114 
115 // ============================================================================
116 // views::slice (adaptor instance definition)
117 // ============================================================================
118 
119 namespace seqan3::views
120 {
121 
189 inline constexpr auto slice = detail::slice_fn{};
190 
192 
193 } // namespace seqan3::views
Provides seqan3::detail::adaptor_from_functor.
T begin(T... args)
The Concepts library.
typename decltype(detail::split_after< i >(list_t{}))::first_type take
Return a seqan3::type_list of the first n types in the input type list.
Definition: traits.hpp:368
typename decltype(detail::split_after< i >(list_t{}))::second_type drop
Return a seqan3::type_list of the types in the input type list, except the first n.
Definition: traits.hpp:388
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:151
constexpr auto slice
A view adaptor that returns a half-open interval on the underlying range.
Definition: slice.hpp:189
constexpr auto type_reduce
A view adaptor that behaves like std::views::all, but type erases certain ranges.
Definition: type_reduce.hpp:158
Provides exceptions used in the I/O module.
T is_const_v
Provides C++20 additions to the <iterator> header.
T min(T... args)
The SeqAn namespace for views.
Definition: char_to.hpp:22
Adaptations of concepts from the Ranges TS.
Provides std::span from the C++20 standard library.
[DEPRECATED] Provides seqan3::views::take.
Provides C++20 additions to the type_traits header.
Provides seqan3::views::type_reduce.