#ifndef ITERATORFILTER_H
#define ITERATORFILTER_H


// ----------------------------------------------------------------------
//
// IteratorFilter.h - Return the first iterator meeting a given criterion
//
// This zmt::IteratorFilter class definition permits definition of
// functor objects used to filter a container iterator according to a
// specified criterion applicable to the container's contents.  Such a
// IteratorFilter object would typically be used:
//      for ( Iter it( x.begin() );  filt(it);  ++it )  { ... }
// and thus the loop would only process those items in the container c
// that match a predicate established before or during filt's creation.
//
// History:
//   18-Feb-2000  WEB  Initial draft, based on discussion with Marc
//     Paterno and Mark Fischler
//   22-Feb-2000  WEB  Redesign of operator() to yield bool, based on
//     discussion with Marc Paterno
//   24-Feb-2000  WEB  Minor reformatting; move old op() out of line;
//     add code guard; inherit from std::unary_function<>; improve Zoom
//     compatibility
//   06-Mar-2000  WEB  Replace assert() with ZMthrow(), as requested by
//     Marc Paterno
//
// ----------------------------------------------------------------------


#include "ZMutility/ZMenvironment.h"

#include <algorithm>
#include <functional>

#ifndef ZMEXCEPTION_H
  #include "Exceptions/ZMexception.h"
#endif  // ZMEXCEPTION_H

#ifndef ZMTHROW_H
  #include "Exceptions/ZMthrow.h"
#endif  // ZMTHROW_H


ZM_BEGIN_NAMESPACE( zmt )


  ZMexStandardDefinition( ZMexception, BadIteratorFilter );

  template< class Iter, class Pred >
  class IteratorFilter  :  public std::unary_function<Iter,bool>  {

  public:  // default constructor:
    IteratorFilter()
    : okFilter( false )
    , end()
    , pred()
    { ; }

  public:  // preferred constructor:
    IteratorFilter( Iter const & e, Pred const & p )
    : okFilter( true )
    , end( e )
    , pred( p )
    { ; }

  public:  // use default copy constructor

  public:  // use default destructor

  public:  // use default copy assignment

  public:  // apply operator:
    bool  operator() ( Iter & b ) const  {
      if ( ! okFilter )
        ZMthrow( BadIteratorFilter("unusable IteratorFilter") );
      b = std::find_if( b, end, pred );
      return b != end;  // true if b is not at end, false if b is at end
    }  // op()

  private:  // member data:
    bool  okFilter;
    Iter  end;
    Pred  pred;

  };  // IteratorFilter<>

ZM_END_NAMESPACE( zmt )



// ----------------------------------------------------------------------
// Original version of IteratorFilter<>::operator()
// (of historical interest only):
// ----------------------------------------------------------------------
//  Iter const &  operator() ( Iter & b ) const  {
//    if ( ! okFilter )
//      throw( "bad IteratorFilter" );
//    for ( ;  b != end && ! pred(*b);  ++b )
//      ;
//    return b;
//  }  // op()
// ----------------------------------------------------------------------


#endif  // ITERATORFILTER_H
