#ifndef __JLANG__JOBJECTSAMPLER__
#define __JLANG__JOBJECTSAMPLER__
#include "JLang/JObjectIterator.hh"
#include "JLang/JPointer.hh"
#include "JLang/JSampler.hh"
/**
* \author mdejong
*/
namespace JLANG {}
namespace JPP { using namespace JLANG; }
namespace JLANG {
/**
* Auxiliary class to sample objects from a JRewindableObjectIterator.
*
* This class can be used for iterations that are different than strict sequential.
* The first template parameter corresponds to the data type of the iteration and the second to the sampler.\n
* The sampling is defined by the number of objects to be skipped.
* The number of objects to be skipped is returned by the function object operator
* of the sampler which takes the actual object as input.\n
* The default JSampler corresponds to zero elements to be skipped,
* which in turn corresponds to the iteration of all objects in sequential order.
*
* The JObjectSampler class implements the JObjectIterator
* using a reference to a JRewindableObjectIterator object so that
* the sampling of objects can continue ad infinitum.
*
* Method JObjectSampler::hasNext normally returns true, unless
* - there are no available objects; or
* - given sampler rejects every object.
*
* Note that the internal sampler is a copy of the specified sampler and not a reference thereof.
*/
template class JSampler_t = JSampler>
class JObjectSampler :
public JObjectIterator
{
public:
typedef typename JObjectIterator::pointer_type pointer_type;
/**
* Constructor.
*
* \param input input
*/
JObjectSampler(JRewindableObjectIterator& input) :
in (input),
has_next(false)
{}
/**
* Constructor.
*
* \param input input
* \param sampler sampler
*/
JObjectSampler(JRewindableObjectIterator& input,
const JSampler_t& sampler) :
in (input),
has_next(false)
{
this->sampler = sampler;
}
/**
* Check availability of next element.
*
* \return true if the iteration has more elements; else false
*/
virtual bool hasNext() override
{
while (!has_next) {
if (!in.hasNext()) {
in.rewind();
}
if (in.hasNext()) {
ps.set(in.next());
skip_type ns = sampler(*ps);
if (ns == 0) {
has_next = true;
} else {
while ((ns -= in.skip(ns)) != 0) {
in.rewind();
}
}
} else {
// nothing to sample
break;
}
}
return has_next;
}
/**
* Get next element.
*
* \return pointer to element
*/
virtual const pointer_type& next() override
{
if (!has_next) {
ps.reset(NULL);
}
has_next = false;
return ps;
}
/**
* Get sampler.
*
* \return sampler
*/
const JSampler_t& getSampler() const
{
return sampler;
}
/**
* Get sampler.
*
* \return sampler
*/
JSampler_t& getSampler()
{
return sampler;
}
protected:
JRewindableObjectIterator& in;
JSampler_t sampler;
JPointer ps;
bool has_next;
};
}
#endif