//***************************************************************************
//* Copyright (c) 2015 Saint Petersburg State University
//* Copyright (c) 2011-2014 Saint Petersburg Academic University
//* All Rights Reserved
//* See file LICENSE for details.
//***************************************************************************

#ifndef FILTER_ITERATOR_H_
#define FILTER_ITERATOR_H_

namespace adt {

/**
* Iterator with some predicate -- iterates only on elements with predicate(item) == true
*/
template<typename iterator_type, typename predicate_type>
class filter_iterator {
public:
    typedef typename iterator_type::value_type value_type;

    filter_iterator(const iterator_type &begin, const iterator_type &end, const predicate_type &pred) :
            current_(begin), end_(end), pred_(pred) {
        while ((current_ != end_) && (!pred_(*current_))) // why do we need here? DRY, see method advance() below.
            ++current_;
    } // filter_iterator

    value_type operator*() const { return *current_; }
    value_type operator->() const { return *current_; }

    filter_iterator &operator++() {
        advance();
        return *this;
    }

    bool operator==(const filter_iterator &rhs) const { return current_ == rhs.current_; }
    bool operator!=(const filter_iterator &rhs) const { return !(operator==(rhs)); }

private:
    void advance() {
        do {
            ++current_;
        }
        while ((current_ != end_) && (!pred_(*current_)));
    } // advance

    iterator_type current_;
    iterator_type end_;
    predicate_type pred_;
};
} //adt
#endif /* FILTER_ITERATOR_H_ */
