basic IterSource implementation passes unit test (#490)

This commit is contained in:
Fischlurch 2010-01-05 05:21:13 +01:00
parent 16962ae714
commit 030a7d3813
3 changed files with 151 additions and 47 deletions

View file

@ -43,6 +43,7 @@
#include "lib/iter-adapter.hpp"
//#include "lib/bool-checkable.hpp"
#include <boost/noncopyable.hpp>
#include <tr1/memory>
@ -52,8 +53,6 @@ namespace lib {
using std::tr1::shared_ptr;
namespace {
}
/**
@ -61,7 +60,7 @@ namespace lib {
* which then can be accessed through IterAdapter as a frontend,
* allowing to pull individual elements until exhaustion.
*
* This base class is empty and makes now assumptions regarding
* This base class is empty and makes no assumptions regarding
* identity, instantiation and copying.
*
* @see PlacementIndex::Table#_eachEntry_4check usage example
@ -69,18 +68,8 @@ namespace lib {
*/
template<typename TY>
class IterSource
// : public lib::BoolCheckable<IterSource<TY> >
{
static void
detach_without_destroy (IterSource * source)
{
WARN_IF (!source, library, "IterSource deleter called with NULL source pointer");
if (source)
source->disconnect();
}
protected: /* == data source API for implementation == */
typedef TY* Pos;
@ -130,15 +119,62 @@ namespace lib {
typedef IterAdapter<Pos, DataHandle> iterator;
/** build an iterator frontend for the given source,
* @note the source is allocated separately and
* \em not owned by the iterator frontend
*/
static iterator
build (IterSource& sourceImpl)
{
DataHandle sourceHandle (&sourceImpl, &detach_without_destroy);
Pos first = sourceImpl.firstResult();
return iterator (sourceHandle, first);
return startIteration(sourceHandle);
}
/** build an iterator frontend, thereby managing
* the given heap allocated source object instance.
* @note we take ownership and destroy the source
* when the last copy of the created iterator
* goes out of scope.
*/
static iterator
build (IterSource* sourceImplObject)
{
DataHandle sourceHandle (sourceImplObject, &destroy_managed_source);
return startIteration(sourceHandle);
}
static iterator EMPTY_SOURCE;
private:
static iterator
startIteration (DataHandle sourceHandle)
{
REQUIRE (sourceHandle);
Pos first = sourceHandle->firstResult();
return iterator (sourceHandle, first);
}
static void
detach_without_destroy (IterSource * source)
{
WARN_IF (!source, library, "IterSource deleter called with NULL source pointer");
if (source)
source->disconnect();
}
static void
destroy_managed_source (IterSource * source)
{
WARN_IF (!source, library, "IterSource deleter called with NULL source pointer");
if (source)
{
source->disconnect();
delete source;
}
}
};
@ -149,6 +185,51 @@ namespace lib {
/**
* Standard implementation of the IterSource interface:
* a wrapped "Lumiera Forward Iterator"
*/
template<class IT>
class WrappedLumieraIterator
: public IterSource<typename IT::value_type>
, boost::noncopyable
{
typedef IterSource<typename IT::value_type> _Base;
typedef typename _Base::Pos Pos;
IT src_;
Pos
firstResult ()
{
if (!src_)
return 0;
else
return & *src_;
}
void
nextResult (Pos& pos)
{
if (!pos) return;
if (src_) ++src_;
if (src_)
pos = & *src_;
else
pos = 0;
}
public:
WrappedLumieraIterator (IT const& orig)
: src_(orig)
{ }
};
/* === pre-defined Adapters for frequently used Containers === */
namespace iter_impl {
@ -188,7 +269,11 @@ namespace lib {
typename iter_impl::_SeqType<CON>::Iter
eachEntry (CON& container)
{
UNIMPLEMENTED ("standard iter wrapper yielding all distinct keys of a multimap");
typedef typename iter_impl::_SeqType<CON>::Val ValType;
typedef RangeIter<typename CON::iterator> Range;
Range contents (container.begin(), container.end());
return IterSource<ValType>::build (new WrappedLumieraIterator<Range>(contents));
}

View file

@ -356,7 +356,9 @@ out: ::12::11::10::9::8::7::6::5::4::3
END
PLANNED "Iterable data source" IterSource_test 20 <<END
TEST "Iterable data source" IterSource_test 13 <<END
out: ::13::12::11::10::9::8::7::6::5::4::3::2::1
out: ::.............::............::...........::..........::.........::........::.......::......::.....::....::...::..::.$
END

View file

@ -23,6 +23,7 @@
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/util.hpp"
#include "lib/iter-source.hpp"
@ -30,6 +31,7 @@
#include <boost/lexical_cast.hpp>
#include <boost/noncopyable.hpp>
#include <iostream>
#include <string>
#include <list>
@ -40,7 +42,10 @@ namespace test{
using ::Test;
using boost::lexical_cast;
using boost::noncopyable;
using lib::test::randStr;
using util::isnil;
using util::cStr;
using std::string;
using std::list;
using std::cout;
using std::endl;
@ -52,37 +57,52 @@ namespace test{
uint NUM_ELMS = 10;
/**
typedef const char* CStr;
/**
* Explicit implementation of the IterSource interface (test dummy)
* Creates a random string and chops off a character on each iteration
*/
class TestSource
: public IterSource<char*>
: public IterSource<CStr>
, noncopyable
{
virtual Pos
firstResult ()
{
UNIMPLEMENTED ("start iteration");
}
virtual void
nextResult (Pos& pos)
{
UNIMPLEMENTED ("iteration step");
}
string buffer_;
CStr current_;
virtual Pos
firstResult ()
{
current_ = buffer_.c_str();
ENSURE (current_);
return &current_;
}
virtual void
nextResult (Pos& pos)
{
if (pos && *pos && **pos)
++(*pos);
if (!(pos && *pos && **pos))
pos = 0;
}
public:
TestSource (uint num)
: buffer_(randStr (num))
, current_(0)
{
UNIMPLEMENTED ("dedicated IterSource implementation");
INFO (test, "created TestSource(\"%s\")", cStr(buffer_));
}
};
/** test dummy, simply wrapping an STL container
/** test dummy: simply wrapping an STL container
* and exposing a range as Lumiera Forward Iterator
*/
struct WrappedList
@ -98,13 +118,8 @@ namespace test{
typedef list<int>::iterator sourceIter;
typedef RangeIter<sourceIter> iterator;
typedef list<int>::const_iterator const_sourceIter;
typedef RangeIter<const_sourceIter> const_iterator;
iterator begin() { return iterator(data_.begin(),data_.end()); }
iterator end() { return iterator(); }
const_iterator begin() const { return const_iterator(data_.begin(),data_.end()); }
const_iterator end() const { return const_iterator(); }
iterator begin() { return iterator(data_.begin(),data_.end()); }
iterator end() { return iterator(); }
};
@ -119,15 +134,17 @@ namespace test{
/******************************************************************
* @test create some (opaque) data sources,
* and then pull the data out by iteration.
* Demonstrates simple usage of the IterSource inteface
* Demonstrates simple usage of the IterSource interface
*
* @see IterSource
* @see PlacementIndex::Table#_eachEntry_4check real world usage example
*/
class IterSource_test : public Test
{
typedef IterSource<int>::iterator IntIter;
typedef IterSource<char*>::iterator StrIter;
typedef IterSource<CStr>::iterator StrIter;
virtual void
run (Arg arg)
{
@ -138,7 +155,7 @@ namespace test{
TestSource dedicatedSource(NUM_ELMS);
IntIter iii (eachEntry (customList));
StrIter cii (IterSource<char*>::build(dedicatedSource));
StrIter cii (IterSource<CStr>::build(dedicatedSource));
ASSERT (!isnil (iii));
ASSERT (!isnil (cii));
@ -154,9 +171,9 @@ namespace test{
template<class IT>
void
pullOut (IT const& ii)
pullOut (IT& iter)
{
for (IT iter(ii) ; iter; ++iter )
for ( ; iter; ++iter )
cout << "::" << *iter;
cout << endl;
}