File indexing completed on 2024-06-16 05:06:54
0001 /* 0002 SPDX-FileCopyrightText: 2018 Ivan Čukić <ivan.cukic(at)kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #ifndef VOY_OPERATIONS_SLICE_H 0008 #define VOY_OPERATIONS_SLICE_H 0009 0010 // STL 0011 #include <functional> 0012 0013 // Self 0014 #include "../utils.h" 0015 #include "../traits.h" 0016 #include "../dsl/node_tags.h" 0017 0018 namespace voy { 0019 0020 using voy::utils::non_copyable; 0021 0022 using voy::dsl::continuator_base, 0023 voy::dsl::transformation_node_tag; 0024 0025 template <typename = void> 0026 class slice_impl { 0027 public: 0028 using node_category = transformation_node_tag; 0029 0030 explicit slice_impl(size_t drop, size_t take) 0031 : m_drop{drop} 0032 , m_take{take} 0033 { 0034 } 0035 0036 template <typename Cont> 0037 class node: public continuator_base<Cont>, non_copyable { 0038 using base = continuator_base<Cont>; 0039 0040 public: 0041 node(size_t drop, size_t take, Cont&& continuation) 0042 : base(std::move(continuation)) 0043 , m_drop(drop) 0044 , m_take(take) 0045 { 0046 } 0047 0048 template <typename T> 0049 void operator() (T&& value) const 0050 { 0051 // 0 1 2 3 4 5 6 7 8 9 drop 3 take 5 0052 // [ ) 0053 // 3 3+5 0054 utils::on_scope_exit increment_count = [&] { 0055 if (m_current_count < m_drop + m_take) { 0056 m_current_count++; 0057 } 0058 }; 0059 0060 if (m_current_count < m_drop) return; 0061 if (m_take != 0 && m_current_count >= m_drop + m_take) return; 0062 0063 base::emit(voy_fwd(value)); 0064 0065 if (m_current_count == m_drop + m_take - 1) { 0066 this->m_continuation.notify_ended(); 0067 } 0068 } 0069 0070 private: 0071 size_t m_drop; 0072 size_t m_take; 0073 0074 // no need for locking, nodes are not shared across threads 0075 mutable size_t m_current_count = 0; 0076 }; 0077 0078 template <typename Cont> 0079 auto with_continuation(Cont&& cont) && 0080 { 0081 return node<Cont>(m_drop, m_take, voy_fwd(cont)); 0082 } 0083 0084 private: 0085 size_t m_drop; 0086 size_t m_take; 0087 }; 0088 0089 inline 0090 auto drop(size_t drop_count) 0091 { 0092 return slice_impl(drop_count, 0); 0093 } 0094 0095 inline 0096 auto take(size_t take_count) 0097 { 0098 return slice_impl(0, take_count); 0099 } 0100 0101 inline 0102 auto slice(size_t drop_count, size_t take_count) 0103 { 0104 return slice_impl(drop_count, take_count); 0105 } 0106 0107 0108 } // namespace voy 0109 0110 #endif // include guard 0111