diff --git a/src/lib/iter-source.hpp b/src/lib/iter-source.hpp index 549907e89..13eb580e3 100644 --- a/src/lib/iter-source.hpp +++ b/src/lib/iter-source.hpp @@ -43,6 +43,7 @@ #include "lib/iter-adapter.hpp" //#include "lib/bool-checkable.hpp" +#include #include @@ -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 class IterSource -// : public lib::BoolCheckable > { - 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 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 WrappedLumieraIterator + : public IterSource + , boost::noncopyable + { + typedef IterSource _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::Iter eachEntry (CON& container) { - UNIMPLEMENTED ("standard iter wrapper yielding all distinct keys of a multimap"); + typedef typename iter_impl::_SeqType::Val ValType; + typedef RangeIter Range; + + Range contents (container.begin(), container.end()); + return IterSource::build (new WrappedLumieraIterator(contents)); } diff --git a/tests/40components.tests b/tests/40components.tests index b8f3a930c..0b4feea90 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -356,7 +356,9 @@ out: ::12::11::10::9::8::7::6::5::4::3 END -PLANNED "Iterable data source" IterSource_test 20 < #include #include +#include #include @@ -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 + : public IterSource , 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::iterator sourceIter; typedef RangeIter iterator; - typedef list::const_iterator const_sourceIter; - typedef RangeIter 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::iterator IntIter; - typedef IterSource::iterator StrIter; - + typedef IterSource::iterator StrIter; + virtual void run (Arg arg) { @@ -138,7 +155,7 @@ namespace test{ TestSource dedicatedSource(NUM_ELMS); IntIter iii (eachEntry (customList)); - StrIter cii (IterSource::build(dedicatedSource)); + StrIter cii (IterSource::build(dedicatedSource)); ASSERT (!isnil (iii)); ASSERT (!isnil (cii)); @@ -154,9 +171,9 @@ namespace test{ template void - pullOut (IT const& ii) + pullOut (IT& iter) { - for (IT iter(ii) ; iter; ++iter ) + for ( ; iter; ++iter ) cout << "::" << *iter; cout << endl; }