You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
4.6KB

  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Johel Guerrero 2019
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_VIEW_TRIM_HPP
  14. #define RANGES_V3_VIEW_TRIM_HPP
  15. #include <utility>
  16. #include <concepts/concepts.hpp>
  17. #include <range/v3/algorithm/find_if_not.hpp>
  18. #include <range/v3/detail/config.hpp>
  19. #include <range/v3/functional/bind_back.hpp>
  20. #include <range/v3/functional/compose.hpp>
  21. #include <range/v3/functional/invoke.hpp>
  22. #include <range/v3/functional/pipeable.hpp>
  23. #include <range/v3/iterator/concepts.hpp>
  24. #include <range/v3/range/access.hpp>
  25. #include <range/v3/range/concepts.hpp>
  26. #include <range/v3/range/primitives.hpp>
  27. #include <range/v3/utility/optional.hpp>
  28. #include <range/v3/utility/semiregular_box.hpp>
  29. #include <range/v3/view/all.hpp>
  30. #include <range/v3/view/interface.hpp>
  31. #include <range/v3/view/view.hpp>
  32. namespace ranges
  33. {
  34. /// \addtogroup group-views
  35. /// @{
  36. template<typename Rng, typename Pred>
  37. struct trim_view : view_interface<trim_view<Rng, Pred>>
  38. {
  39. private:
  40. Rng rng_;
  41. semiregular_box_t<Pred> pred_;
  42. detail::non_propagating_cache<iterator_t<Rng>> begin_;
  43. detail::non_propagating_cache<iterator_t<Rng>> end_;
  44. public:
  45. CPP_assert(bidirectional_range<Rng> && view_<Rng> && indirect_unary_predicate<
  46. Pred, iterator_t<Rng>> && common_range<Rng>);
  47. trim_view() = default;
  48. constexpr trim_view(Rng rng, Pred pred)
  49. : rng_(std::move(rng))
  50. , pred_(std::move(pred))
  51. {}
  52. iterator_t<Rng> begin()
  53. {
  54. if(!begin_)
  55. begin_ = find_if_not(rng_, std::ref(pred_));
  56. return *begin_;
  57. }
  58. iterator_t<Rng> end()
  59. {
  60. if(!end_)
  61. {
  62. const auto first = begin();
  63. auto last = ranges::end(rng_);
  64. while(last != first)
  65. if(!invoke(pred_, *--last))
  66. {
  67. ++last;
  68. break;
  69. }
  70. end_ = std::move(last);
  71. }
  72. return *end_;
  73. }
  74. Rng base() const
  75. {
  76. return rng_;
  77. }
  78. };
  79. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  80. template<typename Rng, typename Pred>
  81. trim_view(Rng &&, Pred)->trim_view<views::all_t<Rng>, Pred>;
  82. #endif
  83. template<typename Rng, typename Pred>
  84. RANGES_INLINE_VAR constexpr bool disable_sized_range<trim_view<Rng, Pred>> = true;
  85. namespace views
  86. {
  87. struct trim_fn
  88. {
  89. private:
  90. friend view_access;
  91. template<typename Pred>
  92. static constexpr auto bind(trim_fn trim, Pred pred)
  93. {
  94. return make_pipeable(bind_back(trim, std::move(pred)));
  95. }
  96. template<typename Pred, typename Proj>
  97. static constexpr auto bind(trim_fn trim, Pred pred, Proj proj)
  98. {
  99. return make_pipeable(bind_back(trim, std::move(pred), std::move(proj)));
  100. }
  101. public:
  102. template<typename Rng, typename Pred>
  103. constexpr auto operator()(Rng && rng, Pred pred) const -> CPP_ret(
  104. trim_view<all_t<Rng>, Pred>)( //
  105. requires viewable_range<Rng> && bidirectional_range<Rng> &&
  106. indirect_unary_predicate<Pred, iterator_t<Rng>> && common_range<Rng>)
  107. {
  108. return {all(static_cast<Rng &&>(rng)), std::move(pred)};
  109. }
  110. template<typename Rng, typename Pred, typename Proj>
  111. constexpr auto operator()(Rng && rng, Pred pred, Proj proj) const
  112. -> CPP_ret(trim_view<all_t<Rng>, composed<Pred, Proj>>)( //
  113. requires viewable_range<Rng> && bidirectional_range<Rng> &&
  114. indirect_unary_predicate<composed<Pred, Proj>, iterator_t<Rng>> &&
  115. common_range<Rng>)
  116. {
  117. return {all(static_cast<Rng &&>(rng)),
  118. compose(std::move(pred), std::move(proj))};
  119. }
  120. };
  121. /// \relates trim_fn
  122. /// \ingroup group-views
  123. RANGES_INLINE_VARIABLE(view<trim_fn>, trim)
  124. } // namespace views
  125. /// @}
  126. } // namespace ranges
  127. #include <range/v3/detail/satisfy_boost_range.hpp>
  128. RANGES_SATISFY_BOOST_RANGE(::ranges::trim_view)
  129. #endif // RANGES_V3_VIEW_TRIM_HPP