SeqAn3  3.1.0-rc.1
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 
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> &&
80  std::ranges::contiguous_range<urng_t> &&
81  std::ranges::sized_range<urng_t>)
82  {
83  return std::span{std::ranges::data(urange) + begin_pos, static_cast<size_t>(target_size)};
84  }
85  // random_access
86  else if constexpr (std::ranges::borrowed_range<urng_t> &&
87  std::ranges::random_access_range<urng_t> &&
88  std::ranges::sized_range<urng_t>)
89  {
90  return std::ranges::subrange<std::ranges::iterator_t<urng_t>, std::ranges::iterator_t<urng_t>>
91  {
92  std::ranges::begin(urange) + begin_pos,
93  std::ranges::begin(urange) + end_pos,
94  static_cast<size_t>(target_size)
95  };
96  }
97  // std::views::drop
98  else
99  {
100  // urange | drop | take
101  return std::views::take(std::views::drop(std::forward<urng_t>(urange), begin_pos), target_size);
102  }
103 #else // ^^^ workaround / no workaround vvv
104  // urange | type_reduce | drop | take
105  return std::views::take(std::views::drop(seqan3::views::type_reduce(std::forward<urng_t>(urange)),
106  begin_pos),
107  target_size);
108 #endif // SEQAN3_WORKAROUND_GCC_100139
109  }
110 };
111 
112 } // namespace seqan3::detail
113 
114 // ============================================================================
115 // views::slice (adaptor instance definition)
116 // ============================================================================
117 
118 namespace seqan3::views
119 {
183 inline constexpr auto slice = detail::slice_fn{};
184 
185 } // namespace seqan3::views
Provides seqan3::detail::adaptor_from_functor.
Template for range adaptor closure objects that store arguments and wrap a proto-adaptor.
Definition: adaptor_from_functor.hpp:57
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:183
constexpr auto type_reduce
A view adaptor that behaves like std::views::all, but type erases certain ranges.
Definition: type_reduce.hpp:153
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 internal SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
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.
View adaptor definition for views::slice.
Definition: slice.hpp:35
constexpr auto operator()(ptrdiff_t begin_pos, ptrdiff_t end_pos) const noexcept
Store the arguments and return a range adaptor closure object.
Definition: slice.hpp:37
constexpr auto operator()(urng_t &&urange, std::ranges::range_difference_t< urng_t > begin_pos, std::ranges::range_difference_t< urng_t > end_pos) const
Call the view's constructor with the underlying view as argument.
Definition: slice.hpp:46
Provides seqan3::views::type_reduce.
Provides C++20 additions to the type_traits header.