93 #ifndef LIB_DIFF_GEN_NODE_H 94 #define LIB_DIFF_GEN_NODE_H 121 using Storage = std::vector<GenNode>;
122 using ElmIter =
typename Storage::const_iterator;
172 bool matchData (
DataCap const&)
const;
173 bool matchNum (int64_t)
const;
174 bool matchTxt (
string const&)
const;
176 bool matchBool (
bool)
const;
177 bool matchDbl (
double)
const;
178 bool matchLuid (hash::LuidH)
const;
179 bool matchRec (RecRef
const&)
const;
180 bool matchRec (Rec
const&)
const;
185 operator string()
const;
190 X
const&
get()
const;
196 const Rec* rec = unConst(
this)->maybeGet<Rec>();
198 return Rec::scopeIter();
204 bool isNested()
const;
207 string recordType()
const;
212 retrieveAttribute (
string key)
const;
214 bool hasAttribute (
string key)
const;
217 Rec* maybeAccessNestedRec();
230 ID (X*,
string const& symbolicID)
232 idi::getTypeHash<X>())
247 operator string()
const 249 return "ID(\""+getSym()+
"\")";
262 : idi(&val, buildChildID<X>())
263 , data(std::forward<X>(val))
267 GenNode(
string const& symbolicID, X&& val)
268 : idi(&val, symbolicID)
269 , data(std::forward<X>(val))
272 GenNode(
string const& symbolicID,
const char* text)
273 :
GenNode(symbolicID,
string(text))
319 data = std::forward<DataCap>(o.data);
320 idi = std::forward<ID>(o.idi);
330 operator string()
const 332 return "GenNode-"+string(idi)+
"-"+string(data);
338 return not util::startsWith (idi.getSym(),
"_CHILD_");
344 return "type" == idi.getSym();
348 bool contains (X
const& elm)
const;
352 bool matches (
ID const&
id)
const {
return idi == id; }
353 bool matches (
int number)
const {
return data.matchNum(number);}
354 bool matches (int64_t number)
const {
return data.matchNum(number);}
355 bool matches (
short number)
const {
return data.matchNum(number);}
356 bool matches (
char number)
const {
return data.matchNum(number);}
357 bool matches (
double number)
const {
return data.matchDbl(number);}
358 bool matches (
string text)
const {
return data.matchTxt(text);}
359 bool matches (
const char* text)
const {
return data.matchTxt(text);}
361 bool matches (
bool b)
const {
return data.matchBool(b); }
362 bool matches (hash::LuidH h)
const {
return data.matchLuid(h); }
363 bool matches (RecRef
const& ref)
const {
return data.matchRec(ref); }
364 bool matches (Rec
const& rec)
const {
return data.matchRec(rec); }
398 childData (Rec::scopeIter&& scopeIter)
400 return ChildDataIter{ std::forward<Rec::scopeIter>(scopeIter)
401 , [](
GenNode const& child) ->DataCap
const&
412 return node.idi.getSym();
418 return n1.idi == n2.idi
425 return not (n1 == n2);
445 return left.idi.getSym() < right.idi.getSym();
461 retrieveAttribute (
string key)
const;
463 bool hasAttribute (
string key)
const;
464 bool isNested()
const;
465 bool hasChildren()
const;
466 Rec::scopeIter getChildren()
const;
479 fabricateRefID (
string const& symbolicID)
482 return ID(typeID, symbolicID);
490 return "_CHILD_" + idi::generateSymbolicID<X>();
497 string renderCompact (RecRef
const&);
498 string renderCompact (Rec
const&);
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>();
665 using IterStateWrapper::IterStateWrapper;
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_"
string renderCompact(Rec const &rec)
compact textual representation of a Record<GenNode> (»object«).
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 as »*State Core*...
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