81 #ifndef LIB_DIFF_TREE_MUTATOR_COLLECTION_BINDING_H 82 #define LIB_DIFF_TREE_MUTATOR_COLLECTION_BINDING_H 106 using lib::iter_stl::eachElm;
112 using _AsVector = std::vector<typename C::value_type>;
114 using _AsMap = std::map<typename C::key_type, typename C::mapped_type>;
123 template<
class C,
typename SEL =
void>
126 static_assert (not
sizeof(C),
"unable to determine any supported container type for C");
132 using Vec = _AsVector<V>;
133 using Elm =
typename Vec::value_type;
134 using Itr =
typename Vec::iterator;
137 recentElmRawIter (Vec& vec)
139 return Itr{&vec.back()};
143 append (Vec& vec, Elm&& elm)
145 vec.emplace_back (forward<Elm> (elm));
152 using Map = _AsMap<M>;
153 using Key =
typename Map::key_type;
154 using Val =
typename Map::mapped_type;
155 using Elm = std::pair<const Key, Val>;
165 auto& recentPos = ++map.rend();
166 return map.find (recentPos->first);
170 append (Map& map, Elm&& elm)
172 map.emplace (forward<Elm> (elm));
196 template<
class COLL,
class MAT,
class CTR,
class SEL,
class ASS,
class MUT>
201 using Elm =
typename Coll::value_type;
204 using iterator =
typename lib::iter_stl::_SeqT<Coll>::Range;
205 using const_iterator =
typename lib::iter_stl::_SeqT<const Coll>::Range;
244 contentBuffer.clear();
245 swap (collection, contentBuffer);
246 return eachElm (contentBuffer);
252 Trait::append (collection, forward<Elm>(elm));
256 search (
GenNode const& targetSpec, iterator pos)
258 while (pos and not matches(targetSpec, *pos))
268 if (not collection.empty()
269 and matches (targetSpec, recentElm()))
270 return recentElmIter();
272 return search (targetSpec, eachElm(collection));
286 return iterator{Trait::recentElmRawIter (collection), std::end (collection)};
292 return *Trait::recentElmRawIter (collection);
314 template<
class PAR,
class BIN>
318 using Iter =
typename BIN::iterator;
326 : PAR(std::forward<PAR>(chain))
327 , binding_(forward<BIN>(wiringClosures))
339 pos_ = binding_.initMutation();
351 if (binding_.isApplicable(n))
353 binding_.inject (std::move (binding_.construct(n)));
357 return PAR::injectNew (n);
363 return bool(pos_) or PAR::hasSrc();
371 if (binding_.isApplicable(spec))
372 return pos_ and binding_.matches (spec, *pos_);
374 return PAR::matchSrc (spec);
384 if (binding_.isApplicable(n))
397 if (binding_.isApplicable(n))
399 bool isSrcMatch = pos_ and binding_.matches (n, *pos_);
402 binding_.inject (move(*pos_));
408 return PAR::acceptSrc (n);
415 if (binding_.isApplicable(refSpec))
417 Iter found = binding_.search (refSpec, pos_);
420 binding_.inject (move(*found));
425 return PAR::findSrc (refSpec);
437 for ( ; pos_; ++pos_)
438 binding_.inject (move(*pos_));
439 return PAR::accept_until (spec);
442 if (binding_.isApplicable(spec))
444 bool foundTarget =
false;
445 while (pos_ and not binding_.matches (spec, *pos_))
447 binding_.inject (move(*pos_));
450 if (pos_ and binding_.matches (spec, *pos_))
452 binding_.inject (move(*pos_));
459 return PAR::accept_until (spec);
467 if (binding_.isApplicable(spec))
469 Iter target_found = binding_.locate (spec);
470 return target_found and binding_.assign (*target_found, spec);
473 return PAR::assignElm (spec);
491 if (binding_.isApplicable(spec))
493 Iter target_found = binding_.locate (spec);
494 return target_found and binding_.openSub (*target_found, spec.idi, targetBuff);
497 return PAR::mutateChild (spec, targetBuff);
505 return PAR::completeScope()
506 and isnil(this->pos_);
516 template<
class COLL,
class MAT,
class CTR,
class SEL,
class ASS,
class MUT>
583 , childMutationBuilder
590 template<
class COLL,
class MAT,
class CTR,
class SEL,
class ASS,
class MUT>
596 return CollectionBindingBuilder<Coll, MAT,CTR,SEL,ASS,MUT> {coll, m,c,s,a,u};
605 __ERROR_missing_matcher (
GenNode const&, ELM
const&)
607 throw error::Logic (
"unable to build a sensible default matching predicate");
611 __ERROR_missing_constructor (
GenNode const&)
613 throw error::Logic (
"unable to build a sensible default for creating new elements");
617 ignore_selector (
GenNode const& spec)
625 disable_assignment (ELM&,
GenNode const&)
639 attachTo (COLL& coll)
642 ,__ERROR_missing_matcher
643 ,__ERROR_missing_constructor
646 ,disable_childMutation
669 template<
class ELM,
typename SEL =
void>
679 attachTo (COLL& coll)
682 .matchElement([](
GenNode const& spec, ELM
const& elm)
686 .constructFrom([](
GenNode const& spec) -> ELM
688 return spec.data.get<ELM>();
701 attachTo (COLL& coll)
714 target.data = spec.data;
719 if (target.idi == subID
750 using Elm =
typename COLL::value_type;
761 Builder<PAR>::attach (BIN&& collectionBindingSetup)
763 return chainedBuilder<ChildCollectionMutator<PAR,BIN>> (forward<BIN>(collectionBindingSetup));
#define ASSERT_VALID_SIGNATURE(_FUN_, _SIG_)
Macro for a compile-time check to verify the given generic functors or lambdas expose some expected s...
metafunction to detect types able to be wrapped into a GenNode.
static auto recentElmRawIter(Map &map)
heuristic for std::map: lookup via reverse iterator.
virtual void skipSrc(GenNode const &n) override
skip next pending src element, causing this element to be discarded
bool isNested() const
determine if payload constitutes a nested scope ("object")
Attach to collection: Building block for a concrete TreeMutator.
virtual bool accept_until(GenNode const &spec) override
repeatedly accept, until after the designated location
Types marked with this mix-in may be moved but not copied.
auto createCollectionBindingBuilder(COLL &coll, MAT m, CTR c, SEL s, ASS a, MUT u)
builder function to synthesise builder type from given functors
Record< VAL >::Mutator & mutateInPlace(Record< VAL > &record_to_mutate)
open an existing record for modification in-place.
Helper for uniform treatment of various STL containers.
starting point for configuration of a binding to STL container.
CollectionBindingBuilder< COLL, MAT, CTR, FUN,ASS, MUT > isApplicableIf(FUN selector)
CollectionBindingBuilder< COLL, MAT, CTR, SEL, FUN,MUT > assignElement(FUN setter)
Implementation namespace for support and library code.
Derived specific exceptions within Lumiera's exception hierarchy.
virtual bool injectNew(GenNode const &n) override
fabricate a new element, based on the given specification (GenNode), and insert it at current positio...
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Nested DSL to define the specifics of a collection binding.
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBu...
virtual bool acceptSrc(GenNode const &n) override
accept existing element, when matching the given spec
static const Ref END
symbolic ID ref "_END_"
Attach to collection: Concrete binding setup.
iterator locate(GenNode const &targetSpec)
locate element for assignment or mutation, with special shortcut to the recently inserted element ...
Generic building block for tree shaped (meta)data structures.
CollectionBindingBuilder< COLL, MAT, CTR, SEL, ASS, FUN > buildChildMutator(FUN childMutationBuilder)
Helpers for type detection, type rewriting and metaprogramming.
Lumiera error handling (C++ interface).
bool matches(GenNode const &o) const
static const Ref ATTRIBS
symbolic ID ref "_ATTRIBS_"
Customisable intermediary to abstract generic tree mutation operations.
virtual bool completeScope() override
verify all our pending (old) source elements where mentioned.
virtual bool matchSrc(GenNode const &spec) override
ensure the next recorded source element matches on a formal level with given spec ...
CollectionBindingBuilder< COLL, FUN,CTR, SEL, ASS, MUT > matchElement(FUN matcher)
auto collection(COLL &coll)
Entry point to a nested DSL for setup and configuration of a collection binding.
Preconfigured adapters for some STL container standard usage situations.
virtual bool findSrc(GenNode const &refSpec) override
locate designated element and accept it at current position
CollectionBindingBuilder< COLL, MAT, FUN,SEL, ASS, MUT > constructFrom(FUN constructor)
object-like record of data.
virtual bool mutateChild(GenNode const &spec, TreeMutator::Handle targetBuff) override
locate the designated target element and build a suitable sub-mutator for this element into the provi...
generic data element node within a tree
virtual bool assignElm(GenNode const &spec) override
locate element already accepted into the target sequence and assign the designated payload value to i...