From d6539374655c38e66a4f555ee8492d3e32fe705e Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 24 Dec 2017 03:28:40 +0100 Subject: [PATCH] TreeExplorer: allow to call through an IterSource based API for child-expansion ...which basically allows us to return any suitable implementation for the child iterator, even to switch the concrete iteration on each level. We need this flexibility when implementing navigation through a concrete UI --- src/lib/iter-tree-explorer.hpp | 25 +++++++- tests/library/iter-tree-explorer-test.cpp | 72 +++++++++++++---------- wiki/thinkPad.ichthyo.mm | 33 ++++++----- 3 files changed, 81 insertions(+), 49 deletions(-) diff --git a/src/lib/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index b78cfd8b5..c26e859d5 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -303,6 +303,15 @@ namespace lib { IterSourceIter (ISO* heap_allocated_IterSource) : ISO::iterator{ISO::build (heap_allocated_IterSource)} { } + + using Source = ISO; + + Source& + source() + { + REQUIRE (ISO::iterator::isValid()); + return static_cast (*ISO::iterator::source()); + } }; }//(End) namespace iter_explorer : basic iterator wrappers @@ -319,6 +328,7 @@ namespace lib { using meta::_Fun; using std::__and_; using std::__not_; + using std::is_base_of; using std::is_convertible; using std::remove_reference_t; using meta::can_IterForEach; @@ -401,14 +411,14 @@ namespace lib { }; template - struct _DecoratorTraits, ISO>>> + struct _DecoratorTraits, ISO>>> { using SrcIter = iter_explorer::IterSourceIter; using SrcVal = typename ISO::value_type; }; template - struct _DecoratorTraits, ISO>>> + struct _DecoratorTraits, ISO>>> { using SrcIter = iter_explorer::IterSourceIter; using SrcVal = typename ISO::value_type; @@ -491,6 +501,17 @@ namespace lib { static auto build() { return [](auto& iter) { return *iter; }; } }; + /** adapt to a functor collaborating with an IterSource based iterator pipeline */ + template + struct ArgAccessor, typename IT::Source> + , is_base_of, remove_reference_t> + > >> + { + using Source = typename IT::Source; + + static auto build() { return [](auto& iter) -> Source& { return iter.source(); }; } + }; + /** holder for the suitably adapted _expansion functor_ */ struct Functor diff --git a/tests/library/iter-tree-explorer-test.cpp b/tests/library/iter-tree-explorer-test.cpp index 30dd26ffa..205cd73e7 100644 --- a/tests/library/iter-tree-explorer-test.cpp +++ b/tests/library/iter-tree-explorer-test.cpp @@ -849,8 +849,17 @@ namespace test{ - /** @test ability to wrap and handle IterSource based iteration - * + + /** @test ability to wrap and handle IterSource based iteration. + * Contrary to the preceding test case, here the point is to _base the whole pipleine_ + * on a data source accessible through the IterSource (VTable based) interface. The notable + * point with this technique is the ability to use some _extended sub interface of IterSource_ + * and to rely on this interface to implement some functor bound into the TreeExplorer pipeline. + * Especially this allows to delegate the "child expansion" through such an interface and just + * return a compatible IterSource as result. This way, the opaque implementation gains total + * freedom regarding the concrete implementation of the "child series" iterator. In fact, + * it may even use a different implementation on each level or even on each individual call; + * only the result type and thus the base interface need to match. */ void verify_IterSource() @@ -874,7 +883,7 @@ namespace test{ virtual PrivateSource* expandChildren() const override { - return new VerySpecivicIter{*wrappedIter() - 1}; + return new VerySpecivicIter{*wrappedIter() - 2}; } uint @@ -892,45 +901,44 @@ namespace test{ - VerySpecivicIter vsit{4}; - // attach to an IterSource living here in local scope... - auto ii = treeExplore(vsit); + VerySpecivicIter vsit{5}; + + // ...and build a child expansion on top, which calls through the PrivateSource-API + // Effectively this means we do not know the concrete type of the "expanded children" iterator, + // only that it adheres to the same IterSource sub-interface as used on the base iterator. + auto ii = treeExplore(vsit) + .expand ([](PrivateSource& source){ return source.expandChildren(); }); CHECK (not isnil (ii)); + CHECK (5 == *ii); + CHECK (5 == vsit.currentVal()); + ++ii; CHECK (4 == *ii); CHECK (4 == vsit.currentVal()); + + CHECK (0 == ii.depth()); + ii.expandChildren(); // note: calls through source's VTable to invoke VerySpecificIter::expandChildren() + CHECK (1 == ii.depth()); + + CHECK (2 == *ii); ++ii; + CHECK (1 == *ii); + + CHECK (3 == vsit.currentVal()); + CHECK (1 == ii.depth()); + ++ii; + CHECK (0 == ii.depth()); CHECK (3 == *ii); CHECK (3 == vsit.currentVal()); - -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #888 - auto jj = ii.explore([](PrivateSource& source){ return source.expandChildren(); }); - - CHECK (3 == *jj); - CHECK (3 == vsit.currentVal()); - - CHECK (0 == jj.depth()); - jj.expandChildren(); - CHECK (1 == jj.depth()); - - CHECK (2 == *jj); - ++jj; - CHECK (1 == *jj); - + ++ii; + CHECK (2 == *ii); CHECK (2 == vsit.currentVal()); - CHECK (1 == jj.depth()); - ++jj; - CHECK (0 == jj.depth()); - CHECK (2 == *jj); - CHECK (2 == vsit.currentVal()); - ++jj; - CHECK (1 == *jj); + ++ii; + CHECK (1 == *ii); CHECK (1 == vsit.currentVal()); - ++jj; - CHECK (isnil (jj)); - CHECK (0 == vsit.currentVal()); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #888 + ++ii; + CHECK (isnil (ii)); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index aab077306..1bd5d100d 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -5149,7 +5149,7 @@ - + @@ -5892,7 +5892,7 @@ - + @@ -6364,17 +6364,17 @@ - + - + - - + + - - + + @@ -6749,7 +6749,7 @@ - + @@ -7065,13 +7065,16 @@ - - + + - - + + + + + @@ -8130,9 +8133,9 @@ - + - +