SeqAn3
take_line.hpp
Go to the documentation of this file.
1 // ============================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ============================================================================
4 //
5 // Copyright (c) 2006-2018, Knut Reinert & Freie Universitaet Berlin
6 // Copyright (c) 2016-2018, Knut Reinert & MPI Molekulare Genetik
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 // DAMAGE.
32 //
33 // ============================================================================
34 
40 #pragma once
41 
42 #include <range/v3/view/take_while.hpp>
43 #include <range/v3/algorithm/copy.hpp>
44 
48 #include <seqan3/io/exception.hpp>
49 #include <seqan3/range/concept.hpp>
53 #include <seqan3/std/iterator>
54 #include <seqan3/std/ranges>
56 #include <seqan3/std/iterator>
57 #include <seqan3/std/type_traits>
59 
60 namespace seqan3::detail
61 {
62 
63 // ============================================================================
64 // view_take_line
65 // ============================================================================
66 
78 template <std::ranges::View urng_t, bool require_eol>
79 class view_take_line : public ranges::view_interface<view_take_line<urng_t, require_eol>>
80 {
81 private:
82 
84  urng_t urange;
85 
87  using sentinel_type = std::ranges::sentinel_t<urng_t>;
88 
91  template <typename rng_t>
92  class iterator_type : public inherited_iterator_base<iterator_type<rng_t>, std::ranges::iterator_t<rng_t>>
93  {
94  private:
96  using base_base_t = std::ranges::iterator_t<rng_t>;
98  using base_t = inherited_iterator_base<iterator_type, std::ranges::iterator_t<rng_t>>;
99 
101  bool at_end = false;
102 
103  public:
107  iterator_type() = default;
108  constexpr iterator_type(iterator_type const & rhs) = default;
109  constexpr iterator_type(iterator_type && rhs) = default;
110  constexpr iterator_type & operator=(iterator_type const & rhs) = default;
111  constexpr iterator_type & operator=(iterator_type && rhs) = default;
112  ~iterator_type() = default;
113 
115  iterator_type(base_base_t const & it) : base_t{it} {}
117 
122  using difference_type = typename std::iterator_traits<base_base_t>::difference_type;
123  using value_type = typename std::iterator_traits<base_base_t>::value_type;
124  using reference = typename std::iterator_traits<base_base_t>::reference;
125  using pointer = typename std::iterator_traits<base_base_t>::pointer;
126  using iterator_category = typename std::iterator_traits<base_base_t>::iterator_category;
128 
133  iterator_type & operator++()
134  {
135  *this = ++static_cast<base_base_t>(*this);
136 
137  if constexpr (!std::ranges::ForwardRange<urng_t>) // consuming behaviour for input ranges
138  {
139  if (!at_end)
140  {
141  if (**this == '\r')
142  {
143  *this = ++static_cast<base_base_t>(*this);
144  at_end = true;
145  }
146 
147  if (**this == '\n')
148  {
149  *this = ++static_cast<base_base_t>(*this);
150  at_end = true;
151  }
152  }
153  }
154 
155  return *this;
156  }
157 
158  iterator_type operator++(int)
159  {
160  iterator_type cpy{*this};
161  ++(*this);
162  return cpy;
163  }
165 
170  bool operator==(iterator_type const & rhs) const noexcept(!require_eol)
171  {
172  return static_cast<base_base_t>(*this) == static_cast<base_base_t>(rhs);
173  }
174 
175  bool operator==(sentinel_type const & rhs) const noexcept(!require_eol)
176  {
177 
178  if constexpr (!std::ranges::ForwardRange<urng_t>)
179  {
180  if (at_end)
181  return true;
182  }
183 
184  if (static_cast<base_base_t>(*this) == rhs)
185  {
186  if constexpr (require_eol)
187  throw unexpected_end_of_input{"Reached end of input before end-of-line."};
188  else
189  return true;
190  }
191 
192  return **this == '\r' || **this == '\n';
193  }
194 
195  friend bool operator==(sentinel_type const & lhs, iterator_type const & rhs) noexcept(!require_eol)
196  {
197  return rhs == lhs;
198  }
199 
200  bool operator!=(sentinel_type const & rhs) const noexcept(!require_eol)
201  {
202  return !(*this == rhs);
203  }
204 
205  bool operator!=(iterator_type const & rhs) const noexcept(!require_eol)
206  {
207  return static_cast<base_base_t>(*this) != static_cast<base_base_t>(rhs);
208  }
209 
210  friend bool operator!=(sentinel_type const & lhs, iterator_type const & rhs) noexcept(!require_eol)
211  {
212  return rhs != lhs;
213  }
215  }; // class iterator_type
216 
217 public:
221  using reference = reference_t<urng_t>;
224  using const_reference = detail::transformation_trait_or_t<seqan3::reference<urng_t const>, void>;
226  using value_type = value_type_t<urng_t>;
228  using size_type = void;
230  using difference_type = difference_type_t<urng_t>;
232  using iterator = iterator_type<urng_t>;
234  using const_iterator = detail::transformation_trait_or_t<std::type_identity<iterator_type<urng_t const>>, void>;
236 
240  view_take_line() = default;
241  constexpr view_take_line(view_take_line const & rhs) = default;
242  constexpr view_take_line(view_take_line && rhs) = default;
243  constexpr view_take_line & operator=(view_take_line const & rhs) = default;
244  constexpr view_take_line & operator=(view_take_line && rhs) = default;
245  ~view_take_line() = default;
246 
250  view_take_line(urng_t _urange)
251  : urange{std::move(_urange)}
252  {}
254 
271  iterator begin() noexcept
272  {
273  return {seqan3::begin(urange)};
274  }
275 
277  const_iterator begin() const noexcept
278  requires const_iterable_concept<urng_t>
279  {
280  return {seqan3::cbegin(urange)};
281  }
282 
284  const_iterator cbegin() const noexcept
285  requires const_iterable_concept<urng_t>
286  {
287  return {seqan3::cbegin(urange)};
288  }
289 
303  sentinel_type end() noexcept
304  {
305  return {seqan3::end(urange)};
306  }
307 
309  sentinel_type end() const noexcept
310  requires const_iterable_concept<urng_t>
311  {
312  return {seqan3::cend(urange)};
313  }
314 
316  sentinel_type cend() const noexcept
317  requires const_iterable_concept<urng_t>
318  {
319  return {seqan3::cend(urange)};
320  }
322 
328  template <sequence_container_concept container_t>
329  operator container_t()
331  requires std::CommonReference<reference_t<container_t>, reference>
333  {
334  container_t ret;
336  return ret;
337  }
338 
340  template <sequence_container_concept container_t>
341  operator container_t() const
343  requires std::CommonReference<reference_t<container_t>, reference> && const_iterable_concept<urng_t>
345  {
346  container_t ret;
348  return ret;
349  }
350 };
351 
354 template <typename urng_t, bool require_eol = false>
355 view_take_line(urng_t) -> view_take_line<std::remove_reference_t<urng_t>, require_eol>;
356 
357 // ============================================================================
358 // take_line_fn (adaptor definition)
359 // ============================================================================
360 
364 template <bool require_eol>
365 class take_line_fn : public pipable_adaptor_base<take_line_fn<require_eol>>
366 {
367 private:
369  using base_t = pipable_adaptor_base<take_line_fn<require_eol>>;
370 
371 public:
373  using base_t::base_t;
374 
375 private:
377  friend base_t;
378 
382  template <std::ranges::View urng_t>
383  static auto impl(urng_t urange)
384  {
385  return view_take_line<urng_t, require_eol>{std::move(urange)};
386  }
387 
391  template <std::ranges::ViewableRange urng_t>
392  static auto impl(urng_t && urange)
393  {
394  return impl(view::all(std::forward<urng_t>(urange)));
395  }
396 };
397 
398 } // namespace seqan3::detail
399 
400 // ============================================================================
401 // view::take_line (adaptor instance definition)
402 // ============================================================================
403 
404 namespace seqan3::view
405 {
406 
458 inline auto constexpr take_line = detail::take_line_fn<false>{};
459 
460 // ============================================================================
461 // view::take_line_or_throw (adaptor instance definition)
462 // ============================================================================
463 
471 inline auto constexpr take_line_or_throw = detail::take_line_fn<true>{};
472 
474 
475 } // namespace seqan3::view
::ranges::cbegin cbegin
Alias for ranges::cbegin. Returns an iterator to the beginning of a range.
Definition: ranges:245
Provides exceptions used in the I/O module.
Provides C++20 additions to the <iterator> header.
Contains various shortcuts for common std::ranges functions.
Provides seqan3::detail::transformation_trait_or.
Provides the seqan3::detail::inherited_iterator_base template.
SeqAn specific customisations in the standard namespace.
Definition: align_result.hpp:221
::ranges::copy copy
Alias for ranges::copy. Copies a range of elements to a new location.
Definition: ranges:200
t & operator=(t1 const &rhs)
Assignment operator.
Additional non-standard concepts for ranges.
auto constexpr take_line_or_throw
A view adaptor that returns a single line from the underlying range (throws if there is no end-of-lin...
Definition: take_line.hpp:471
Auxiliary header for the view submodule .
::ranges::iterator_t iterator_t
Alias for ranges::iterator_t. Obtains the iterator type of a range.
Definition: ranges:225
Adaptations of concepts from the Ranges TS.
::ranges::sentinel_t sentinel_t
Alias for ranges::sentinel_t. Obtains the sentinel type of a range.
Definition: ranges:220
::ranges::begin begin
Alias for ranges::begin. Returns an iterator to the beginning of a range.
Definition: ranges:185
Provides seqan3::view::all.
The SeqAn3 namespace for views.
Specifies requirements of a Range type for which begin returns a type that models std::ForwardIterato...
Definition: aligned_sequence_concept.hpp:288
Provides C++20 additions to the type_traits header.
typename reference< t >::type reference_t
Type metafunction shortcut for seqan3::reference.
Definition: pre.hpp:98
constexpr auto all
A view that safely wraps a container (you will likely not need to use this unless defining a new view...
Definition: view_all.hpp:95
Provides various metafunctions used by the range module.
Provides various metafunctions for use on iterators.
::ranges::cend cend
Alias for ranges::cend. Returns an iterator to the end of a range.
Definition: ranges:250
Adaptations of concepts from the standard library.
constexpr auto back_inserter(container_t &container)
Create a std::back_insert_iterator for the argument.
Definition: iterator:79
::ranges::end end
Alias for ranges::end. Returns an iterator to the end of a range.
Definition: ranges:190
auto constexpr take_line
A view adaptor that returns a single line from the underlying range or the full range if there is no ...
Definition: take_line.hpp:458