Lumiera  0.pre.03
»edit your freedom«
iter-chain-search.hpp
Go to the documentation of this file.
1 /*
2  ITER-CHAIN-SEARCH.hpp - chained search with backtracking based on (bidirectional) iterator
3 
4  Copyright (C) Lumiera.org
5  2018, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
76 #ifndef SRC_LIB_ITER_CHAIN_SEARCH_H
77 #define SRC_LIB_ITER_CHAIN_SEARCH_H
78 
79 
80 #include "lib/error.hpp"
81 #include "lib/iter-explorer.hpp"
82 #include "lib/meta/util.hpp"
83 
84 #include <utility>
85 #include <vector>
86 #include <string>
87 
88 
89 namespace lib {
90 namespace iter {
91 
92  using std::move;
93  using std::forward;
94  using std::string;
95 
96  using lib::meta::disable_if;
97 
98 
99  namespace { // type construction helpers...
100 
101  template<class SRC>
102  auto
103  buildSearchFilter (SRC&& dataSource)
104  {
105  return explore (forward<SRC> (dataSource))
106  .mutableFilter();
107  }
108 
116  template<class SRC>
117  auto
118  buildChainExplorer (SRC&& dataSource)
119  {
120  return buildSearchFilter (forward<SRC> (dataSource))
121  .expand ([](auto it){ return it; }); // child iterator starts as copy of current level iterator
122  }
123 
133  template<class SRC>
135  {
136  using Filter = decltype( buildSearchFilter(std::declval<SRC>()).asIterator() );
137  using Pipeline = decltype( buildChainExplorer (std::declval<SRC>()) );
138 
140  using StepFunctor = std::function<void(Filter&)>;
141  };
142 
143  }//(End)type construction helpers
144 
145 
146 
147 
148 
149  /*********************************************************************************************************/
157  template<class SRC>
159  : public _IterChainSetup<SRC>::Pipeline
160  {
161  using _Trait = _IterChainSetup<SRC>;
162  using _Base = typename _Trait::Pipeline;
163 
164  using Value = typename _Base::value_type;
165  using Filter = typename _Trait::Filter;
166  using Step = typename _Trait::StepFunctor;
167 
169  std::vector<Step> stepChain_;
170 
171 
172  bool
173  needsExpansion() const
174  {
175  return _Base::depth() < stepChain_.size();
176  }
177 
178  public:
185  template<class SEQ>
186  explicit
187  IterChainSearch (SEQ&& srcData)
188  : _Base{buildChainExplorer (forward<SEQ> (srcData))}
189  { // mark initial pristine state
190  _Base::disableFilter();
191  }
192 
193  // inherited default ctor and standard copy operations
194  using _Base::_Base;
195 
196 
197  /* === adapted iteration control API === */
198  void
199  iterNext()
200  {
201  _Base::__throw_if_empty();
202  if (not needsExpansion())
203  _Base::iterNext();
204  while (needsExpansion() // Backtracking loop: attempt to establish all conditions
205  and _Base::checkPoint()) // possibly trying further combinations until success:
206  {
207  uint depth =_Base::depth();
208  _Base::expandChildren(); // create copy of current filter embedded into child level
209  stepChain_[depth] (_Base::accessCurrentChildIter()); // invoke step functor to reconfigure this filter...
210  _Base::dropExhaustedChildren(); // which thereby might become empty
211  }
212  }
213 
215  operator++()
216  {
217  iterNext();
218  return *this;
219  }
220 
221 
222 
237  template<typename FUN>
239  addStep (FUN&& configureSearchStep)
240  {
241  if (not this->empty())
242  {
243  Step nextStep{forward<FUN> (configureSearchStep)};
244 
245  if (_Base::isDisabled())
246  nextStep (*this); // apply first step immediately
247  else // (implicitly enables the base filter)
248  {
249  stepChain_.emplace_back (move (nextStep)); // append all further steps into the chain...
250  this->iterNext(); // then establish invariant:
251  } // expand to leaf and forward to first match
252  }
253  return move(*this);
254  }
255 
262  template<typename FUN>
263  disable_if<is_convertible<FUN, Value>,
264  IterChainSearch&& >
265  search (FUN&& filterPredicate)
266  {
267  addStep ([predicate{forward<FUN> (filterPredicate)}]
268  (Filter& filter)
269  { // manipulate current filter configuration
270  filter.setNewFilter (predicate);
271  });
272  return move(*this);
273  }
274 
280  search (Value target)
281  {
282  search ([target](Value const& currVal) { return currVal == target; });
283  return move(*this);
284  }
285 
293  {
294  stepChain_.clear();
295  _Base::rootCurrent();
296  _Base::disableFilter();
297  return move(*this);
298  }
299  };
300 
301 
302 
303 
304  /* ==== convenient builder free function ==== */
305 
317  template<class SRC>
318  inline auto
319  chainSearch (SRC&& srcData)
320  {
321  return IterChainSearch<SRC>{forward<SRC> (srcData)};
322  }
323 
324 
325 
326 }} // namespace lib::iter
327 #endif /*SRC_LIB_ITER_CHAIN_SEARCH_H*/
auto chainSearch(SRC &&srcData)
setup a chain search configuration by suitably wrapping the given container.
std::function< void(Filter &)> StepFunctor
each step in the chain is a functor to reconfigure the underlying filter
auto explore(IT &&srcSeq)
start building a IterExplorer by suitably wrapping the given iterable source.
bool filter(Placement< DummyMO > const &candidate)
a filter predicate to pick some objects from a resultset.
Simple and lightweight helpers for metaprogramming and type detection.
IterChainSearch(SEQ &&srcData)
Build a chain-search mechanism based on the given source data sequence.
std::vector< Step > stepChain_
Storage for a sequence of filter configuration functors.
Implementation namespace for support and library code.
IterChainSearch && search(Value target)
attach additional direct search for a given value.
IterChainSearch && addStep(FUN &&configureSearchStep)
configure additional chained search condition.
Iterator based linear search mechanism, with the ability to perform consecutive search with backtrack...
Lumiera error handling (C++ interface).
disable_if< is_convertible< FUN, Value >, IterChainSearch &&> search(FUN &&filterPredicate)
attach additional search with the given filter predicate.
Building tree expanding and backtracking evaluations within hierarchical scopes.
IterChainSearch && clearFilter()
drop all search condition frames.
auto buildChainExplorer(SRC &&dataSource)
define the chained-search mechanism: invoking filter.expandChildren() adds a new layer with the copy ...