72 #ifndef LIB_DIFF_TREE_MUTATOR_COLLECTION_BINDING_H 73 #define LIB_DIFF_TREE_MUTATOR_COLLECTION_BINDING_H 97 using lib::iter_stl::eachElm;
103 using _AsVector = std::vector<typename C::value_type>;
105 using _AsMap = std::map<typename C::key_type, typename C::mapped_type>;
114 template<
class C,
typename SEL =
void>
117 static_assert (not
sizeof(C),
"unable to determine any supported container type for C");
123 using Vec = _AsVector<V>;
124 using Elm =
typename Vec::value_type;
125 using Itr =
typename Vec::iterator;
128 recentElmRawIter (Vec& vec)
130 return Itr{&vec.back()};
134 append (Vec& vec, Elm&& elm)
136 vec.emplace_back (forward<Elm> (elm));
143 using Map = _AsMap<M>;
144 using Key =
typename Map::key_type;
145 using Val =
typename Map::mapped_type;
146 using Elm = std::pair<const Key, Val>;
156 auto& recentPos = ++map.rend();
157 return map.find (recentPos->first);
161 append (Map& map, Elm&& elm)
163 map.emplace (forward<Elm> (elm));
187 template<
class COLL,
class MAT,
class CTR,
class SEL,
class ASS,
class MUT>
192 using Elm =
typename Coll::value_type;
195 using iterator =
typename lib::iter_stl::_SeqT<Coll>::Range;
196 using const_iterator =
typename lib::iter_stl::_SeqT<const Coll>::Range;
235 contentBuffer.clear();
236 swap (collection, contentBuffer);
237 return eachElm (contentBuffer);
243 Trait::append (collection, forward<Elm>(elm));
247 search (
GenNode const& targetSpec, iterator pos)
249 while (pos and not matches(targetSpec, *pos))
259 if (not collection.empty()
260 and matches (targetSpec, recentElm()))
261 return recentElmIter();
263 return search (targetSpec, eachElm(collection));
277 return iterator{Trait::recentElmRawIter (collection), std::end (collection)};
283 return *Trait::recentElmRawIter (collection);
305 template<
class PAR,
class BIN>
309 using Iter =
typename BIN::iterator;
317 : PAR(std::forward<PAR>(chain))
318 , binding_(forward<BIN>(wiringClosures))
330 pos_ = binding_.initMutation();
342 if (binding_.isApplicable(n))
344 binding_.inject (std::move (binding_.construct(n)));
348 return PAR::injectNew (n);
354 return bool(pos_) or PAR::hasSrc();
362 if (binding_.isApplicable(spec))
363 return pos_ and binding_.matches (spec, *pos_);
365 return PAR::matchSrc (spec);
375 if (binding_.isApplicable(n))
388 if (binding_.isApplicable(n))
390 bool isSrcMatch = pos_ and binding_.matches (n, *pos_);
393 binding_.inject (move(*pos_));
399 return PAR::acceptSrc (n);
406 if (binding_.isApplicable(refSpec))
408 Iter found = binding_.search (refSpec, pos_);
411 binding_.inject (move(*found));
416 return PAR::findSrc (refSpec);
428 for ( ; pos_; ++pos_)
429 binding_.inject (move(*pos_));
430 return PAR::accept_until (spec);
433 if (binding_.isApplicable(spec))
435 bool foundTarget =
false;
436 while (pos_ and not binding_.matches (spec, *pos_))
438 binding_.inject (move(*pos_));
441 if (pos_ and binding_.matches (spec, *pos_))
443 binding_.inject (move(*pos_));
450 return PAR::accept_until (spec);
458 if (binding_.isApplicable(spec))
460 Iter target_found = binding_.locate (spec);
461 return target_found and binding_.assign (*target_found, spec);
464 return PAR::assignElm (spec);
482 if (binding_.isApplicable(spec))
484 Iter target_found = binding_.locate (spec);
485 return target_found and binding_.openSub (*target_found, spec.idi, targetBuff);
488 return PAR::mutateChild (spec, targetBuff);
496 return PAR::completeScope()
497 and isnil(this->pos_);
507 template<
class COLL,
class MAT,
class CTR,
class SEL,
class ASS,
class MUT>
574 , childMutationBuilder
581 template<
class COLL,
class MAT,
class CTR,
class SEL,
class ASS,
class MUT>
587 return CollectionBindingBuilder<Coll, MAT,CTR,SEL,ASS,MUT> {coll, m,c,s,a,u};
596 __ERROR_missing_matcher (
GenNode const&, ELM
const&)
598 throw error::Logic (
"unable to build a sensible default matching predicate");
602 __ERROR_missing_constructor (
GenNode const&)
604 throw error::Logic (
"unable to build a sensible default for creating new elements");
608 ignore_selector (
GenNode const& spec)
616 disable_assignment (ELM&,
GenNode const&)
630 attachTo (COLL& coll)
633 ,__ERROR_missing_matcher
634 ,__ERROR_missing_constructor
637 ,disable_childMutation
660 template<
class ELM,
typename SEL =
void>
670 attachTo (COLL& coll)
673 .matchElement([](
GenNode const& spec, ELM
const& elm)
677 .constructFrom([](
GenNode const& spec) -> ELM
679 return spec.data.get<ELM>();
692 attachTo (COLL& coll)
705 target.data = spec.data;
710 if (target.idi == subID
741 using Elm =
typename COLL::value_type;
752 Builder<PAR>::attach (BIN&& collectionBindingSetup)
754 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...