diff --git a/CHANGELOG.md b/CHANGELOG.md index dd0c44b611e..5e2f3a4f61f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -245,6 +245,8 @@ regression test suite and patches at https://github.com/seqan/seqan3/tree/master [\#2541](https://github.com/seqan/seqan3/pull/2541). * We deprecated `seqan3::views::take_line` and it will be removed in 3.1.0 [\#2525](https://github.com/seqan/seqan3/pull/2525). +* We deprecated `seqan3::views::take_until` and it will be removed in 3.1.0. Use `std::views::take_while` in + combination with `std::not_fn` ([\#2604](https://github.com/seqan/seqan3/pull/2604)). * We deprecated `seqan3::views::to_upper` and it will be removed in 3.1.0, use `std::views::transform([](auto && chr){return std::toupper(chr)})`. ([\#2540](https://github.com/seqan/seqan3/pull/2538)) diff --git a/include/seqan3/alphabet/views/trim_quality.hpp b/include/seqan3/alphabet/views/trim_quality.hpp index 4847b94e628..e207626d448 100644 --- a/include/seqan3/alphabet/views/trim_quality.hpp +++ b/include/seqan3/alphabet/views/trim_quality.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include namespace seqan3::detail @@ -55,7 +55,7 @@ struct trim_fn "The threshold must either be a letter of the underlying alphabet or an integral type " "in which case it is compared with the underlying Phred score type."); - return views::take_until(std::forward(irange), [threshold] (auto const value) + return detail::take_until(std::forward(irange), [threshold] (auto const value) { if constexpr (std::same_as, std::remove_cvref_t>>) diff --git a/include/seqan3/io/detail/take_line_view.hpp b/include/seqan3/io/detail/take_line_view.hpp index 39ecfe88ee1..d805b03425d 100644 --- a/include/seqan3/io/detail/take_line_view.hpp +++ b/include/seqan3/io/detail/take_line_view.hpp @@ -12,7 +12,7 @@ #pragma once -#include +#include #include // ============================================================================ @@ -75,7 +75,7 @@ namespace seqan3::detail * On single pass std::ranges::input_range it can be used to tokenise the input stream line-wise: * \include test/snippet/io/detail/take_line_view_tokenise.cpp */ -inline auto constexpr take_line = views::take_until_and_consume(is_char<'\r'> || is_char<'\n'>); +inline auto constexpr take_line = detail::take_until_and_consume(is_char<'\r'> || is_char<'\n'>); // ============================================================================ // detail::take_line_or_throw (adaptor instance definition) @@ -87,7 +87,7 @@ inline auto constexpr take_line = views::take_until_and_consume(is_char<'\r'> || * * \copydetails seqan3::detail::take_line */ -inline auto constexpr take_line_or_throw = views::take_until_or_throw_and_consume(is_char<'\r'> || is_char<'\n'>); +inline auto constexpr take_line_or_throw = detail::take_until_or_throw_and_consume(is_char<'\r'> || is_char<'\n'>); //!\} diff --git a/include/seqan3/io/detail/take_until_view.hpp b/include/seqan3/io/detail/take_until_view.hpp new file mode 100644 index 00000000000..399bc85a709 --- /dev/null +++ b/include/seqan3/io/detail/take_until_view.hpp @@ -0,0 +1,684 @@ +// ----------------------------------------------------------------------------------------------------- +// Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin +// Copyright (c) 2016-2020, Knut Reinert & MPI für molekulare Genetik +// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License +// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md +// ----------------------------------------------------------------------------------------------------- + +/*!\file + * \author Hannes Hauswedell + * \brief Provides seqan3::views::take_until and seqan3::views::take_until_or_throw. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace seqan3::detail +{ + +// ============================================================================ +// view_take_until +// ============================================================================ + +/*!\brief The type returned by seqan3::detail::take_until and seqan3::detail::take_until_or_throw. + * \tparam urng_t The type of the underlying range, must model std::ranges::view. + * \tparam fun_t Type of the callable that will be evaluated on every member; must model + * std::invocable with std::ranges::range_reference_t as argument and return `bool`. + * \tparam or_throw Whether to throw an exception when the input is exhausted before the end of line is reached. + * \implements std::ranges::view + * \implements std::ranges::random_access_range + * \ingroup io + * + * \details + * + * Note that most members of this class are generated by ranges::view_interface which is not yet documented here. + */ +template +class view_take_until : public std::ranges::view_interface> +{ +private: + + static_assert(std::invocable>, + "The functor type for detail::take_until must model" + "std::invocable>."); + static_assert(std::convertible_to)>, bool>, + "The result type of the functor for detail::take_until must be a boolean."); + + //!\brief The underlying range. + urng_t urange; + + //!\brief The functor. + ranges::semiregular_t fun; + + //!\brief Whether this view is const_iterable or not. + static constexpr bool const_iterable = const_iterable_range && + std::regular_invocable>; + + template + class basic_iterator; + + template + class basic_sentinel; + + template + class basic_consume_iterator; + +private: + /*!\name Associated types + * \{ + */ + //!\brief The iterator type of this view (a random access iterator). + using iterator = std::conditional_t, + basic_consume_iterator, + basic_iterator>; + + //!\brief The const_iterator type is equal to the iterator type if the underlying range is const-iterable. + using const_iterator = basic_iterator; + //!\} + +public: + /*!\name Constructors, destructor and assignment + * \{ + */ + view_take_until() = default; //!< Defaulted. + constexpr view_take_until(view_take_until const & rhs) = default; //!< Defaulted. + constexpr view_take_until(view_take_until && rhs) = default; //!< Defaulted. + constexpr view_take_until & operator=(view_take_until const & rhs) = default; //!< Defaulted. + constexpr view_take_until & operator=(view_take_until && rhs) = default; //!< Defaulted. + ~view_take_until() = default; //!< Defaulted. + + /*!\brief Construct from another range. + * \param[in] _urange The underlying range. + * \param[in] _fun The functor that acts as termination criterium. + */ + view_take_until(urng_t _urange, fun_t _fun) + : urange{std::move(_urange)}, fun{std::forward(_fun)} + {} + + /*!\brief Construct from another viewable_range. + * \tparam rng_t Type of the passed range; `urng_t` must be constructible from this. + * \param[in] _urange The underlying range. + * \param[in] _fun The functor that acts as termination criterium. + */ + template + //!\cond + requires std::constructible_from> + //!\endcond + view_take_until(rng_t && _urange, fun_t _fun) + : view_take_until{std::views::all(std::forward(_urange)), std::move(_fun)} + {} + //!\} + + /*!\name Iterators + * \{ + */ + /*!\brief Returns an iterator to the first element of the container. + * \returns Iterator to the first element. + * + * If the container is empty, the returned iterator will be equal to seqan3::detail::take_until::end(). + * + * ### Complexity + * + * Constant. + * + * ### Exceptions + * + * No-throw guarantee. + */ + iterator begin() noexcept + { + return {std::ranges::begin(urange), static_cast(fun), std::ranges::end(urange)}; + } + + //!\copydoc begin() + const_iterator begin() const noexcept + requires const_iterable + { + return {std::ranges::cbegin(urange), static_cast(fun), std::ranges::cend(urange)}; + } + + /*!\brief Returns an iterator to the element following the last element of the range. + * \returns Iterator to the end. + * + * This element acts as a placeholder; attempting to dereference it results in undefined behaviour. + * + * ### Complexity + * + * Constant. + * + * ### Exceptions + * + * No-throw guarantee. + */ + auto end() noexcept + { + if constexpr (and_consume && !std::ranges::forward_range) + return std::ranges::end(urange); + else + return basic_sentinel{std::ranges::end(urange), fun}; + } + + //!\copydoc end() + auto end() const noexcept + requires const_iterable + { + if constexpr (and_consume && !std::ranges::forward_range) + return std::ranges::cend(urange); + else + return basic_sentinel{std::ranges::cend(urange), static_cast(fun)}; + } + //!\} +}; + +//!\brief Type deduction guide that strips references. +//!\relates seqan3::detail::view_take_until +template +view_take_until(urng_t &&, fun_t) -> view_take_until, fun_t, or_throw, and_consume>; + +//!\brief The iterator type inherits from the underlying type, but overwrites several operators. +//!\tparam rng_t Should be `urng_t` for defining #iterator and `urng_t const` for defining #const_iterator. +template +template +class view_take_until::basic_iterator : + public inherited_iterator_base, std::ranges::iterator_t> +{ +private: + //!\brief The iterator type of the underlying range. + using base_base_t = std::ranges::iterator_t; + //!\brief The CRTP wrapper type. + using base_t = inherited_iterator_base>; + //!\brief The sentinel type is identical to that of the underlying range. + using sentinel_type = std::ranges::sentinel_t; + //!\brief Auxiliary type. + using fun_ref_t = std::conditional_t, + std::remove_reference_t const &, + std::remove_reference_t &>; + //!\brief Reference to the functor stored in the view. + seqan3::semiregular_box_t fun; + +public: + /*!\name Constructors, destructor and assignment + * \brief Exceptions specification is implicitly inherited. + * \{ + */ + constexpr basic_iterator() = default; //!< Defaulted. + constexpr basic_iterator(basic_iterator const & rhs) = default; //!< Defaulted. + constexpr basic_iterator(basic_iterator && rhs) = default; //!< Defaulted. + constexpr basic_iterator & operator=(basic_iterator const & rhs) = default; //!< Defaulted. + constexpr basic_iterator & operator=(basic_iterator && rhs) = default; //!< Defaulted. + ~basic_iterator() = default; //!< Defaulted. + + //!\brief Constructor that delegates to the CRTP layer. + basic_iterator(base_base_t it) noexcept(noexcept(base_t{it})) : + base_t{std::move(it)} + {} + + //!\brief Constructor that delegates to the CRTP layer and initialises the callable. + basic_iterator(base_base_t it, + fun_ref_t _fun, + sentinel_type /*only used by the consuming iterator*/) noexcept(noexcept(base_t{it})) : + base_t{std::move(it)}, fun{_fun} + {} + //!\} + + /*!\name Associated types + * \brief All are derived from the base_base_t. + * \{ + */ + + //!\brief The difference type. + using difference_type = std::iter_difference_t; + //!\brief The value type. + using value_type = std::iter_value_t; + //!\brief The reference type. + using reference = std::iter_reference_t; + //!\brief The pointer type. + using pointer = detail::iter_pointer_t; + //!\brief The iterator category tag. + using iterator_category = detail::iterator_category_tag_t; + //!\brief The iterator concept tag. + using iterator_concept = detail::iterator_concept_tag_t; + //!\} +}; + +//!\brief Special iterator type used when consuming behaviour is selected. +//!\tparam rng_t Should be `urng_t` for defining #iterator and `urng_t const` for defining #const_iterator. +template +template +class view_take_until::basic_consume_iterator : + public inherited_iterator_base, std::ranges::iterator_t> +{ +private: + //!\brief The iterator type of the underlying range. + using base_base_t = std::ranges::iterator_t; + //!\brief The CRTP wrapper type. + using base_t = inherited_iterator_base>; + + //!\brief Auxiliary type. + using fun_ref_t = std::conditional_t, + std::remove_reference_t const &, + std::remove_reference_t &>; + //!\brief Reference to the functor stored in the view. + seqan3::semiregular_box_t fun; + + //!\brief The sentinel type is identical to that of the underlying range. + using sentinel_type = std::ranges::sentinel_t; + + //!\brief Whether this iterator has reached the end (cache is only used on pure input ranges). + sentinel_type stored_end; + + //!\brief Whether the end was reached by evaluating the functor. + bool at_end_gracefully = false; + +public: + /*!\name Constructors, destructor and assignment + * \brief Exceptions specification is implicitly inherited. + * \{ + */ + constexpr basic_consume_iterator() = default; //!< Defaulted. + constexpr basic_consume_iterator(basic_consume_iterator const & rhs) = default; //!< Defaulted. + constexpr basic_consume_iterator(basic_consume_iterator && rhs) = default; //!< Defaulted. + constexpr basic_consume_iterator & operator=(basic_consume_iterator const & rhs) = default; //!< Defaulted. + constexpr basic_consume_iterator & operator=(basic_consume_iterator && rhs) = default; //!< Defaulted. + ~basic_consume_iterator() = default; //!< Defaulted. + + //!\brief Constructor that delegates to the CRTP layer and initialises the callable. + basic_consume_iterator(base_base_t it, + fun_ref_t _fun, + sentinel_type sen) noexcept(noexcept(base_t{it})) : + base_t{std::move(it)}, fun{_fun}, stored_end{std::move(sen)} + { + if ((this->base() != stored_end) && fun(**this)) + { + at_end_gracefully = true; + ++(*this); + } + } + //!\} + + /*!\name Associated types + * \brief All are derived from the base_base_t. + * \{ + */ + using difference_type = std::iter_difference_t; //!< From base. + using value_type = std::iter_value_t; //!< From base. + using reference = std::iter_reference_t; //!< From base. + using pointer = detail::iter_pointer_t; //!< From base. + using iterator_category = std::input_iterator_tag; //!< Always input. + //!\} + + /*!\name Arithmetic operators + * \brief seqan3::detail::inherited_iterator_base operators are used unless specialised here. + * \{ + */ + //!\brief Override pre-increment to implement consuming behaviour. + basic_consume_iterator & operator++() + noexcept(noexcept(++std::declval()) && + noexcept(std::declval() != std::declval()) && + noexcept(fun(std::declval()))) + { + base_t::operator++(); + + while ((this->base() != stored_end) && fun(**this)) + { + at_end_gracefully = true; + base_t::operator++(); + } + + return *this; + } + + //!\brief Post-increment implemented via pre-increment. + basic_consume_iterator operator++(int) + noexcept(noexcept(++std::declval()) && + std::is_nothrow_copy_constructible_v) + { + basic_consume_iterator cpy{*this}; + ++(*this); + return cpy; + } + //!\} + /*!\name Comparison operators + * \brief We define comparison against self and against the sentinel. + * \{ + */ + //!\brief Return the saved at_end state. + bool operator==(sentinel_type const & rhs) const + noexcept(!or_throw && + noexcept(std::declval() != std::declval()) && + noexcept(fun(std::declval()))) + { + if (at_end_gracefully) + return true; + + if (this->base() == rhs) + { + if constexpr (or_throw) + throw unexpected_end_of_input{"Reached end of input before functor evaluated to true."}; + else + return true; + } + + return fun(**this); + } + + //!\brief Return the saved at_end state. + friend bool operator==(sentinel_type const & lhs, basic_consume_iterator const & rhs) + noexcept(noexcept(rhs == lhs)) + { + return rhs == lhs; + } + + //!\brief Return the saved at_end state. + bool operator!=(sentinel_type const & rhs) const + noexcept(noexcept(std::declval() == rhs)) + { + return !(*this == rhs); + } + + //!\brief Return the saved at_end state. + friend bool operator!=(sentinel_type const & lhs, basic_consume_iterator const & rhs) + noexcept(noexcept(rhs != lhs)) + { + return rhs != lhs; + } + //!\} +}; + +//!\brief The sentinel type of take_until, provides the comparison operators. +template +template +class view_take_until::basic_sentinel +{ +private: + //!\brief The base type of the underlying range. + using urng_base_type = std::conditional_t, urng_t>; + //!\brief The sentinel type of the underlying range. + using urng_sentinel_type = std::ranges::sentinel_t; + //!\brief Auxiliary type. + using predicate_ref_t = std::conditional_t const &, + std::remove_reference_t &>; + + //!\brief The actual end of the underlying range. + urng_sentinel_type urng_sentinel{}; + + //!\brief Reference to the predicate stored in the view. + seqan3::semiregular_box_t predicate{}; + +public: + /*!\name Constructors, destructor and assignment + * \{ + */ + basic_sentinel() = default; //!< Defaulted. + basic_sentinel(basic_sentinel const &) = default; //!< Defaulted. + basic_sentinel(basic_sentinel &&) = default; //!< Defaulted. + basic_sentinel & operator=(basic_sentinel const &) = default; //!< Defaulted. + basic_sentinel & operator=(basic_sentinel &&) = default; //!< Defaulted. + ~basic_sentinel() = default; //!< Defaulted. + + /*!\brief Construct from a sentinel and a predicate. + * \param[in] urng_sentinel The actual end of the underlying range. + * \param[in] predicate Reference to the predicate stored in the view. + */ + explicit basic_sentinel(urng_sentinel_type urng_sentinel, predicate_ref_t predicate) : + urng_sentinel{std::move(urng_sentinel)}, + predicate{predicate} + {} + + //!\brief Construct from a not const range a const range. + basic_sentinel(basic_sentinel other) + requires is_const_range && std::convertible_to, urng_sentinel_type> + : urng_sentinel{std::move(other.urng_sentinel)}, + predicate{other.predicate} + {} + //!\} + + /*!\name Comparison operators + * \{ + */ + + //!\brief Compares `lhs` with `rhs` for equality. + template + friend bool operator==(basic_iterator const & lhs, basic_sentinel const & rhs) + { + // Actual comparison delegated to lhs base + if (lhs.base() == rhs.urng_sentinel) + { + if constexpr (or_throw) + throw unexpected_end_of_input{"Reached end of input before functor evaluated to true."}; + else + return true; + } + + return rhs.predicate(*lhs); + } + + //!\brief Compares `lhs` with `rhs` for equality. + template + friend bool operator==(basic_sentinel const & lhs, basic_iterator const & rhs) + { + return rhs == lhs; + } + + //!\brief Compares `lhs` with `rhs` for inequality. + template + friend bool operator!=(basic_iterator const & lhs, basic_sentinel const & rhs) + { + return !(lhs == rhs); + } + + //!\brief Compares `lhs` with `rhs` for inequality. + template + friend bool operator!=(basic_sentinel const & lhs, basic_iterator const & rhs) + { + return rhs != lhs; + } + //!\} +}; + +// ============================================================================ +// take_until_fn (adaptor definition) +// ============================================================================ + +/*!\brief View adaptor definition for detail::take_until and detail::take_until_or_throw. + * \tparam or_throw Whether to throw an exception when the input is exhausted before the end of line is reached. + */ +template +struct take_until_fn +{ + //!\brief Store the arguments and return a range adaptor closure object. + template + constexpr auto operator()(fun_t && fun) const + { + return adaptor_from_functor{*this, std::forward(fun)}; + } + + /*!\brief Call the view's constructor with the given parameters. + * \tparam urng_t The underlying range type; must model std::ranges::view. + * \tparam fun_t The type of the callable; concept checks done in class. + * \param[in] urange The underlying range. + * \param[in] fun The callable that will be evaluated on every element. + * \returns An instance of seqan3::detail::view_take_until. + */ + template + constexpr auto operator()(urng_t && urange, fun_t && fun) const + { + return view_take_until, fun_t, or_throw, and_consume> + { + std::views::all(std::forward(urange)), + std::forward(fun) + }; + } +}; + +} // namespace seqan3::detail + +// ============================================================================ +// detail::take_until (adaptor instance definition) +// ============================================================================ + +namespace seqan3::detail +{ + +/*!\name General purpose views + * \{ + */ + +/*!\brief A view adaptor that returns elements from the underlying range until the functor evaluates to + * true (or the end of the underlying range is reached). + * \tparam urng_t The type of the range being processed. See below for requirements. [template parameter is + * omitted in pipe notation] + * \tparam fun_t The type of the functor; must model std::invocable with std::ranges::range_reference_t + * and return a type convertible to `bool`. + * \param[in] urange The range being processed. [parameter is omitted in pipe notation] + * \param[in] fun The functor. + * \returns All elements of the underlying range up until (but excluding) the element that evaluates the + * functor to true. + * \ingroup io + * + * \details + * + * \header_file{seqan3/io/detail/take_until_view.hpp} + * + * ### View properties + * + * | Concepts and traits | `urng_t` (underlying range type) | `rrng_t` (returned range type) | + * |----------------------------------|:-------------------------------------:|:--------------------------------------------------:| + * | std::ranges::input_range | *required* | *preserved* | + * | std::ranges::forward_range | | preserved¹ | + * | std::ranges::bidirectional_range | | preserved¹ | + * | std::ranges::random_access_range | | preserved¹ | + * | std::ranges::contiguous_range | | preserved¹ | + * | | | | + * | std::ranges::viewable_range | *required* | *guaranteed* | + * | std::ranges::view | | *guaranteed* | + * | std::ranges::sized_range | | *lost* | + * | std::ranges::common_range | | *lost* | + * | std::ranges::output_range | | *preserved* | + * | seqan3::const_iterable_range | | preserved¹ | + * | | | | + * | std::ranges::range_reference_t | | std::ranges::range_reference_t | + * + * See the \link views views submodule documentation \endlink for detailed descriptions of the view properties. + * + * ¹ The marked properties are only *preserved* if the specified functor models + * `std::regular_invocable`, i.e. applying the functor doesn't change the functor. + * If the functor only models `std::invocable` and not `std::regular_invocable` these concepts are *lost*. + * + * Throwing: `seqan3::detail::take_until_or_throw` and `seqan3::detail::take_until_or_throw_and_consume` throw an exception + * if the end of the underlying range is reached before their own termination criterium is met. This is useful + * if you want a "strict" evaluation of the functor. + * + * Consuming: `seqan3::detail::take_until_and_consume` and `seqan3::detail::take_until_or_throw_and_consume` behave the + * same as their non-consuming counter-parts if the underlying range models at least `std::ranges::forward_range`. + * If, however, the underlying range is a pure `std::ranges::input_range`, the view will keep moving the underlying + * iterator forward as long as the termination criterium holds and the underlying range is not at end. + * This is useful for string tokenisation among other things. + * + * ### Example + * + * \include test/snippet/io/detail/take_until_view.cpp + * + * \hideinitializer + */ +inline auto constexpr take_until = take_until_fn{}; + +// ============================================================================ +// detail::take_until_or_throw (adaptor instance definition) +// ============================================================================ + +/*!\brief A view adaptor that returns elements from the underlying range until the functor evaluates to true + * (**throws** if the end of the underlying range is reached). + * \throws seqan3::unexpected_end_of_input If the underlying range contains no element that satisfies the functor. + * \ingroup views + * + * \copydetails seqan3::detail::take_until + * \hideinitializer + */ +inline auto constexpr take_until_or_throw = take_until_fn{}; + +// ============================================================================ +// detail::take_until_and_consume (adaptor instance definition) +// ============================================================================ + +/*!\brief A view adaptor that returns elements from the underlying range until the functor evaluates to true + * (or the end of the underlying range is reached and consumes the end in single-pass ranges). + * \throws seqan3::unexpected_end_of_input If the underlying range contains no element that satisfies the functor. + * \ingroup views + * + * \copydetails seqan3::detail::take_until + * \hideinitializer + */ +inline auto constexpr take_until_and_consume = take_until_fn{}; + +// ============================================================================ +// detail::take_until_or_throw_and_consume (adaptor instance definition) +// ============================================================================ + +/*!\brief A view adaptor that returns elements from the underlying range until the functor evaluates to true + * (**throws** if the end of the underlying range is reached and consumes the end in single-pass ranges). + * \throws seqan3::unexpected_end_of_input If the underlying range contains no element that satisfies the functor. + * \ingroup views + * + * \copydetails seqan3::detail::take_until_and_consume + * \hideinitializer + */ +inline auto constexpr take_until_or_throw_and_consume = take_until_fn{}; + +//!\} + +} // namespace seqan3::detail + +namespace seqan3::views +{ + +/*!\brief A view adaptor that returns elements from the underlying range until the functor evaluates to + * true (or the end of the underlying range is reached). + * \ingroup io + * \deprecated Use std::views::take_while with std::not_fn instead. + */ +SEQAN3_DEPRECATED_310 inline auto constexpr take_until = detail::take_until; + +/*!\brief A view adaptor that returns elements from the underlying range until the functor evaluates to true + * (**throws** if the end of the underlying range is reached). + * \throws seqan3::unexpected_end_of_input If the underlying range contains no element that satisfies the functor. + * \ingroup io + * \deprecated Use std::views::take_while with std::not_fn instead. + */ +SEQAN3_DEPRECATED_310 inline auto constexpr take_until_or_throw = detail::take_until_or_throw; + +/*!\brief A view adaptor that returns elements from the underlying range until the functor evaluates to true + * (or the end of the underlying range is reached and consumes the end in single-pass ranges). + * \throws seqan3::unexpected_end_of_input If the underlying range contains no element that satisfies the functor. + * \ingroup views + * + * \deprecated A previous call `view | take_until_and_consume(is_space)` could be convert to + * `view | std::take_while(std::not_fn(is_space)) | std::drop_while(is_space)` + */ +SEQAN3_DEPRECATED_310 inline auto constexpr take_until_and_consume = detail::take_until_and_consume; + +/*!\brief A view adaptor that returns elements from the underlying range until the functor evaluates to true + * (**throws** if the end of the underlying range is reached and consumes the end in single-pass ranges). + * \throws seqan3::unexpected_end_of_input If the underlying range contains no element that satisfies the functor. + * \ingroup views + * \deprecated A previous call `view | take_until_and_consume(is_space)` could be convert to + * `view | std::take_while(std::not_fn(is_space)) | std::drop_while(is_space)` + */ +SEQAN3_DEPRECATED_310 inline auto constexpr take_until_or_throw_and_consume = detail::take_until_fn{}; + +} // namespace seqan3::views diff --git a/include/seqan3/io/sam_file/detail/cigar.hpp b/include/seqan3/io/sam_file/detail/cigar.hpp index 314a1a6e934..d8fd9e0c773 100644 --- a/include/seqan3/io/sam_file/detail/cigar.hpp +++ b/include/seqan3/io/sam_file/detail/cigar.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -146,7 +146,7 @@ inline std::tuple, int32_t, int32_t> parse_cigar(cigar_input_ // ------------------------------------------------------------------------------------------------------------- while (std::ranges::begin(cigar_view) != std::ranges::end(cigar_view)) // until stream is not empty { - auto buff_end = (std::ranges::copy(cigar_view | views::take_until_or_throw(!is_digit), buffer.data())).out; + auto buff_end = (std::ranges::copy(cigar_view | detail::take_until_or_throw(!is_digit), buffer.data())).out; cigar_operation = *std::ranges::begin(cigar_view); std::ranges::next(std::ranges::begin(cigar_view)); diff --git a/include/seqan3/io/sam_file/detail/format_sam_base.hpp b/include/seqan3/io/sam_file/detail/format_sam_base.hpp index 0b12664a749..473c8fb6639 100644 --- a/include/seqan3/io/sam_file/detail/format_sam_base.hpp +++ b/include/seqan3/io/sam_file/detail/format_sam_base.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/include/seqan3/io/sam_file/format_bam.hpp b/include/seqan3/io/sam_file/format_bam.hpp index ddf9955455b..d7ed46c8a89 100644 --- a/include/seqan3/io/sam_file/format_bam.hpp +++ b/include/seqan3/io/sam_file/format_bam.hpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/include/seqan3/io/sam_file/format_sam.hpp b/include/seqan3/io/sam_file/format_sam.hpp index 67513242ef6..b44e3100c6a 100644 --- a/include/seqan3/io/sam_file/format_sam.hpp +++ b/include/seqan3/io/sam_file/format_sam.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -325,7 +325,7 @@ inline void format_sam::read_sequence_record(stream_type & stream, throw parse_error{"The id information must not be empty."}; if (options.truncate_ids) - id = id | views::take_until_and_consume(is_space) | views::to; + id = id | detail::take_until_and_consume(is_space) | views::to; } //!\copydoc sequence_file_output_format::write_sequence_record @@ -409,7 +409,7 @@ inline void format_sam::read_alignment_record(stream_type & stream, "The ref_offset must be a specialisation of std::optional."); auto stream_view = detail::istreambuf(stream); - auto field_view = stream_view | views::take_until_or_throw_and_consume(is_char<'\t'>); + auto field_view = stream_view | detail::take_until_or_throw_and_consume(is_char<'\t'>); // these variables need to be stored to compute the ALIGNMENT int32_t ref_offset_tmp{}; @@ -583,7 +583,7 @@ inline void format_sam::read_alignment_record(stream_type & stream, // Field 11: Quality // ------------------------------------------------------------------------------------------------------------- auto const tab_or_end = is_char<'\t'> || is_char<'\r'> || is_char<'\n'>; - read_field(stream_view | views::take_until_or_throw(tab_or_end), qual); + read_field(stream_view | detail::take_until_or_throw(tab_or_end), qual); if constexpr (!detail::decays_to_ignore_v && !detail::decays_to_ignore_v) { @@ -601,10 +601,10 @@ inline void format_sam::read_alignment_record(stream_type & stream, while (is_char<'\t'>(*std::ranges::begin(stream_view))) // read all tags if present { std::ranges::next(std::ranges::begin(stream_view)); // skip tab - read_field(stream_view | views::take_until_or_throw(tab_or_end), tag_dict); + read_field(stream_view | detail::take_until_or_throw(tab_or_end), tag_dict); } - detail::consume(stream_view | views::take_until(!(is_char<'\r'> || is_char<'\n'>))); // consume new line + detail::consume(stream_view | detail::take_until(!(is_char<'\r'> || is_char<'\n'>))); // consume new line // DONE READING - wrap up // ------------------------------------------------------------------------------------------------------------- @@ -938,7 +938,7 @@ inline void format_sam::read_sam_dict_vector(seqan3::detail::sam_tag_variant & v std::vector tmp_vector; while (std::ranges::begin(stream_view) != ranges::end(stream_view)) // not fully consumed yet { - read_field(stream_view | views::take_until(is_char<','>), value); + read_field(stream_view | detail::take_until(is_char<','>), value); tmp_vector.push_back(value); if (is_char<','>(*std::ranges::begin(stream_view))) diff --git a/include/seqan3/io/sequence_file/format_embl.hpp b/include/seqan3/io/sequence_file/format_embl.hpp index c6ecf08ebc4..74b40205088 100644 --- a/include/seqan3/io/sequence_file/format_embl.hpp +++ b/include/seqan3/io/sequence_file/format_embl.hpp @@ -28,12 +28,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -107,7 +107,7 @@ class format_embl auto stream_it = std::ranges::begin(stream_view); std::string idbuffer; - std::ranges::copy(stream_view | views::take_until_or_throw(is_cntrl || is_blank), + std::ranges::copy(stream_view | detail::take_until_or_throw(is_cntrl || is_blank), std::cpp20::back_inserter(idbuffer)); if (idbuffer != "ID") throw parse_error{"An entry has to start with the code word ID."}; @@ -119,7 +119,7 @@ class format_embl std::ranges::copy(idbuffer | views::char_to>, std::cpp20::back_inserter(id)); do { - std::ranges::copy(stream_view | views::take_until_or_throw(is_char<'S'>) + std::ranges::copy(stream_view | detail::take_until_or_throw(is_char<'S'>) | views::char_to>, std::cpp20::back_inserter(id)); id.push_back(*stream_it); @@ -131,18 +131,18 @@ class format_embl else { // ID - detail::consume(stream_view | views::take_until(!is_blank)); + detail::consume(stream_view | detail::take_until(!is_blank)); // read id if (options.truncate_ids) { - std::ranges::copy(stream_view | views::take_until_or_throw(is_blank || is_char<';'> || is_cntrl) + std::ranges::copy(stream_view | detail::take_until_or_throw(is_blank || is_char<';'> || is_cntrl) | views::char_to>, std::cpp20::back_inserter(id)); } else { - std::ranges::copy(stream_view | views::take_until_or_throw(is_char<';'>) + std::ranges::copy(stream_view | detail::take_until_or_throw(is_char<';'>) | views::char_to>, std::cpp20::back_inserter(id)); } @@ -154,7 +154,7 @@ class format_embl { do { - detail::consume(stream_view | views::take_until_or_throw(is_char<'S'>)); + detail::consume(stream_view | detail::take_until_or_throw(is_char<'S'>)); ++stream_it; } while (*stream_it != 'Q'); } @@ -165,7 +165,7 @@ class format_embl if constexpr (!detail::decays_to_ignore_v) { auto seq_view = stream_view | std::views::filter(!(is_space || is_digit)) // ignore whitespace and numbers - | views::take_until_or_throw(is_end); // until // + | detail::take_until_or_throw(is_end); // until // auto constexpr is_legal_alph = char_is_valid_for; std::ranges::copy(seq_view | std::views::transform([is_legal_alph] (char const c) // enforce legal alphabet @@ -185,7 +185,7 @@ class format_embl } else { - detail::consume(stream_view | views::take_until(is_end)); + detail::consume(stream_view | detail::take_until(is_end)); } //Jump over // and cntrl ++stream_it; diff --git a/include/seqan3/io/sequence_file/format_fasta.hpp b/include/seqan3/io/sequence_file/format_fasta.hpp index 1d281768c35..f8529c04ace 100644 --- a/include/seqan3/io/sequence_file/format_fasta.hpp +++ b/include/seqan3/io/sequence_file/format_fasta.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,6 @@ #include #include #include -#include #include #include @@ -213,7 +213,7 @@ class format_fasta #else // ↑↑↑ WORKAROUND | ORIGINAL ↓↓↓ std::ranges::copy(stream_view | std::views::drop_while(is_id || is_blank) // skip leading > - | views::take_until_or_throw(is_cntrl || is_blank) // read ID until delimiter… + | detail::take_until_or_throw(is_cntrl || is_blank) // read ID until delimiter… | views::char_to>, std::cpp20::back_inserter(id)); // … ^A is old delimiter @@ -301,7 +301,7 @@ class format_fasta if (std::ranges::begin(stream_view) == std::ranges::end(stream_view)) throw unexpected_end_of_input{"No sequence information given!"}; - std::ranges::copy(stream_view | views::take_until(is_id) // until next header (or end) + std::ranges::copy(stream_view | detail::take_until(is_id) // until next header (or end) | std::views::filter(!(is_space || is_digit))// ignore whitespace and numbers | std::views::transform([is_legal_alph] (char const c) { @@ -321,7 +321,7 @@ class format_fasta } else { - detail::consume(stream_view | views::take_until(is_id)); + detail::consume(stream_view | detail::take_until(is_id)); } } diff --git a/include/seqan3/io/sequence_file/format_fastq.hpp b/include/seqan3/io/sequence_file/format_fastq.hpp index 504d1c7edbf..2600d98c688 100644 --- a/include/seqan3/io/sequence_file/format_fastq.hpp +++ b/include/seqan3/io/sequence_file/format_fastq.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,6 @@ #include #include #include -#include #include #include @@ -131,7 +131,7 @@ class format_fastq { if (options.truncate_ids) { - std::ranges::copy(stream_view | views::take_until_or_throw(is_cntrl || is_blank) + std::ranges::copy(stream_view | detail::take_until_or_throw(is_cntrl || is_blank) | views::char_to>, std::cpp20::back_inserter(id)); detail::consume(stream_view | detail::take_line_or_throw); @@ -149,7 +149,7 @@ class format_fastq } /* Sequence */ - auto seq_view = stream_view | views::take_until_or_throw(is_char<'+'>) // until 2nd ID line + auto seq_view = stream_view | detail::take_until_or_throw(is_char<'+'>) // until 2nd ID line | std::views::filter(!is_space); // ignore whitespace if constexpr (!detail::decays_to_ignore_v) { diff --git a/include/seqan3/io/sequence_file/format_genbank.hpp b/include/seqan3/io/sequence_file/format_genbank.hpp index 472ed9bdb4e..0040608e91e 100644 --- a/include/seqan3/io/sequence_file/format_genbank.hpp +++ b/include/seqan3/io/sequence_file/format_genbank.hpp @@ -29,12 +29,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -108,7 +108,7 @@ class format_genbank auto stream_view = detail::istreambuf(stream); auto stream_it = std::ranges::begin(stream_view); - if (!(std::ranges::equal(stream_view | views::take_until_or_throw(is_cntrl || is_blank), std::string{"LOCUS"}))) + if (!(std::ranges::equal(stream_view | detail::take_until_or_throw(is_cntrl || is_blank), std::string{"LOCUS"}))) throw parse_error{"An entry has to start with the code word LOCUS."}; //ID @@ -128,11 +128,11 @@ class format_genbank } else { - detail::consume(stream_view | views::take_until(!is_blank)); + detail::consume(stream_view | detail::take_until(!is_blank)); auto read_id_until = [&stream_view, &id] (auto predicate) { - std::ranges::copy(stream_view | views::take_until_or_throw(predicate) + std::ranges::copy(stream_view | detail::take_until_or_throw(predicate) | views::char_to>, std::cpp20::back_inserter(id)); }; @@ -157,7 +157,7 @@ class format_genbank { auto constexpr is_legal_alph = char_is_valid_for; std::ranges::copy(stream_view | std::views::filter(!(is_space || is_digit)) - | views::take_until_or_throw_and_consume(is_end) // consume "//" + | detail::take_until_or_throw_and_consume(is_end) // consume "//" | std::views::transform([is_legal_alph] (char const c) // enforce legal alphabet { if (!is_legal_alph(c)) @@ -175,7 +175,7 @@ class format_genbank } else { - detail::consume(stream_view | views::take_until_or_throw_and_consume(is_end)); // consume until "//" + detail::consume(stream_view | detail::take_until_or_throw_and_consume(is_end)); // consume until "//" ++stream_it; // consume "/n" } } diff --git a/include/seqan3/io/structure_file/format_vienna.hpp b/include/seqan3/io/structure_file/format_vienna.hpp index b042a800bc8..622dc2eb253 100644 --- a/include/seqan3/io/structure_file/format_vienna.hpp +++ b/include/seqan3/io/structure_file/format_vienna.hpp @@ -32,13 +32,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -140,7 +140,7 @@ class format_vienna if (options.truncate_ids) { std::ranges::copy(stream_view | std::views::drop_while(is_id || is_blank) // skip leading > - | views::take_until_or_throw(is_cntrl || is_blank) + | detail::take_until_or_throw(is_cntrl || is_blank) | views::char_to>, std::cpp20::back_inserter(id)); detail::consume(stream_view | detail::take_line_or_throw); @@ -229,7 +229,7 @@ class format_vienna } else { - detail::consume(stream_view | views::take_until(is_space)); // until whitespace + detail::consume(stream_view | detail::take_until(is_space)); // until whitespace } if constexpr (!detail::decays_to_ignore_v && @@ -259,7 +259,7 @@ class format_vienna { detail::consume(stream_view | detail::take_line); } - detail::consume(stream_view | views::take_until(!is_space)); + detail::consume(stream_view | detail::take_until(!is_space)); } //!\copydoc seqan3::structure_file_output_format::write_structure_record @@ -366,7 +366,7 @@ class format_vienna auto read_structure(stream_view_type & stream_view) { auto constexpr is_legal_structure = char_is_valid_for; - return stream_view | views::take_until(is_space) // until whitespace + return stream_view | detail::take_until(is_space) // until whitespace | std::views::transform([is_legal_structure](char const c) { if (!is_legal_structure(c)) diff --git a/include/seqan3/range/views/all.hpp b/include/seqan3/range/views/all.hpp index 90905c28234..84e96be40ee 100644 --- a/include/seqan3/range/views/all.hpp +++ b/include/seqan3/range/views/all.hpp @@ -25,7 +25,6 @@ #endif // SEQAN3_DEPRECATED_310 #include #include -#include #include #include #include diff --git a/include/seqan3/range/views/take_until.hpp b/include/seqan3/range/views/take_until.hpp index 8ac968b9db5..f337ddd562a 100644 --- a/include/seqan3/range/views/take_until.hpp +++ b/include/seqan3/range/views/take_until.hpp @@ -6,640 +6,13 @@ // ----------------------------------------------------------------------------------------------------- /*!\file + * \brief [DEPRECATED] Provides seqan3::views::take_until. * \author Hannes Hauswedell - * \brief Provides seqan3::views::take_until and seqan3::views::take_until_or_throw. */ #pragma once -#include -#include -#include -#include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace seqan3::detail -{ - -// ============================================================================ -// view_take_until -// ============================================================================ - -/*!\brief The type returned by seqan3::views::take_until and seqan3::views::take_until_or_throw. - * \tparam urng_t The type of the underlying range, must model std::ranges::view. - * \tparam fun_t Type of the callable that will be evaluated on every member; must model - * std::invocable with std::ranges::range_reference_t as argument and return `bool`. - * \tparam or_throw Whether to throw an exception when the input is exhausted before the end of line is reached. - * \implements std::ranges::view - * \implements std::ranges::random_access_range - * \ingroup views - * - * \details - * - * Note that most members of this class are generated by ranges::view_interface which is not yet documented here. - */ -template -class view_take_until : public std::ranges::view_interface> -{ -private: - - static_assert(std::invocable>, - "The functor type for views::take_until must model" - "std::invocable>."); - static_assert(std::convertible_to)>, bool>, - "The result type of the functor for views::take_until must be a boolean."); - - //!\brief The underlying range. - urng_t urange; - - //!\brief The functor. - ranges::semiregular_t fun; - - //!\brief Whether this view is const_iterable or not. - static constexpr bool const_iterable = const_iterable_range && - std::regular_invocable>; - - template - class basic_iterator; - - template - class basic_sentinel; - - template - class basic_consume_iterator; - -private: - /*!\name Associated types - * \{ - */ - //!\brief The iterator type of this view (a random access iterator). - using iterator = std::conditional_t, - basic_consume_iterator, - basic_iterator>; - - //!\brief The const_iterator type is equal to the iterator type if the underlying range is const-iterable. - using const_iterator = basic_iterator; - //!\} - -public: - /*!\name Constructors, destructor and assignment - * \{ - */ - view_take_until() = default; //!< Defaulted. - constexpr view_take_until(view_take_until const & rhs) = default; //!< Defaulted. - constexpr view_take_until(view_take_until && rhs) = default; //!< Defaulted. - constexpr view_take_until & operator=(view_take_until const & rhs) = default; //!< Defaulted. - constexpr view_take_until & operator=(view_take_until && rhs) = default; //!< Defaulted. - ~view_take_until() = default; //!< Defaulted. - - /*!\brief Construct from another range. - * \param[in] _urange The underlying range. - * \param[in] _fun The functor that acts as termination criterium. - */ - view_take_until(urng_t _urange, fun_t _fun) - : urange{std::move(_urange)}, fun{std::forward(_fun)} - {} - - /*!\brief Construct from another viewable_range. - * \tparam rng_t Type of the passed range; `urng_t` must be constructible from this. - * \param[in] _urange The underlying range. - * \param[in] _fun The functor that acts as termination criterium. - */ - template - //!\cond - requires std::constructible_from> - //!\endcond - view_take_until(rng_t && _urange, fun_t _fun) - : view_take_until{std::views::all(std::forward(_urange)), std::move(_fun)} - {} - //!\} - - /*!\name Iterators - * \{ - */ - /*!\brief Returns an iterator to the first element of the container. - * \returns Iterator to the first element. - * - * If the container is empty, the returned iterator will be equal to seqan3::views::take_until::end(). - * - * ### Complexity - * - * Constant. - * - * ### Exceptions - * - * No-throw guarantee. - */ - iterator begin() noexcept - { - return {std::ranges::begin(urange), static_cast(fun), std::ranges::end(urange)}; - } - - //!\copydoc begin() - const_iterator begin() const noexcept - requires const_iterable - { - return {std::ranges::cbegin(urange), static_cast(fun), std::ranges::cend(urange)}; - } - - /*!\brief Returns an iterator to the element following the last element of the range. - * \returns Iterator to the end. - * - * This element acts as a placeholder; attempting to dereference it results in undefined behaviour. - * - * ### Complexity - * - * Constant. - * - * ### Exceptions - * - * No-throw guarantee. - */ - auto end() noexcept - { - if constexpr (and_consume && !std::ranges::forward_range) - return std::ranges::end(urange); - else - return basic_sentinel{std::ranges::end(urange), fun}; - } - - //!\copydoc end() - auto end() const noexcept - requires const_iterable - { - if constexpr (and_consume && !std::ranges::forward_range) - return std::ranges::cend(urange); - else - return basic_sentinel{std::ranges::cend(urange), static_cast(fun)}; - } - //!\} -}; - -//!\brief Type deduction guide that strips references. -//!\relates seqan3::detail::view_take_until -template -view_take_until(urng_t &&, fun_t) -> view_take_until, fun_t, or_throw, and_consume>; - -//!\brief The iterator type inherits from the underlying type, but overwrites several operators. -//!\tparam rng_t Should be `urng_t` for defining #iterator and `urng_t const` for defining #const_iterator. -template -template -class view_take_until::basic_iterator : - public inherited_iterator_base, std::ranges::iterator_t> -{ -private: - //!\brief The iterator type of the underlying range. - using base_base_t = std::ranges::iterator_t; - //!\brief The CRTP wrapper type. - using base_t = inherited_iterator_base>; - //!\brief The sentinel type is identical to that of the underlying range. - using sentinel_type = std::ranges::sentinel_t; - //!\brief Auxiliary type. - using fun_ref_t = std::conditional_t, - std::remove_reference_t const &, - std::remove_reference_t &>; - //!\brief Reference to the functor stored in the view. - seqan3::semiregular_box_t fun; - -public: - /*!\name Constructors, destructor and assignment - * \brief Exceptions specification is implicitly inherited. - * \{ - */ - constexpr basic_iterator() = default; //!< Defaulted. - constexpr basic_iterator(basic_iterator const & rhs) = default; //!< Defaulted. - constexpr basic_iterator(basic_iterator && rhs) = default; //!< Defaulted. - constexpr basic_iterator & operator=(basic_iterator const & rhs) = default; //!< Defaulted. - constexpr basic_iterator & operator=(basic_iterator && rhs) = default; //!< Defaulted. - ~basic_iterator() = default; //!< Defaulted. - - //!\brief Constructor that delegates to the CRTP layer. - basic_iterator(base_base_t it) noexcept(noexcept(base_t{it})) : - base_t{std::move(it)} - {} - - //!\brief Constructor that delegates to the CRTP layer and initialises the callable. - basic_iterator(base_base_t it, - fun_ref_t _fun, - sentinel_type /*only used by the consuming iterator*/) noexcept(noexcept(base_t{it})) : - base_t{std::move(it)}, fun{_fun} - {} - //!\} - - /*!\name Associated types - * \brief All are derived from the base_base_t. - * \{ - */ - - //!\brief The difference type. - using difference_type = std::iter_difference_t; - //!\brief The value type. - using value_type = std::iter_value_t; - //!\brief The reference type. - using reference = std::iter_reference_t; - //!\brief The pointer type. - using pointer = detail::iter_pointer_t; - //!\brief The iterator category tag. - using iterator_category = detail::iterator_category_tag_t; - //!\brief The iterator concept tag. - using iterator_concept = detail::iterator_concept_tag_t; - //!\} -}; - -//!\brief Special iterator type used when consuming behaviour is selected. -//!\tparam rng_t Should be `urng_t` for defining #iterator and `urng_t const` for defining #const_iterator. -template -template -class view_take_until::basic_consume_iterator : - public inherited_iterator_base, std::ranges::iterator_t> -{ -private: - //!\brief The iterator type of the underlying range. - using base_base_t = std::ranges::iterator_t; - //!\brief The CRTP wrapper type. - using base_t = inherited_iterator_base>; - - //!\brief Auxiliary type. - using fun_ref_t = std::conditional_t, - std::remove_reference_t const &, - std::remove_reference_t &>; - //!\brief Reference to the functor stored in the view. - seqan3::semiregular_box_t fun; - - //!\brief The sentinel type is identical to that of the underlying range. - using sentinel_type = std::ranges::sentinel_t; - - //!\brief Whether this iterator has reached the end (cache is only used on pure input ranges). - sentinel_type stored_end; - - //!\brief Whether the end was reached by evaluating the functor. - bool at_end_gracefully = false; - -public: - /*!\name Constructors, destructor and assignment - * \brief Exceptions specification is implicitly inherited. - * \{ - */ - constexpr basic_consume_iterator() = default; //!< Defaulted. - constexpr basic_consume_iterator(basic_consume_iterator const & rhs) = default; //!< Defaulted. - constexpr basic_consume_iterator(basic_consume_iterator && rhs) = default; //!< Defaulted. - constexpr basic_consume_iterator & operator=(basic_consume_iterator const & rhs) = default; //!< Defaulted. - constexpr basic_consume_iterator & operator=(basic_consume_iterator && rhs) = default; //!< Defaulted. - ~basic_consume_iterator() = default; //!< Defaulted. - - //!\brief Constructor that delegates to the CRTP layer and initialises the callable. - basic_consume_iterator(base_base_t it, - fun_ref_t _fun, - sentinel_type sen) noexcept(noexcept(base_t{it})) : - base_t{std::move(it)}, fun{_fun}, stored_end{std::move(sen)} - { - if ((this->base() != stored_end) && fun(**this)) - { - at_end_gracefully = true; - ++(*this); - } - } - //!\} - - /*!\name Associated types - * \brief All are derived from the base_base_t. - * \{ - */ - using difference_type = std::iter_difference_t; //!< From base. - using value_type = std::iter_value_t; //!< From base. - using reference = std::iter_reference_t; //!< From base. - using pointer = detail::iter_pointer_t; //!< From base. - using iterator_category = std::input_iterator_tag; //!< Always input. - //!\} - - /*!\name Arithmetic operators - * \brief seqan3::detail::inherited_iterator_base operators are used unless specialised here. - * \{ - */ - //!\brief Override pre-increment to implement consuming behaviour. - basic_consume_iterator & operator++() - noexcept(noexcept(++std::declval()) && - noexcept(std::declval() != std::declval()) && - noexcept(fun(std::declval()))) - { - base_t::operator++(); - - while ((this->base() != stored_end) && fun(**this)) - { - at_end_gracefully = true; - base_t::operator++(); - } - - return *this; - } - - //!\brief Post-increment implemented via pre-increment. - basic_consume_iterator operator++(int) - noexcept(noexcept(++std::declval()) && - std::is_nothrow_copy_constructible_v) - { - basic_consume_iterator cpy{*this}; - ++(*this); - return cpy; - } - //!\} - /*!\name Comparison operators - * \brief We define comparison against self and against the sentinel. - * \{ - */ - //!\brief Return the saved at_end state. - bool operator==(sentinel_type const & rhs) const - noexcept(!or_throw && - noexcept(std::declval() != std::declval()) && - noexcept(fun(std::declval()))) - { - if (at_end_gracefully) - return true; - - if (this->base() == rhs) - { - if constexpr (or_throw) - throw unexpected_end_of_input{"Reached end of input before functor evaluated to true."}; - else - return true; - } - - return fun(**this); - } - - //!\brief Return the saved at_end state. - friend bool operator==(sentinel_type const & lhs, basic_consume_iterator const & rhs) - noexcept(noexcept(rhs == lhs)) - { - return rhs == lhs; - } - - //!\brief Return the saved at_end state. - bool operator!=(sentinel_type const & rhs) const - noexcept(noexcept(std::declval() == rhs)) - { - return !(*this == rhs); - } - - //!\brief Return the saved at_end state. - friend bool operator!=(sentinel_type const & lhs, basic_consume_iterator const & rhs) - noexcept(noexcept(rhs != lhs)) - { - return rhs != lhs; - } - //!\} -}; - -//!\brief The sentinel type of take_until, provides the comparison operators. -template -template -class view_take_until::basic_sentinel -{ -private: - //!\brief The base type of the underlying range. - using urng_base_type = std::conditional_t, urng_t>; - //!\brief The sentinel type of the underlying range. - using urng_sentinel_type = std::ranges::sentinel_t; - //!\brief Auxiliary type. - using predicate_ref_t = std::conditional_t const &, - std::remove_reference_t &>; - - //!\brief The actual end of the underlying range. - urng_sentinel_type urng_sentinel{}; - - //!\brief Reference to the predicate stored in the view. - seqan3::semiregular_box_t predicate{}; - -public: - /*!\name Constructors, destructor and assignment - * \{ - */ - basic_sentinel() = default; //!< Defaulted. - basic_sentinel(basic_sentinel const &) = default; //!< Defaulted. - basic_sentinel(basic_sentinel &&) = default; //!< Defaulted. - basic_sentinel & operator=(basic_sentinel const &) = default; //!< Defaulted. - basic_sentinel & operator=(basic_sentinel &&) = default; //!< Defaulted. - ~basic_sentinel() = default; //!< Defaulted. - - /*!\brief Construct from a sentinel and a predicate. - * \param[in] urng_sentinel The actual end of the underlying range. - * \param[in] predicate Reference to the predicate stored in the view. - */ - explicit basic_sentinel(urng_sentinel_type urng_sentinel, predicate_ref_t predicate) : - urng_sentinel{std::move(urng_sentinel)}, - predicate{predicate} - {} - - //!\brief Construct from a not const range a const range. - basic_sentinel(basic_sentinel other) - requires is_const_range && std::convertible_to, urng_sentinel_type> - : urng_sentinel{std::move(other.urng_sentinel)}, - predicate{other.predicate} - {} - //!\} - - /*!\name Comparison operators - * \{ - */ - - //!\brief Compares `lhs` with `rhs` for equality. - template - friend bool operator==(basic_iterator const & lhs, basic_sentinel const & rhs) - { - // Actual comparison delegated to lhs base - if (lhs.base() == rhs.urng_sentinel) - { - if constexpr (or_throw) - throw unexpected_end_of_input{"Reached end of input before functor evaluated to true."}; - else - return true; - } - - return rhs.predicate(*lhs); - } - - //!\brief Compares `lhs` with `rhs` for equality. - template - friend bool operator==(basic_sentinel const & lhs, basic_iterator const & rhs) - { - return rhs == lhs; - } - - //!\brief Compares `lhs` with `rhs` for inequality. - template - friend bool operator!=(basic_iterator const & lhs, basic_sentinel const & rhs) - { - return !(lhs == rhs); - } - - //!\brief Compares `lhs` with `rhs` for inequality. - template - friend bool operator!=(basic_sentinel const & lhs, basic_iterator const & rhs) - { - return rhs != lhs; - } - //!\} -}; - -// ============================================================================ -// take_until_fn (adaptor definition) -// ============================================================================ - -/*!\brief View adaptor definition for views::take_until and views::take_until_or_throw. - * \tparam or_throw Whether to throw an exception when the input is exhausted before the end of line is reached. - */ -template -struct take_until_fn -{ - //!\brief Store the arguments and return a range adaptor closure object. - template - constexpr auto operator()(fun_t && fun) const - { - return adaptor_from_functor{*this, std::forward(fun)}; - } - - /*!\brief Call the view's constructor with the given parameters. - * \tparam urng_t The underlying range type; must model std::ranges::view. - * \tparam fun_t The type of the callable; concept checks done in class. - * \param[in] urange The underlying range. - * \param[in] fun The callable that will be evaluated on every element. - * \returns An instance of seqan3::detail::view_take_until. - */ - template - constexpr auto operator()(urng_t && urange, fun_t && fun) const - { - return view_take_until, fun_t, or_throw, and_consume> - { - std::views::all(std::forward(urange)), - std::forward(fun) - }; - } -}; - -} // namespace seqan3::detail - -// ============================================================================ -// views::take_until (adaptor instance definition) -// ============================================================================ - -namespace seqan3::views -{ - -/*!\name General purpose views - * \{ - */ - -/*!\brief A view adaptor that returns elements from the underlying range until the functor evaluates to - * true (or the end of the underlying range is reached). - * \tparam urng_t The type of the range being processed. See below for requirements. [template parameter is - * omitted in pipe notation] - * \tparam fun_t The type of the functor; must model std::invocable with std::ranges::range_reference_t - * and return a type convertible to `bool`. - * \param[in] urange The range being processed. [parameter is omitted in pipe notation] - * \param[in] fun The functor. - * \returns All elements of the underlying range up until (but excluding) the element that evaluates the - * functor to true. - * \ingroup views - * - * \details - * - * \header_file{seqan3/range/views/take_until.hpp} - * - * ### View properties - * - * | Concepts and traits | `urng_t` (underlying range type) | `rrng_t` (returned range type) | - * |----------------------------------|:-------------------------------------:|:--------------------------------------------------:| - * | std::ranges::input_range | *required* | *preserved* | - * | std::ranges::forward_range | | preserved¹ | - * | std::ranges::bidirectional_range | | preserved¹ | - * | std::ranges::random_access_range | | preserved¹ | - * | std::ranges::contiguous_range | | preserved¹ | - * | | | | - * | std::ranges::viewable_range | *required* | *guaranteed* | - * | std::ranges::view | | *guaranteed* | - * | std::ranges::sized_range | | *lost* | - * | std::ranges::common_range | | *lost* | - * | std::ranges::output_range | | *preserved* | - * | seqan3::const_iterable_range | | preserved¹ | - * | | | | - * | std::ranges::range_reference_t | | std::ranges::range_reference_t | - * - * See the \link views views submodule documentation \endlink for detailed descriptions of the view properties. - * - * ¹ The marked properties are only *preserved* if the specified functor models - * `std::regular_invocable`, i.e. applying the functor doesn't change the functor. - * If the functor only models `std::invocable` and not `std::regular_invocable` these concepts are *lost*. - * - * Throwing: `seqan3::views::take_until_or_throw` and `seqan3::views::take_until_or_throw_and_consume` throw an exception - * if the end of the underlying range is reached before their own termination criterium is met. This is useful - * if you want a "strict" evaluation of the functor. - * - * Consuming: `seqan3::views::take_until_and_consume` and `seqan3::views::take_until_or_throw_and_consume` behave the same - * as their non-consuming counter-parts if the underlying range models at least `std::forward_range`. - * If, however, the underlying range is a pure `std::input_range`, the view will keep moving the underlying - * iterator forward as long as the termination criterium holds and the underlying range is not at end. - * This is useful for string tokenisation among other things. - * - * ### Example - * - * \include test/snippet/range/views/take_until.cpp - * - * \hideinitializer - */ -inline auto constexpr take_until = detail::take_until_fn{}; - -// ============================================================================ -// views::take_until_or_throw (adaptor instance definition) -// ============================================================================ - -/*!\brief A view adaptor that returns elements from the underlying range until the functor evaluates to true - * (**throws** if the end of the underlying range is reached). - * \throws seqan3::unexpected_end_of_input If the underlying range contains no element that satisfies the functor. - * \ingroup views - * - * \copydetails seqan3::views::take_until - * \hideinitializer - */ -inline auto constexpr take_until_or_throw = detail::take_until_fn{}; - -// ============================================================================ -// views::take_until_and_consume (adaptor instance definition) -// ============================================================================ - -/*!\brief A view adaptor that returns elements from the underlying range until the functor evaluates to true - * (or the end of the underlying range is reached; consumes end in single-pass ranges). - * \throws seqan3::unexpected_end_of_input If the underlying range contains no element that satisfies the functor. - * \ingroup views - * - * \copydetails seqan3::views::take_until - * \hideinitializer - */ -inline auto constexpr take_until_and_consume = detail::take_until_fn{}; - -// ============================================================================ -// views::take_until_or_throw_and_consume (adaptor instance definition) -// ============================================================================ - -/*!\brief A view adaptor that returns elements from the underlying range until the functor evaluates to true - * (**throws** if the end of the underlying range is reached; consumes end in single-pass ranges). - * \throws seqan3::unexpected_end_of_input If the underlying range contains no element that satisfies the functor. - * \ingroup views - * - * \copydetails seqan3::views::take_until - * \hideinitializer - */ -inline auto constexpr take_until_or_throw_and_consume = detail::take_until_fn{}; - -//!\} - -} // namespace seqan3::views +SEQAN3_DEPRECATED_HEADER( + "This header is deprecated and will be removed in SeqAn-3.1.0; Please #include instead.") diff --git a/test/performance/io/CMakeLists.txt b/test/performance/io/CMakeLists.txt index 4235a03c2d8..ce40b475866 100644 --- a/test/performance/io/CMakeLists.txt +++ b/test/performance/io/CMakeLists.txt @@ -1,3 +1,5 @@ +add_subdirectories () + seqan3_benchmark(format_fasta_benchmark.cpp) seqan3_benchmark(format_fastq_benchmark.cpp) seqan3_benchmark(format_sam_benchmark.cpp) diff --git a/test/performance/io/detail/CMakeLists.txt b/test/performance/io/detail/CMakeLists.txt new file mode 100644 index 00000000000..0ee3d26a634 --- /dev/null +++ b/test/performance/io/detail/CMakeLists.txt @@ -0,0 +1 @@ +seqan3_benchmark(view_take_until_benchmark.cpp) diff --git a/test/performance/range/views/view_take_until_benchmark.cpp b/test/performance/io/detail/view_take_until_benchmark.cpp similarity index 86% rename from test/performance/range/views/view_take_until_benchmark.cpp rename to test/performance/io/detail/view_take_until_benchmark.cpp index 37c4ad806ff..d33faacce80 100644 --- a/test/performance/range/views/view_take_until_benchmark.cpp +++ b/test/performance/io/detail/view_take_until_benchmark.cpp @@ -13,7 +13,7 @@ #include -#include +#include #include #include @@ -81,67 +81,67 @@ void sequential_read(benchmark::State & state) // runs with chained adaptor (cannot use or_throw here) BENCHMARK_TEMPLATE(sequential_read, std::string, void, false); BENCHMARK_TEMPLATE(sequential_read, std::string, decltype(std::views::take_while), true); -BENCHMARK_TEMPLATE(sequential_read, std::string, decltype(seqan3::views::take_until), false); +BENCHMARK_TEMPLATE(sequential_read, std::string, decltype(seqan3::detail::take_until), false); BENCHMARK_TEMPLATE(sequential_read, std::vector, void, false); BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(std::views::take_while), true); -BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(seqan3::views::take_until), false); +BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(seqan3::detail::take_until), false); BENCHMARK_TEMPLATE(sequential_read, std::deque, void, false); BENCHMARK_TEMPLATE(sequential_read, std::deque, decltype(std::views::take_while), true); -BENCHMARK_TEMPLATE(sequential_read, std::deque, decltype(seqan3::views::take_until), false); +BENCHMARK_TEMPLATE(sequential_read, std::deque, decltype(seqan3::detail::take_until), false); BENCHMARK_TEMPLATE(sequential_read, std::list, void, false); BENCHMARK_TEMPLATE(sequential_read, std::list, decltype(std::views::take_while), true); -BENCHMARK_TEMPLATE(sequential_read, std::list, decltype(seqan3::views::take_until), false); +BENCHMARK_TEMPLATE(sequential_read, std::list, decltype(seqan3::detail::take_until), false); BENCHMARK_TEMPLATE(sequential_read, std::forward_list, void, false); BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(std::views::take_while), true); -BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(seqan3::views::take_until), false); +BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(seqan3::detail::take_until), false); BENCHMARK_TEMPLATE(sequential_read, std::vector, void, false, true); BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(std::views::take_while), true, true); -BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(seqan3::views::take_until), false, true); +BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(seqan3::detail::take_until), false, true); BENCHMARK_TEMPLATE(sequential_read, std::forward_list, void, false, true); BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(std::views::take_while), true, true); -BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(seqan3::views::take_until), false, true); +BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(seqan3::detail::take_until), false, true); // runs with one adaptor BENCHMARK_TEMPLATE(sequential_read, std::string, void, false, false, false); BENCHMARK_TEMPLATE(sequential_read, std::string, decltype(std::views::take_while), true, false, false); -BENCHMARK_TEMPLATE(sequential_read, std::string, decltype(seqan3::views::take_until), false, false, false); -BENCHMARK_TEMPLATE(sequential_read, std::string, decltype(seqan3::views::take_until_or_throw), false, false, false); +BENCHMARK_TEMPLATE(sequential_read, std::string, decltype(seqan3::detail::take_until), false, false, false); +BENCHMARK_TEMPLATE(sequential_read, std::string, decltype(seqan3::detail::take_until_or_throw), false, false, false); BENCHMARK_TEMPLATE(sequential_read, std::vector, void, false, false, false); BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(std::views::take_while), true, false, false); -BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(seqan3::views::take_until), false, false, false); -BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(seqan3::views::take_until_or_throw), false, false, false); +BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(seqan3::detail::take_until), false, false, false); +BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(seqan3::detail::take_until_or_throw), false, false, false); BENCHMARK_TEMPLATE(sequential_read, std::deque, void, false, false, false); BENCHMARK_TEMPLATE(sequential_read, std::deque, decltype(std::views::take_while), true, false, false); -BENCHMARK_TEMPLATE(sequential_read, std::deque, decltype(seqan3::views::take_until), false, false, false); -BENCHMARK_TEMPLATE(sequential_read, std::deque, decltype(seqan3::views::take_until_or_throw), false, false, false); +BENCHMARK_TEMPLATE(sequential_read, std::deque, decltype(seqan3::detail::take_until), false, false, false); +BENCHMARK_TEMPLATE(sequential_read, std::deque, decltype(seqan3::detail::take_until_or_throw), false, false, false); BENCHMARK_TEMPLATE(sequential_read, std::list, void, false, false, false); BENCHMARK_TEMPLATE(sequential_read, std::list, decltype(std::views::take_while), true, false, false); -BENCHMARK_TEMPLATE(sequential_read, std::list, decltype(seqan3::views::take_until), false, false, false); -BENCHMARK_TEMPLATE(sequential_read, std::list, decltype(seqan3::views::take_until_or_throw), false, false, false); +BENCHMARK_TEMPLATE(sequential_read, std::list, decltype(seqan3::detail::take_until), false, false, false); +BENCHMARK_TEMPLATE(sequential_read, std::list, decltype(seqan3::detail::take_until_or_throw), false, false, false); BENCHMARK_TEMPLATE(sequential_read, std::forward_list, void, false, false, false); BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(std::views::take_while), true, false, false); -BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(seqan3::views::take_until), false, false, false); -BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(seqan3::views::take_until_or_throw), false, false, false); +BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(seqan3::detail::take_until), false, false, false); +BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(seqan3::detail::take_until_or_throw), false, false, false); BENCHMARK_TEMPLATE(sequential_read, std::vector, void, false, true, false); BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(std::views::take_while), true, true, false); -BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(seqan3::views::take_until), false, true, false); -BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(seqan3::views::take_until_or_throw), false, true, false); +BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(seqan3::detail::take_until), false, true, false); +BENCHMARK_TEMPLATE(sequential_read, std::vector, decltype(seqan3::detail::take_until_or_throw), false, true, false); BENCHMARK_TEMPLATE(sequential_read, std::forward_list, void, false, true, false); BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(std::views::take_while), true, true, false); -BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(seqan3::views::take_until), false, true, false); -BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(seqan3::views::take_until_or_throw), false, true, false); +BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(seqan3::detail::take_until), false, true, false); +BENCHMARK_TEMPLATE(sequential_read, std::forward_list, decltype(seqan3::detail::take_until_or_throw), false, true, false); // ============================================================================ // run diff --git a/test/performance/range/views/CMakeLists.txt b/test/performance/range/views/CMakeLists.txt index 8d1552b7b6a..bb78410f23f 100644 --- a/test/performance/range/views/CMakeLists.txt +++ b/test/performance/range/views/CMakeLists.txt @@ -2,4 +2,3 @@ seqan3_benchmark(view_all_benchmark.cpp) seqan3_benchmark(view_drop_benchmark.cpp) seqan3_benchmark(view_drop_view_take_benchmark.cpp) seqan3_benchmark(view_take_benchmark.cpp) -seqan3_benchmark(view_take_until_benchmark.cpp) diff --git a/test/snippet/range/views/take_until.cpp b/test/snippet/io/detail/take_until_view.cpp similarity index 69% rename from test/snippet/range/views/take_until.cpp rename to test/snippet/io/detail/take_until_view.cpp index e2ea474b485..95173452b64 100644 --- a/test/snippet/range/views/take_until.cpp +++ b/test/snippet/io/detail/take_until_view.cpp @@ -2,7 +2,7 @@ #include #include // for debug_stream -#include // for views::take_until* +#include // for detail::take_until* #include // for is_char #include // for views::single_pass_input @@ -10,16 +10,16 @@ int main() { // regular usage std::string vec{"foo\nbar"}; - auto v = vec | seqan3::views::take_until(seqan3::is_char<'\n'>); // or use a lambda + auto v = vec | seqan3::detail::take_until(seqan3::is_char<'\n'>); // or use a lambda seqan3::debug_stream << v << '\n'; // "foo" - auto v2 = vec | std::views::reverse | seqan3::views::take_until(seqan3::is_char<'\n'>); + auto v2 = vec | std::views::reverse | seqan3::detail::take_until(seqan3::is_char<'\n'>); seqan3::debug_stream << v2 << '\n'; // "rab" // consuming behaviour std::string vec2{"foo bar"}; // ← multiple spaces auto vin = vec2 | seqan3::views::single_pass_input; - auto v3 = vin | seqan3::views::take_until_and_consume(seqan3::is_blank); + auto v3 = vin | seqan3::detail::take_until_and_consume(seqan3::is_blank); seqan3::debug_stream << v3 << '\n'; // "foo" seqan3::debug_stream << *std::ranges::begin(vin) << '\n'; // "b", the spaces where skipped } diff --git a/test/unit/io/detail/CMakeLists.txt b/test/unit/io/detail/CMakeLists.txt index c5b2c62d4e7..9f4fcc7723f 100644 --- a/test/unit/io/detail/CMakeLists.txt +++ b/test/unit/io/detail/CMakeLists.txt @@ -7,4 +7,5 @@ seqan3_test(ignore_output_iterator_test.cpp) seqan3_test(record_like_test.cpp) seqan3_test(safe_filesystem_entry_test.cpp) seqan3_test(take_line_view_test.cpp) +seqan3_test(take_until_view_test.cpp) seqan3_test(take_view_test.cpp) diff --git a/test/unit/range/views/take_until_test.cpp b/test/unit/io/detail/take_until_view_test.cpp similarity index 90% rename from test/unit/range/views/take_until_test.cpp rename to test/unit/io/detail/take_until_view_test.cpp index c6a0ac5d33d..76032b960b5 100644 --- a/test/unit/range/views/take_until_test.cpp +++ b/test/unit/io/detail/take_until_view_test.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include @@ -103,7 +103,7 @@ void do_concepts(adaptor_t && adaptor, bool const_it) TEST(view_take_until, unix_eol) { auto is_newline = [] (char c) { return c == '\n'; }; - do_test(seqan3::views::take_until, is_newline, "foo\nbar"); + do_test(seqan3::detail::take_until, is_newline, "foo\nbar"); } TEST(view_take_until, functor_fail) @@ -112,17 +112,17 @@ TEST(view_take_until, functor_fail) std::string vec{"foo"}; auto is_newline = [](char c){return c == '\n'; }; - EXPECT_RANGE_EQ("foo"sv, vec | seqan3::views::take_until(is_newline)); + EXPECT_RANGE_EQ("foo"sv, vec | seqan3::detail::take_until(is_newline)); } TEST(view_take_until, concepts) { auto is_newline = [] (char c) { return c == '\n'; }; - auto adapt = seqan3::views::take_until(is_newline); + auto adapt = seqan3::detail::take_until(is_newline); do_concepts(adapt, true); // mutable adapters make the view loose const-iterability, but this is not checked by conepts unfortunately -// auto adapt2 = seqan3::views::take_until([count = 0] (char c) mutable { ++count; return c == '\n'; }); +// auto adapt2 = seqan3::detail::take_until([count = 0] (char c) mutable { ++count; return c == '\n'; }); // do_concepts(adapt2, false); } @@ -133,7 +133,7 @@ TEST(view_take_until, concepts) TEST(view_take_until_or_throw, unix_eol) { auto is_newline = [] (char c) { return c == '\n'; }; - do_test(seqan3::views::take_until_or_throw, is_newline, "foo\nbar"); + do_test(seqan3::detail::take_until_or_throw, is_newline, "foo\nbar"); } TEST(view_take_until_or_throw, functor_fail) @@ -141,12 +141,12 @@ TEST(view_take_until_or_throw, functor_fail) std::string vec{"foo"}; auto is_newline = [] (char c) { return c == '\n'; }; - EXPECT_THROW(std::ranges::for_each(vec | seqan3::views::take_until_or_throw(is_newline), [](auto &&){}), + EXPECT_THROW(std::ranges::for_each(vec | seqan3::detail::take_until_or_throw(is_newline), [](auto &&){}), seqan3::unexpected_end_of_input); } TEST(view_take_until_or_throw, concepts) { auto is_newline = [](char c){return c == '\n'; }; - do_concepts(seqan3::views::take_until_or_throw(is_newline), true); + do_concepts(seqan3::detail::take_until_or_throw(is_newline), true); } diff --git a/test/unit/range/views/CMakeLists.txt b/test/unit/range/views/CMakeLists.txt index 1f1b53e0b64..cb330bc73c7 100644 --- a/test/unit/range/views/CMakeLists.txt +++ b/test/unit/range/views/CMakeLists.txt @@ -7,6 +7,5 @@ seqan3_test(deep_test.cpp) seqan3_test(drop_test.cpp) seqan3_test(istreambuf_test.cpp) seqan3_test(move_test.cpp) -seqan3_test(take_until_test.cpp) seqan3_test(to_lower_test.cpp) seqan3_test(to_upper_test.cpp) diff --git a/test/unit/range/views/istreambuf_test.cpp b/test/unit/range/views/istreambuf_test.cpp index 334951fb5f5..3db087d01f7 100644 --- a/test/unit/range/views/istreambuf_test.cpp +++ b/test/unit/range/views/istreambuf_test.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -69,7 +69,7 @@ TEST(view_istreambuf, basic) // combinability 2 is.clear(); is.seekg(0, std::ios::beg); - EXPECT_RANGE_EQ(seqan3::detail::istreambuf(is) | seqan3::views::take_until(seqan3::is_space), + EXPECT_RANGE_EQ(seqan3::detail::istreambuf(is) | seqan3::detail::take_until(seqan3::is_space), "ACGTATATATAT"sv); } @@ -106,7 +106,7 @@ TEST(view_istreambuf, big_file_stram) auto v = seqan3::detail::istreambuf(istream); while (v.begin() != v.end()) { - EXPECT_RANGE_EQ(v | seqan3::views::take_until_or_throw_and_consume(seqan3::is_char<'\n'>), + EXPECT_RANGE_EQ(v | seqan3::detail::take_until_or_throw_and_consume(seqan3::is_char<'\n'>), "halloballo"sv); } diff --git a/test/unit/search/views/kmer_hash_test.cpp b/test/unit/search/views/kmer_hash_test.cpp index 949106a3028..da26f27372a 100644 --- a/test/unit/search/views/kmer_hash_test.cpp +++ b/test/unit/search/views/kmer_hash_test.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -29,7 +29,7 @@ using result_t = std::vector; static constexpr auto ungapped_view = seqan3::views::kmer_hash(seqan3::ungapped{3}); static constexpr auto gapped_view = seqan3::views::kmer_hash(0b101_shape); -static constexpr auto prefix_until_first_thymine = seqan3::views::take_until([] (seqan3::dna4 x) +static constexpr auto prefix_until_first_thymine = seqan3::detail::take_until([] (seqan3::dna4 x) { return x == 'T'_dna4; }); using iterator_type = std::ranges::iterator_t() | gapped_view)>; @@ -213,7 +213,7 @@ TYPED_TEST(kmer_hash_ungapped_test, issue1754) { TypeParam text1{'A'_dna4, 'C'_dna4, 'G'_dna4, 'T'_dna4, 'A'_dna4, 'G'_dna4, 'C'_dna4}; // ACGTAGC - auto stop_at_t = seqan3::views::take_until([] (seqan3::dna4 const x) { return x == 'T'_dna4; }); + auto stop_at_t = seqan3::detail::take_until([] (seqan3::dna4 const x) { return x == 'T'_dna4; }); if constexpr (std::ranges::bidirectional_range) // excludes forward_list { EXPECT_RANGE_EQ(result_t{36}, text1 | stop_at_t | std::views::reverse | ungapped_view); @@ -225,7 +225,7 @@ TYPED_TEST(kmer_hash_gapped_test, issue1754) { TypeParam text1{'A'_dna4, 'C'_dna4, 'G'_dna4, 'T'_dna4, 'A'_dna4, 'G'_dna4, 'C'_dna4}; // ACGTAGC - auto stop_at_t = seqan3::views::take_until([] (seqan3::dna4 const x) { return x == 'T'_dna4; }); + auto stop_at_t = seqan3::detail::take_until([] (seqan3::dna4 const x) { return x == 'T'_dna4; }); if constexpr (std::ranges::bidirectional_range) // excludes forward_list { EXPECT_RANGE_EQ(result_t{8}, text1 | stop_at_t | std::views::reverse | gapped_view); diff --git a/test/unit/search/views/minimiser_hash_test.cpp b/test/unit/search/views/minimiser_hash_test.cpp index ac54cc68bc6..8db996c54cb 100644 --- a/test/unit/search/views/minimiser_hash_test.cpp +++ b/test/unit/search/views/minimiser_hash_test.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include @@ -97,7 +97,7 @@ TEST_F(minimiser_hash_test, ungapped) EXPECT_RANGE_EQ(result2, text2 | ungapped_view); EXPECT_RANGE_EQ(ungapped3, text3 | ungapped_view); - auto stop_at_t = seqan3::views::take_until([] (seqan3::dna4 const x) { return x == 'T'_dna4; }); + auto stop_at_t = seqan3::detail::take_until([] (seqan3::dna4 const x) { return x == 'T'_dna4; }); EXPECT_RANGE_EQ(ungapped_stop_at_t3, text3 | stop_at_t | ungapped_view); } @@ -107,7 +107,7 @@ TEST_F(minimiser_hash_test, gapped) EXPECT_RANGE_EQ(result2, text2 | gapped_view); EXPECT_RANGE_EQ(gapped3, text3 | gapped_view); - auto stop_at_t = seqan3::views::take_until([] (seqan3::dna4 const x) { return x == 'T'_dna4; }); + auto stop_at_t = seqan3::detail::take_until([] (seqan3::dna4 const x) { return x == 'T'_dna4; }); EXPECT_RANGE_EQ(gapped_stop_at_t3, text3 | stop_at_t | gapped_view); } diff --git a/test/unit/search/views/minimiser_test.cpp b/test/unit/search/views/minimiser_test.cpp index 401b833164d..da0d26c4d94 100644 --- a/test/unit/search/views/minimiser_test.cpp +++ b/test/unit/search/views/minimiser_test.cpp @@ -13,8 +13,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -211,7 +211,7 @@ TEST_F(minimiser_test, window_too_big) TEST_F(minimiser_test, combinability) { - auto stop_at_t = seqan3::views::take_until([] (seqan3::dna4 const x) { return x == 'T'_dna4; }); + auto stop_at_t = seqan3::detail::take_until([] (seqan3::dna4 const x) { return x == 'T'_dna4; }); EXPECT_RANGE_EQ(result3_ungapped_stop, text3 | stop_at_t | kmer_view | minimiser_no_rev_view); EXPECT_RANGE_EQ(result3_gapped_stop, text3 | stop_at_t | gapped_kmer_view | minimiser_no_rev_view);