basic IterSource implementation passes unit test (#490)
This commit is contained in:
parent
16962ae714
commit
030a7d3813
3 changed files with 151 additions and 47 deletions
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ¤t_;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue