102 #ifndef LIB_DIFF_GEN_NODE_H 103 #define LIB_DIFF_GEN_NODE_H 130 using Storage = std::vector<GenNode>;
131 using ElmIter =
typename Storage::const_iterator;
181 bool matchData (
DataCap const&)
const;
182 bool matchNum (int64_t)
const;
183 bool matchTxt (
string const&)
const;
185 bool matchBool (
bool)
const;
186 bool matchDbl (
double)
const;
187 bool matchLuid (hash::LuidH)
const;
188 bool matchRec (RecRef
const&)
const;
189 bool matchRec (Rec
const&)
const;
194 operator string()
const;
199 X
const&
get()
const;
205 const Rec* rec = unConst(
this)->maybeGet<Rec>();
207 return Rec::scopeIter();
213 bool isNested()
const;
216 string recordType()
const;
221 retrieveAttribute (
string key)
const;
223 bool hasAttribute (
string key)
const;
226 Rec* maybeAccessNestedRec();
239 ID (X*,
string const& symbolicID)
241 idi::getTypeHash<X>())
256 operator string()
const 258 return "ID(\""+getSym()+
"\")";
271 : idi(&val, buildChildID<X>())
272 , data(std::forward<X>(val))
276 GenNode(
string const& symbolicID, X&& val)
277 : idi(&val, symbolicID)
278 , data(std::forward<X>(val))
281 GenNode(
string const& symbolicID,
const char* text)
282 :
GenNode(symbolicID,
string(text))
328 data = std::forward<DataCap>(o.data);
329 idi = std::forward<ID>(o.idi);
339 operator string()
const 341 return "GenNode-"+string(idi)+
"-"+string(data);
347 return not util::startsWith (idi.getSym(),
"_CHILD_");
353 return "type" == idi.getSym();
357 bool contains (X
const& elm)
const;
361 bool matches (
ID const&
id)
const {
return idi == id; }
362 bool matches (
int number)
const {
return data.matchNum(number);}
363 bool matches (int64_t number)
const {
return data.matchNum(number);}
364 bool matches (
short number)
const {
return data.matchNum(number);}
365 bool matches (
char number)
const {
return data.matchNum(number);}
366 bool matches (
double number)
const {
return data.matchDbl(number);}
367 bool matches (
string text)
const {
return data.matchTxt(text);}
368 bool matches (
const char* text)
const {
return data.matchTxt(text);}
370 bool matches (
bool b)
const {
return data.matchBool(b); }
371 bool matches (hash::LuidH h)
const {
return data.matchLuid(h); }
372 bool matches (RecRef
const& ref)
const {
return data.matchRec(ref); }
373 bool matches (Rec
const& rec)
const {
return data.matchRec(rec); }
407 childData (Rec::scopeIter&& scopeIter)
409 return ChildDataIter{ std::forward<Rec::scopeIter>(scopeIter)
410 , [](
GenNode const& child) ->DataCap
const&
421 return node.idi.getSym();
427 return n1.idi == n2.idi
434 return not (n1 == n2);
454 return left.idi.getSym() < right.idi.getSym();
470 retrieveAttribute (
string key)
const;
472 bool hasAttribute (
string key)
const;
473 bool isNested()
const;
474 bool hasChildren()
const;
475 Rec::scopeIter getChildren()
const;
488 fabricateRefID (
string const& symbolicID)
491 return ID(typeID, symbolicID);
499 return "_CHILD_" + idi::generateSymbolicID<X>();
512 template<
typename ELM>
521 static No check(...);
524 static const bool value = (
sizeof(Yes)==
sizeof(check<ELM>(0)));
561 : scope_? scope_.operator->()
599 std::deque<ScopeIter> scopes_;
605 scopes_.emplace_back(n);
611 return scopes_.size();
619 return not scopes_.empty()
620 and bool(scopes_.back());
626 return *(scopes_.back());
633 scopes_.emplace_back (current->data.expand());
635 while (not scopes_.empty() and not scopes_.back())
642 return not s1.scopes_.empty()
643 && not s2.scopes_.empty()
644 && s1.scopes_.size() == s2.scopes_.size()
645 && s1.yield() == s2.yield();
654 Rec* val = unConst(
this)->maybeGet<Rec>();
667 size_t level()
const {
return unConst(
this)->stateCore().depth(); }
678 GenNode::contains (X
const& elm)
const 680 for (
auto & n : *
this)
722 Rec* rec = maybeGet<Rec>();
723 if (rec)
return *rec;
732 Rec* rec = unConst(
this)->maybeGet<Rec>();
733 if (rec)
return *rec;
742 Rec* nested = maybeGet<Rec>();
745 RecRef* ref = maybeGet<RecRef>();
746 if (ref and not ref->empty())
762 Rec* nested = unConst(
this)->maybeAccessNestedRec();
763 return nested? nested->getType()
764 : util::BOTTOM_INDICATOR;
770 return nullptr != unConst(
this)->maybeAccessNestedRec();
775 inline std::optional<X>
778 static_assert (not std::is_reference_v<X>
779 ,
"optional access only possible by value");
781 Rec* nested = unConst(
this)->maybeAccessNestedRec();
782 if (nested and nested->hasAttribute (key))
784 DataCap const& nestedAttributeData = nested->get(key).data;
785 X* payload = unConst(nestedAttributeData).maybeGet<X>();
786 if (payload)
return *payload;
792 DataCap::hasAttribute (
string key)
const 794 Rec* nested = unConst(
this)->maybeAccessNestedRec();
795 return nested and nested->hasAttribute (key);
799 inline std::optional<X>
802 return data.retrieveAttribute<X> (key);
806 GenNode::hasAttribute (
string key)
const 808 return data.hasAttribute (key);
812 GenNode::isNested()
const 814 return data.isNested();
818 GenNode::hasChildren()
const 820 return not isnil (data.childIter());
823 inline Rec::scopeIter
824 GenNode::getChildren()
const 826 return data.childIter();
847 Ref(
string const& symbolicID)
848 :
GenNode(fabricateRefID<Rec> (symbolicID)
857 ,
DataCap(RecRef(oNode.data.get<Rec>())))
870 inline GenNode::GenNode(
Ref const& r) : idi(r.idi), data(r.data) { }
871 inline GenNode::GenNode(
Ref & r) : idi(r.idi), data(r.data) { }
872 inline GenNode::GenNode(
Ref && r) : idi(std::move(r.idi)),
873 data(std::move(r.data)) { }
882 return GenNode{std::move(record_)};
894 MakeRec::genNode (
string const& symbolicID)
896 return GenNode{symbolicID, std::move(record_)};
915 Rec::isAttribute (
GenNode const& attrib)
917 return attrib.isNamed();
922 Rec::isTypeID (
GenNode const& attrib)
924 return attrib.isTypeID();
929 Rec::extractTypeID (
GenNode const& v)
931 return isTypeID(v)? v.data.get<
string>()
937 Rec::extractKey (
GenNode const& v)
939 return isAttribute(v)? v.idi.getSym()
945 Rec::extractVal (
GenNode const& v)
952 Rec::renderAttribute (
GenNode const& a)
954 return a.idi.getSym() +
" = "+ string(a.data);
960 Rec::buildAttribute (
string const& key, X&& payload)
962 return GenNode{key, forward<X>(payload)};
976 template<
typename TYPES>
static const Ref I
symbolic ID ref "_I_"
type erased baseclass for building a combined hash and symbolic ID.
metafunction to detect types able to be wrapped into a GenNode.
Constructor for a specially crafted 'ref GenNode'.
bool isNested() const
determine if payload constitutes a nested scope ("object")
friend ChildDataIter childData(GenNode const &n)
visit the data of nested child elements
GenNode(ID &&id, DataCap &&d)
std::optional< X > retrieveAttribute(string key) const
peek into the attributes of a nested Record
Rec::scopeIter childIter() const
visit children of a nested Record<GenNode>
bool operator==(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
Supporting equality comparisons...
static const Ref CHILD
symbolic ID ref "_CHILD_"
Building block for monad-like depth-first expansion of a GenNode.
iterator begin() const
default iteration exposes all data within this "object", starting with the attributes ...
Implementation namespace for support and library code.
Lumiera's internal time value datatype.
Special collection to represent object-like data.
static const Ref END
symbolic ID ref "_END_"
bool matchData(DataCap const &) const
Implementation of content equality test, delgating to content.
allow for storage in ordered containers, ordering based on the human-readable ID within the GenNode...
A typesafe union record to carry embedded values of unrelated type.
Another Lumiera Forward Iterator building block, based on incorporating a state type right into the i...
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
wrapped record reference.
Rec * maybeAccessNestedRec()
std::optional< X > retrieveAttribute(string key) const
mismatch tolerant convenience shortcut to peek into the attributes of a nested Record ...
static const Ref NO
symbolic ID ref "_NO_"
void buildMutator(BufferHandle)
attachment point to receive and apply tree-diff changes.
Lumiera error handling (C++ interface).
static GenNode asAttribute(idi::BareEntryID &&rawID, X &&payload)
fabricate a GenNode with the literally given ID
Hash implementation based on a lumiera unique object id (LUID) When invoking the default ctor...
bool matches(GenNode const &o) const
static const Ref ATTRIBS
symbolic ID ref "_ATTRIBS_"
Offset measures a distance in time.
string recordType() const
peek into the type field of a nested Record<GenNode>
Duration is the internal Lumiera time metric.
Ref(string const &symbolicID)
create an empty ID stand-in.
Bare symbolic and hash ID used for accounting of asset like entries.
std::function< UICoord(Literal)> Locator
Locator is a functor to resolve to a topological location in the UI-tree.
A time interval anchored at a specific point in time.
Ref(GenNode &oNode)
build reference to a Record, using the original ID
a family of time value like entities and their relationships.
object-like record of data.
static const Ref THIS
symbolic ID ref "_THIS_"
basic constant internal time value.
GenNode const & Access
using const reference data access relevant for handling large subtrees
Adapter for building an implementation of the »Lumiera Forward Iterator« concept. ...
generic data element node within a tree