// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. #pragma once /*! \file rx-skip.hpp \brief Make new observable with skipped first count items from this observable. \tparam Count the type of the items counter \param t the number of items to skip \return An observable that is identical to the source observable except that it does not emit the first t items that the source observable emits. \sample \snippet skip.cpp skip sample \snippet output.txt skip sample */ #if !defined(RXCPP_OPERATORS_RX_SKIP_HPP) #define RXCPP_OPERATORS_RX_SKIP_HPP #include "../rx-includes.hpp" namespace rxcpp { namespace operators { namespace detail { template struct skip_invalid_arguments {}; template struct skip_invalid : public rxo::operator_base> { using type = observable, skip_invalid>; }; template using skip_invalid_t = typename skip_invalid::type; template struct skip : public operator_base { typedef rxu::decay_t source_type; typedef rxu::decay_t count_type; struct values { values(source_type s, count_type t) : source(std::move(s)) , count(std::move(t)) { } source_type source; count_type count; }; values initial; skip(source_type s, count_type t) : initial(std::move(s), std::move(t)) { } struct mode { enum type { skipping, // ignore messages triggered, // capture messages errored, // error occured stopped // observable completed }; }; template void on_subscribe(const Subscriber& s) const { typedef Subscriber output_type; struct state_type : public std::enable_shared_from_this , public values { state_type(const values& i, const output_type& oarg) : values(i) , mode_value(i.count > 0 ? mode::skipping : mode::triggered) , out(oarg) { } typename mode::type mode_value; output_type out; }; // take a copy of the values for each subscription auto state = std::make_shared(initial, s); composite_subscription source_lifetime; s.add(source_lifetime); state->source.subscribe( // split subscription lifetime source_lifetime, // on_next [state](T t) { if (state->mode_value == mode::skipping) { if (--state->count == 0) { state->mode_value = mode::triggered; } } else { state->out.on_next(t); } }, // on_error [state](rxu::error_ptr e) { state->mode_value = mode::errored; state->out.on_error(e); }, // on_completed [state]() { state->mode_value = mode::stopped; state->out.on_completed(); } ); } }; } /*! @copydoc rx-skip.hpp */ template auto skip(AN&&... an) -> operator_factory { return operator_factory(std::make_tuple(std::forward(an)...)); } } template<> struct member_overload { template>, class SourceValue = rxu::value_type_t, class Skip = rxo::detail::skip, rxu::decay_t>, class Value = rxu::value_type_t, class Result = observable> static Result member(Observable&& o, Count&& c) { return Result(Skip(std::forward(o), std::forward(c))); } template static operators::detail::skip_invalid_t member(AN...) { std::terminate(); return {}; static_assert(sizeof...(AN) == 10000, "skip takes (optional Count)"); } }; } #endif