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>();
506 string renderCompact (RecRef
const&);
507 string renderCompact (Rec
const&);
521 template<
typename ELM>
530 static No check(...);
533 static const bool value = (
sizeof(Yes)==
sizeof(check<ELM>(0)));
570 : scope_? scope_.operator->()
608 std::deque<ScopeIter> scopes_;
614 scopes_.emplace_back(n);
620 return scopes_.size();
628 return not scopes_.empty()
629 and bool(scopes_.back());
635 return *(scopes_.back());
642 scopes_.emplace_back (current->data.expand());
644 while (not scopes_.empty() and not scopes_.back())
651 return not s1.scopes_.empty()
652 && not s2.scopes_.empty()
653 && s1.scopes_.size() == s2.scopes_.size()
654 && s1.yield() == s2.yield();
663 Rec* val = unConst(
this)->maybeGet<Rec>();
676 size_t level()
const {
return unConst(
this)->stateCore().depth(); }
687 GenNode::contains (X
const& elm)
const 689 for (
auto & n : *
this)
731 Rec* rec = maybeGet<Rec>();
732 if (rec)
return *rec;
741 Rec* rec = unConst(
this)->maybeGet<Rec>();
742 if (rec)
return *rec;
751 Rec* nested = maybeGet<Rec>();
754 RecRef* ref = maybeGet<RecRef>();
755 if (ref and not ref->empty())
771 Rec* nested = unConst(
this)->maybeAccessNestedRec();
772 return nested? nested->getType()
773 : util::BOTTOM_INDICATOR;
779 return nullptr != unConst(
this)->maybeAccessNestedRec();
784 inline std::optional<X>
787 static_assert (not std::is_reference_v<X>
788 ,
"optional access only possible by value");
790 Rec* nested = unConst(
this)->maybeAccessNestedRec();
791 if (nested and nested->hasAttribute (key))
793 DataCap const& nestedAttributeData = nested->get(key).data;
794 X* payload = unConst(nestedAttributeData).maybeGet<X>();
795 if (payload)
return *payload;
801 DataCap::hasAttribute (
string key)
const 803 Rec* nested = unConst(
this)->maybeAccessNestedRec();
804 return nested and nested->hasAttribute (key);
808 inline std::optional<X>
811 return data.retrieveAttribute<X> (key);
815 GenNode::hasAttribute (
string key)
const 817 return data.hasAttribute (key);
821 GenNode::isNested()
const 823 return data.isNested();
827 GenNode::hasChildren()
const 829 return not isnil (data.childIter());
832 inline Rec::scopeIter
833 GenNode::getChildren()
const 835 return data.childIter();
856 Ref(
string const& symbolicID)
857 :
GenNode(fabricateRefID<Rec> (symbolicID)
866 ,
DataCap(RecRef(oNode.data.get<Rec>())))
879 inline GenNode::GenNode(
Ref const& r) : idi(r.idi), data(r.data) { }
880 inline GenNode::GenNode(
Ref & r) : idi(r.idi), data(r.data) { }
881 inline GenNode::GenNode(
Ref && r) : idi(std::move(r.idi)),
882 data(std::move(r.data)) { }
891 return GenNode{std::move(record_)};
903 MakeRec::genNode (
string const& symbolicID)
905 return GenNode{symbolicID, std::move(record_)};
924 Rec::isAttribute (
GenNode const& attrib)
926 return attrib.isNamed();
931 Rec::isTypeID (
GenNode const& attrib)
933 return attrib.isTypeID();
938 Rec::extractTypeID (
GenNode const& v)
940 return isTypeID(v)? v.data.get<
string>()
946 Rec::extractKey (
GenNode const& v)
948 return isAttribute(v)? v.idi.getSym()
954 Rec::extractVal (
GenNode const& v)
961 Rec::renderAttribute (
GenNode const& a)
963 return a.idi.getSym() +
" = "+ string(a.data);
969 Rec::buildAttribute (
string const& key, X&& payload)
971 return GenNode{key, forward<X>(payload)};
985 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 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