• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2 
3 #pragma once
4 
5 /*! \file rx-any.hpp
6 
7     \brief Returns an Observable that emits true if any item emitted by the source Observable satisfies a specified condition, otherwise false. Emits false if the source Observable terminates without emitting any item.
8 
9     \tparam Predicate the type of the test function.
10 
11     \param p the test function to test items emitted by the source Observable.
12 
13     \return  An observable that emits true if any item emitted by the source observable satisfies a specified condition, otherwise false.
14 
15     Some basic any- operators have already been implemented:
16     - rxcpp::operators::exists
17     - rxcpp::operators::contains
18 
19     \sample
20     \snippet exists.cpp exists sample
21     \snippet output.txt exists sample
22 
23     \sample
24     \snippet contains.cpp contains sample
25     \snippet output.txt contains sample
26 */
27 
28 
29 #if !defined(RXCPP_OPERATORS_RX_ANY_HPP)
30 #define RXCPP_OPERATORS_RX_ANY_HPP
31 
32 #include "../rx-includes.hpp"
33 
34 namespace rxcpp {
35 
36 namespace operators {
37 
38 namespace detail {
39 
40 template<class... AN>
41 struct any_invalid_arguments {};
42 
43 template<class... AN>
44 struct any_invalid : public rxo::operator_base<any_invalid_arguments<AN...>> {
45     using type = observable<any_invalid_arguments<AN...>, any_invalid<AN...>>;
46 };
47 template<class... AN>
48 using any_invalid_t = typename any_invalid<AN...>::type;
49 
50 template<class T, class Predicate>
51 struct any
52 {
53     typedef rxu::decay_t<T> source_value_type;
54     typedef bool value_type;
55     typedef rxu::decay_t<Predicate> test_type;
56     test_type test;
57 
anyrxcpp::operators::detail::any58     any(test_type t)
59         : test(std::move(t))
60     {
61     }
62 
63     template<class Subscriber>
64     struct any_observer
65     {
66         typedef any_observer<Subscriber> this_type;
67         typedef source_value_type value_type;
68         typedef rxu::decay_t<Subscriber> dest_type;
69         typedef observer<value_type, this_type> observer_type;
70         dest_type dest;
71         test_type test;
72         mutable bool done;
73 
any_observerrxcpp::operators::detail::any::any_observer74         any_observer(dest_type d, test_type t)
75             : dest(std::move(d))
76             , test(std::move(t)),
77               done(false)
78         {
79         }
on_nextrxcpp::operators::detail::any::any_observer80         void on_next(source_value_type v) const {
81             auto filtered = on_exception([&]() {
82                 return !this->test(v); },
83                 dest);
84             if (filtered.empty()) {
85                 return;
86             }
87             if (!filtered.get() && !done) {
88                 done = true;
89                 dest.on_next(true);
90                 dest.on_completed();
91             }
92         }
on_errorrxcpp::operators::detail::any::any_observer93         void on_error(rxu::error_ptr e) const {
94             dest.on_error(e);
95         }
on_completedrxcpp::operators::detail::any::any_observer96         void on_completed() const {
97             if(!done) {
98                 done = true;
99                 dest.on_next(false);
100                 dest.on_completed();
101             }
102         }
103 
makerxcpp::operators::detail::any::any_observer104         static subscriber<value_type, observer_type> make(dest_type d, test_type t) {
105             return make_subscriber<value_type>(d, this_type(d, std::move(t)));
106         }
107     };
108 
109     template<class Subscriber>
operator ()rxcpp::operators::detail::any110     auto operator()(Subscriber dest) const
111         -> decltype(any_observer<Subscriber>::make(std::move(dest), test)) {
112         return      any_observer<Subscriber>::make(std::move(dest), test);
113     }
114 };
115 
116 }
117 
118 /*! @copydoc rx-any.hpp
119 */
120 template<class... AN>
any(AN &&...an)121 auto any(AN&&... an)
122     ->     operator_factory<any_tag, AN...> {
123     return operator_factory<any_tag, AN...>(std::make_tuple(std::forward<AN>(an)...));
124 }
125 
126 /*! \brief Returns an Observable that emits true if any item emitted by the source Observable satisfies a specified condition, otherwise false. Emits false if the source Observable terminates without emitting any item.
127 
128     \tparam Predicate the type of the test function.
129 
130     \param p the test function to test items emitted by the source Observable.
131 
132     \return  An observable that emits true if any item emitted by the source observable satisfies a specified condition, otherwise false.
133 
134     \sample
135     \snippet exists.cpp exists sample
136     \snippet output.txt exists sample
137 */
138 template<class... AN>
exists(AN &&...an)139 auto exists(AN&&... an)
140     ->     operator_factory<exists_tag, AN...> {
141     return operator_factory<exists_tag, AN...>(std::make_tuple(std::forward<AN>(an)...));
142 }
143 
144 /*! \brief Returns an Observable that emits true if the source Observable emitted a specified item, otherwise false. Emits false if the source Observable terminates without emitting any item.
145 
146     \tparam T the type of the item to search for.
147 
148     \param value the item to search for.
149 
150     \return An observable that emits true if the source Observable emitted a specified item, otherwise false.
151 
152     \sample
153     \snippet contains.cpp contains sample
154     \snippet output.txt contains sample
155 */
156 template<class... AN>
contains(AN &&...an)157 auto contains(AN&&... an)
158 ->     operator_factory<contains_tag, AN...> {
159     return operator_factory<contains_tag, AN...>(std::make_tuple(std::forward<AN>(an)...));
160 }
161 
162 }
163 
164 template<>
165 struct member_overload<any_tag>
166 {
167     template<class Observable, class Predicate,
168         class SourceValue = rxu::value_type_t<Observable>,
169         class Enabled = rxu::enable_if_all_true_type_t<
170             is_observable<Observable>>,
171         class Any = rxo::detail::any<SourceValue, rxu::decay_t<Predicate>>,
172         class Value = rxu::value_type_t<Any>>
memberrxcpp::member_overload173     static auto member(Observable&& o, Predicate&& p)
174     -> decltype(o.template lift<Value>(Any(std::forward<Predicate>(p)))) {
175         return  o.template lift<Value>(Any(std::forward<Predicate>(p)));
176     }
177 
178     template<class... AN>
memberrxcpp::member_overload179     static operators::detail::any_invalid_t<AN...> member(const AN&...) {
180         std::terminate();
181         return {};
182         static_assert(sizeof...(AN) == 10000, "any takes (Predicate)");
183     }
184 };
185 
186 template<>
187 struct member_overload<exists_tag>
188     : member_overload<any_tag>
189 {
190     using member_overload<any_tag>::member;
191 
192     template<class... AN>
memberrxcpp::member_overload193     static operators::detail::any_invalid_t<AN...> member(const AN&...) {
194         std::terminate();
195         return {};
196         static_assert(sizeof...(AN) == 10000, "exists takes (Predicate)");
197     }
198 };
199 
200 template<>
201 struct member_overload<contains_tag>
202 {
203     template<class Observable, class T,
204         class SourceValue = rxu::value_type_t<Observable>,
205         class Enabled = rxu::enable_if_all_true_type_t<
206             is_observable<Observable>>,
207         class Predicate = std::function<bool(T)>,
208         class Any = rxo::detail::any<SourceValue, rxu::decay_t<Predicate>>,
209         class Value = rxu::value_type_t<Any>>
memberrxcpp::member_overload210     static auto member(Observable&& o, T&& value)
211     -> decltype(o.template lift<Value>(Any(nullptr))) {
212         return  o.template lift<Value>(Any([value](T n) { return n == value; }));
213     }
214 
215     template<class... AN>
memberrxcpp::member_overload216     static operators::detail::any_invalid_t<AN...> member(const AN&...) {
217         std::terminate();
218         return {};
219         static_assert(sizeof...(AN) == 10000, "contains takes (T)");
220     }
221 };
222 
223 }
224 
225 #endif
226