Lumiera  0.pre.03
»edityourfreedom«
gen-node.hpp
Go to the documentation of this file.
1 /*
2  GEN-NODE.hpp - generic node element for tree like data representation
3 
4  Copyright (C) Lumiera.org
5  2015, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
92 #ifndef LIB_DIFF_GEN_NODE_H
93 #define LIB_DIFF_GEN_NODE_H
94 
95 
96 #include "lib/error.hpp"
97 #include "lib/idi/entry-id.hpp"
98 #include "lib/time/timevalue.hpp"
99 #include "lib/diff/record.hpp"
100 #include "lib/variant.hpp"
101 #include "lib/util.hpp"
102 
103 #include <utility>
104 #include <string>
105 #include <deque>
106 
107 
108 namespace lib {
109 namespace diff{
110 
111  namespace error = lumiera::error;
112 
113  using std::string;
114 
115  struct GenNode;
116  struct Ref;
117 
119  template<>
121  {
122  using Storage = std::vector<GenNode>;
124 
127  using Access = GenNode const&;
128  };
129 
130 
131 
132 
136  using DataValues = meta::Types<int
137  ,int64_t
138  ,short
139  ,char
140  ,bool
141  ,double
142  ,string
143  ,time::Time
144  ,time::Offset
147  ,hash::LuidH
148  ,RecRef
149  ,Rec
150  >;
151 
152 
153 
154  class DataCap
155  : public Variant<DataValues>
156  {
157  public:
158  template<typename X>
159  DataCap(X&& x)
160  : Variant<DataValues>(std::forward<X>(x))
161  { }
162 
164  DataCap(DataCap const&) =default;
165  DataCap(DataCap&&) =default;
167  : DataCap((DataCap const&)o)
168  { }
169 
170  DataCap& operator= (DataCap const&) =default;
171  DataCap& operator= (DataCap&&) =default;
172 
173  bool matchData (DataCap const&) const;
174  bool matchNum (int64_t) const;
175  bool matchTxt (string const&) const;
176  bool matchTime (time::TimeValue) const;
177  bool matchBool (bool) const;
178  bool matchDbl (double) const;
179  bool matchLuid (hash::LuidH) const;
180  bool matchRec (RecRef const&) const;
181  bool matchRec (Rec const&) const;
182 
183  struct Locator;
184  Locator expand() const;
185 
186  operator string() const;
187 
188  template<typename X>
189  X& get();
190  template<typename X>
191  X const& get() const;
192 
194  bool isNested() const;
195 
197  string recordType() const;
198 
201  childIter() const
202  {
203  const Rec* rec = unConst(this)->maybeGet<Rec>();
204  if (!rec)
205  return Rec::scopeIter();
206  else
207  return rec->scope();
208  }
209  };
210 
211 
213  struct GenNode
214  {
215  class ID
216  : public idi::BareEntryID
217  {
218  friend struct GenNode;
219 
220  template<typename X>
221  ID (X*, string const& symbolicID)
222  : idi::BareEntryID (symbolicID,
223  idi::getTypeHash<X>())
224  { }
225 
226  public:
227  ID (GenNode const& node)
228  : ID(node.idi)
229  { }
230 
231  // standard copy operations acceptable
232 
233  operator string() const
234  {
235  return "ID(\""+getSym()+"\")";
236  }
237  };
238 
239 
240  //------GenNode Data fields---
241 
244 
245 
246  template<typename X>
247  GenNode(X&& val)
248  : idi(&val, buildChildID<X>())
249  , data(std::forward<X>(val))
250  { }
251 
252  template<typename X>
253  GenNode(string const& symbolicID, X&& val)
254  : idi(&val, symbolicID)
255  , data(std::forward<X>(val))
256  { }
257 
258  GenNode(string const& symbolicID, const char* text)
259  : GenNode(symbolicID, string(text))
260  { }
261 
262  GenNode(const char* text)
263  : GenNode(string(text))
264  { }
265 
267  GenNode(GenNode const&) =default;
268  GenNode(GenNode&&) =default;
269  GenNode(GenNode& o) : GenNode((GenNode const&)o) { }
270  GenNode(Ref const& r);
271  GenNode(Ref & r);
272  GenNode(Ref && r);
273 
290  GenNode&
291  operator= (GenNode const& o)
292  {
293  if (&o != this)
294  {
295  data = o.data;
296  idi = o.idi;
297  }
298  return *this;
299  }
300 
301  GenNode&
302  operator= (GenNode&& o)
303  {
304  ASSERT (&o != this);
305  data = std::forward<DataCap>(o.data);
306  idi = std::forward<ID>(o.idi);
307  return *this;
308  }
309 
310  //note: NOT defining a swap operation, because swapping inline storage is pointless!
311 
312 
313 
314 
316  operator string() const
317  {
318  return "GenNode-"+string(idi)+"-"+string(data);
319  }
320 
321  bool
322  isNamed() const
323  {
324  return not util::startsWith (idi.getSym(), "_CHILD_");
325  }
326 
327  bool
328  isTypeID() const
329  {
330  return "type" == idi.getSym();
331  }
332 
333  template<typename X>
334  bool contains (X const& elm) const;
335 
336 
337  bool matches (GenNode const& o) const { return this->matches(o.idi); }
338  bool matches (ID const& id) const { return idi == id; }
339  bool matches (int number) const { return data.matchNum(number);}
340  bool matches (int64_t number) const { return data.matchNum(number);}
341  bool matches (short number) const { return data.matchNum(number);}
342  bool matches (char number) const { return data.matchNum(number);}
343  bool matches (double number) const { return data.matchDbl(number);}
344  bool matches (string text) const { return data.matchTxt(text);}
345  bool matches (const char* text) const { return data.matchTxt(text);}
346  bool matches (time::TimeValue t) const { return data.matchTime(t); }
347  bool matches (bool b) const { return data.matchBool(b); }
348  bool matches (hash::LuidH h) const { return data.matchLuid(h); }
349  bool matches (RecRef const& ref) const { return data.matchRec(ref); }
350  bool matches (Rec const& rec) const { return data.matchRec(rec); }
351 
352  class ScopeExplorer;
353 
354  struct ScopeExplorerIterator;
356 
357  iterator begin() ;
358  iterator begin() const;
359  iterator end() ;
360  iterator end() const;
361 
362 
364 
372  friend ChildDataIter
373  childData (GenNode const& n)
374  {
375  return ChildDataIter{ n.data.childIter()
376  , [](GenNode const& child) ->DataCap const&
377  {
378  return child.data;
379  }
380  };
381  }
382 
383  friend ChildDataIter
384  childData (Rec::scopeIter&& scopeIter)
385  {
386  return ChildDataIter{ std::forward<Rec::scopeIter>(scopeIter)
387  , [](GenNode const& child) ->DataCap const&
388  {
389  return child.data;
390  }
391  };
392  }
393 
394 
395  friend string
396  name (GenNode const& node)
397  {
398  return node.idi.getSym();
399  }
400 
401  friend bool
402  operator== (GenNode const& n1, GenNode const& n2)
403  {
404  return n1.idi == n2.idi
405  && n1.data.matchData(n2.data);
406  }
407 
408  friend bool
409  operator!= (GenNode const& n1, GenNode const& n2)
410  {
411  return not (n1 == n2);
412  }
413 
427  {
428  bool
429  operator() (GenNode const& left, GenNode const& right) const
430  {
431  return left.idi.getSym() < right.idi.getSym();
432  }
433  };
434 
435 
436  protected:
438  GenNode (ID&& id, DataCap&& d)
439  : idi(std::move(id))
440  , data(std::move(d))
441  { }
442 
443  template<typename X>
444  static GenNode::ID
445  fabricateRefID (string const& symbolicID)
446  {
447  X* typeID(0);
448  return ID(typeID, symbolicID);
449  }
450 
451  private:
452  template<typename X>
453  static string
455  {
456  return "_CHILD_" + idi::generateSymbolicID<X>();
457  }
458  };
459 
460 
461 
469  template<typename ELM>
471  {
474 
475  template<class X>
476  static Yes check(typename variant::CanBuildFrom<X, DataValues>::Type*);
477  template<class X>
478  static No check(...);
479 
480  public:
481  static const bool value = (sizeof(Yes)==sizeof(check<ELM>(0)));
482  };
483 
484 
485 
486 
487  /* === iteration / recursive expansion === */
488 
489 
497  {
498  const GenNode* node_;
500 
502  : node_(nullptr)
503  { }
504 
505  Locator(GenNode const& n)
506  : node_(&n)
507  { }
508 
509  Locator(Rec const& r)
510  : node_(nullptr)
511  , scope_(r.begin())
512  { }
513 
514  const GenNode *
515  get() const
516  {
517  return node_? node_
518  : scope_? scope_.operator->()
519  : nullptr;
520  }
521 
522  /* === Iteration control API for IterStateWrapper == */
523 
524  bool
525  checkPoint() const
526  {
527  return this->get();
528  }
529 
530  GenNode const&
531  yield() const
532  {
533  return *get();
534  }
535 
536  void
538  {
539  if (node_)
540  node_ = nullptr;
541  else
542  ++scope_;
543  }
544  };
545 
546 
553  {
555 
556  std::deque<ScopeIter> scopes_;
557 
558  public:
561  {
562  scopes_.emplace_back(n);
563  }
564 
565  size_t
566  depth() const
567  {
568  return scopes_.size();
569  }
570 
571  /* === Iteration control API for IterStateWrapper == */
572 
573  bool
574  checkPoint() const
575  {
576  return not scopes_.empty()
577  and bool(scopes_.back());
578  }
579 
580  GenNode const&
581  yield() const
582  {
583  return *(scopes_.back());
584  }
585 
586  void
588  {
589  ScopeIter& current = scopes_.back();
590  scopes_.emplace_back (current->data.expand());
591  ++current;
592  while (not scopes_.empty() and not scopes_.back())
593  scopes_.pop_back();
594  }
595 
596  friend bool
598  {
599  return not s1.scopes_.empty()
600  && not s2.scopes_.empty()
601  && s1.scopes_.size() == s2.scopes_.size()
602  && s1.yield() == s2.yield();
603  }
604  };
605 
606 
608  inline DataCap::Locator
610  {
611  Rec* val = unConst(this)->maybeGet<Rec>();
612  if (!val)
613  return Locator();
614  else
615  return Locator(*val);
616  }
617 
618 
620  : IterStateWrapper<const GenNode, ScopeExplorer>
621  {
623 
624  size_t level() const { return unConst(this)->stateCore().depth(); }
625  };
626 
627 
628  inline GenNode::iterator GenNode::begin() { return iterator(*this); }
629  inline GenNode::iterator GenNode::begin() const { return iterator(*this); }
630  inline GenNode::iterator GenNode::end() { return iterator(); }
631  inline GenNode::iterator GenNode::end() const { return iterator(); }
632 
633  template<typename X>
634  inline bool
635  GenNode::contains (X const& elm) const
636  {
637  for (auto & n : *this)
638  if (n.matches(elm))
639  return true;
640  return false;
641  }
642 
643 
644 
645 
646  /* === References : special treatment on element access === */
647 
648  template<typename X>
649  inline X&
651  {
652  return Variant<DataValues>::get<X>();
653  }
654 
655  template<typename X>
656  inline X const&
657  DataCap::get() const
658  {
659  return Variant<DataValues>::get<X>();
660  }
661 
675  template<>
676  inline Rec&
678  {
679  Rec* rec = maybeGet<Rec>();
680  if (rec) return *rec;
681 
682  return Variant<DataValues>::get<RecRef>();
683  }
684 
685  template<>
686  inline Rec const&
687  DataCap::get() const
688  {
689  Rec* rec = unConst(this)->maybeGet<Rec>();
690  if (rec) return *rec;
691 
692  return Variant<DataValues>::get<RecRef>();
693  }
694 
702  inline string
704  {
705  Rec* nested = unConst(this)->maybeGet<Rec>();
706  if (!nested)
707  {
708  RecRef* ref = unConst(this)->maybeGet<RecRef>();
709  if (ref and not ref->empty())
710  nested = ref->get();
711  }
712 
713  return nested? nested->getType()
715  }
716 
717  inline bool
719  {
720  return util::BOTTOM_INDICATOR != recordType();
721  }
722 
723 
724 
725 
732  struct Ref
733  : GenNode
734  {
738  explicit
739  Ref(string const& symbolicID)
740  : GenNode(fabricateRefID<Rec> (symbolicID)//note: seeds the type hash with Rec, not RecRef
741  , DataCap(RecRef())) // note: places NIL into the reference part
742  { }
743 
747  Ref(GenNode& oNode)
748  : GenNode(ID(oNode)
749  , DataCap(RecRef(oNode.data.get<Rec>())))
750  { }
751 
752  static const Ref I;
753  static const Ref NO;
754  static const Ref END;
755  static const Ref THIS;
756  static const Ref CHILD;
757  static const Ref ATTRIBS;
758  };
759 
760 
761  // slice down on copy construction...
762  inline GenNode::GenNode(Ref const& r) : idi(r.idi), data(r.data) { }
763  inline GenNode::GenNode(Ref & r) : idi(r.idi), data(r.data) { }
764  inline GenNode::GenNode(Ref && r) : idi(std::move(r.idi)),
765  data(std::move(r.data)) { }
766 
767 
768  /* === Specialisation to add fluent GenNode builder API to Record<GenNode> === */
769 
770  template<>
771  inline GenNode
773  {
774  return GenNode(std::move(record_));
775  }
776 
777  template<>
778  inline GenNode
779  MakeRec::genNode(string const& symbolicID)
780  {
781  return GenNode(symbolicID, std::move(record_));
782  }
783 
784 
785  /* === Extension point to apply a tree-diff === */
786 
791  template<>
793 
794 
795 
796  /* === Specialisation for handling of attributes in Record<GenNode> === */
797 
798  template<>
799  inline bool
800  Rec::isAttribute (GenNode const& attrib)
801  {
802  return attrib.isNamed();
803  }
804 
805  template<>
806  inline bool
807  Rec::isTypeID (GenNode const& attrib)
808  {
809  return attrib.isTypeID();
810  }
811 
812  template<>
813  inline string
814  Rec::extractTypeID (GenNode const& v)
815  {
816  return isTypeID(v)? v.data.get<string>()
817  : Rec::TYPE_NIL;
818  }
819 
820  template<>
821  inline string
822  Rec::extractKey (GenNode const& v)
823  {
824  return isAttribute(v)? v.idi.getSym()
825  : "";
826  }
827 
828  template<>
829  inline GenNode const&
830  Rec::extractVal (GenNode const& v)
831  {
832  return v;
833  }
834 
835  template<>
836  inline string
837  Rec::renderAttribute (GenNode const& a)
838  {
839  return a.idi.getSym() +" = "+ string(a.data);
840  }
841 
842  template<>
843  template<typename X>
844  inline GenNode
845  Rec::buildAttribute (string const& key, X&& payload)
846  {
847  return GenNode(key, std::forward<X>(payload));
848  }
849 
850 
851 
852 }// namespace lib::diff
853 
854 namespace variant {
855  using diff::Rec;
856 
861  template<typename TYPES>
862  struct CanBuildFrom<diff::MakeRec, Node<Rec, TYPES>>
863  : std::true_type
864  {
865  using Type = Rec;
866  };
867 
868 }} // namespace lib::variant
869 #endif /*LIB_DIFF_GEN_NODE_H*/
static GenNode::ID fabricateRefID(string const &symbolicID)
Definition: gen-node.hpp:445
static string extractTypeID(VAL const &v)
bool matches(RecRef const &ref) const
Definition: gen-node.hpp:349
static const Ref I
symbolic ID ref "_I_"
Definition: gen-node.hpp:752
bool isTypeID() const
Definition: gen-node.hpp:328
type erased baseclass for building a combined hash and symbolic ID.
Definition: entry-id.hpp:135
GenNode(string const &symbolicID, X &&val)
Definition: gen-node.hpp:253
Rec::Mutator MakeRec
Definition: gen-node.hpp:135
GenNode const & Access
using const reference data access relevant for handling large subtrees
Definition: gen-node.hpp:127
Record< GenNode > Rec
Definition: gen-node.hpp:133
metafunction to detect types able to be wrapped into a GenNode.
Definition: gen-node.hpp:470
iterator begin()
Definition: gen-node.hpp:628
static VAL buildAttribute(string const &key, X &&payload)
std::deque< ScopeIter > scopes_
Definition: gen-node.hpp:556
static string extractKey(VAL const &v)
Constructor for a specially crafted &#39;ref GenNode&#39;.
Definition: gen-node.hpp:732
Locator(GenNode const &n)
Definition: gen-node.hpp:505
bool operator!=(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
bool matches(int64_t number) const
Definition: gen-node.hpp:340
friend ChildDataIter childData(Rec::scopeIter &&scopeIter)
Definition: gen-node.hpp:384
bool isNested() const
determine if payload constitutes a nested scope ("object")
Definition: gen-node.hpp:718
int data
Definition: test-priqueue.c:84
friend ChildDataIter childData(GenNode const &n)
visit the data of nested child elements
Definition: gen-node.hpp:373
static bool isAttribute(VAL const &v)
bool matchTxt(string const &) const
Definition: gen-node.cpp:185
GenNode(ID &&id, DataCap &&d)
Definition: gen-node.hpp:438
bool matches(ID const &id) const
Definition: gen-node.hpp:338
Rec::scopeIter childIter() const
visit children of a nested Record<GenNode>
Definition: gen-node.hpp:201
typename iter_stl::_SeqT< const Storage >::Range scopeIter
Definition: record.hpp:305
bool empty() const
Definition: record.hpp:656
Typesafe union record.
Definition: variant.hpp:223
STL namespace.
bool operator==(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
Supporting equality comparisons...
static const Ref CHILD
symbolic ID ref "_CHILD_"
Definition: gen-node.hpp:756
GenNode(string const &symbolicID, const char *text)
Definition: gen-node.hpp:258
DataCap(DataCap &o)
Definition: gen-node.hpp:166
typename meta::Strip< CON >::TypeReferred::iterator iterator
bool matches(char number) const
Definition: gen-node.hpp:342
GenNode(const char *text)
Definition: gen-node.hpp:262
static string renderAttribute(VAL const &a)
GenNode const & yield() const
Definition: gen-node.hpp:581
Building block for monad-like depth-first expansion of a GenNode.
Definition: gen-node.hpp:552
char Yes_t
helper types to detect the overload resolution chosen by the compiler
Definition: meta/util.hpp:103
bool matches(int number) const
Definition: gen-node.hpp:339
Implementation namespace for support and library code.
scopeIter scope() const
Definition: record.hpp:314
static string buildChildID()
Definition: gen-node.hpp:454
bool isNamed() const
Definition: gen-node.hpp:322
string const & getSym() const
Definition: entry-id.hpp:165
bool matches(string text) const
Definition: gen-node.hpp:344
bool contains(MAP &map, typename MAP::key_type const &key)
shortcut for containment test on a map
Definition: util.hpp:205
bool matchNum(int64_t) const
Definition: gen-node.cpp:129
handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBuff...
Definition: record.hpp:108
Special collection to represent object-like data.
RecordRef< GenNode > RecRef
Definition: gen-node.hpp:134
static const Ref END
symbolic ID ref "_END_"
Definition: gen-node.hpp:754
typename meta::Strip< CON >::TypeReferred::const_iterator const_iterator
bool matchData(DataCap const &) const
Implementation of content equality test, delgating to content.
Definition: gen-node.cpp:85
allow for storage in ordered containers, ordering based on the human-readable ID within the GenNode...
Definition: gen-node.hpp:426
bool matchBool(bool) const
Definition: gen-node.cpp:244
A typesafe union record to carry embedded values of unrelated type.
bool matches(short number) const
Definition: gen-node.hpp:341
Target * get() const noexcept
Definition: record.hpp:673
GenNode const & yield() const
Definition: gen-node.hpp:531
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...
Iterator tool treating pulled data by a custom transformation (function)
Definition: itertools.hpp:756
wrapped record reference.
Definition: record.hpp:611
bool startsWith(string const &str, string const &prefix)
check if string starts with a given prefix
Definition: util.hpp:160
friend string name(GenNode const &node)
Definition: gen-node.hpp:396
bool matches(bool b) const
Definition: gen-node.hpp:347
bool matchRec(RecRef const &) const
Definition: gen-node.cpp:260
static const Ref NO
symbolic ID ref "_NO_"
Definition: gen-node.hpp:753
HashVal getTypeHash()
Definition: genfunc.hpp:168
bool matchTime(time::TimeValue) const
Definition: gen-node.cpp:216
void buildMutator(BufferHandle)
attachment point to receive and apply tree-diff changes.
friend class Mutator
Definition: record.hpp:298
bool contains(X const &elm) const
Definition: gen-node.hpp:635
ID(X *, string const &symbolicID)
Definition: gen-node.hpp:221
Locator expand() const
Definition: gen-node.hpp:609
Lumiera error handling (C++ interface).
bool matches(hash::LuidH h) const
Definition: gen-node.hpp:348
OBJ * unConst(const OBJ *o)
shortcut to save some typing when having to define const and non-const variants of member functions ...
Definition: util.hpp:319
static bool isTypeID(VAL const &v)
Hash implementation based on a lumiera unique object id (LUID) When invoking the default ctor...
bool matches(Rec const &rec) const
Definition: gen-node.hpp:350
bool matches(GenNode const &o) const
Definition: gen-node.hpp:337
static const Ref ATTRIBS
symbolic ID ref "_ATTRIBS_"
Definition: gen-node.hpp:757
Offset measures a distance in time.
Definition: timevalue.hpp:283
string recordType() const
peek into the type field of a nested Record<GenNode>
Definition: gen-node.hpp:703
std::vector< GenNode > Storage
Definition: gen-node.hpp:122
Duration is the internal Lumiera time metric.
Definition: timevalue.hpp:380
const string BOTTOM_INDICATOR
Definition: meta/util.hpp:244
Ref(string const &symbolicID)
create an empty ID stand-in.
Definition: gen-node.hpp:739
Bare symbolic and hash ID used for accounting of asset like entries.
typename Storage::const_iterator ElmIter
Definition: gen-node.hpp:123
static const string TYPE_NIL
Definition: record.hpp:155
A time interval anchored at a specific point in time.
Definition: timevalue.hpp:467
iterator end()
Definition: gen-node.hpp:630
Ref(GenNode &oNode)
build reference to a Record, using the original ID
Definition: gen-node.hpp:747
a family of time value like entities and their relationships.
object-like record of data.
Definition: record.hpp:143
static const Ref THIS
symbolic ID ref "_THIS_"
Definition: gen-node.hpp:755
basic constant internal time value.
Definition: timevalue.hpp:80
string getType() const
Definition: record.hpp:225
bool matchLuid(hash::LuidH) const
Definition: gen-node.cpp:252
GenNode(GenNode &o)
Definition: gen-node.hpp:269
Adapter for building an implementation of the »Lumiera Forward Iterator« concept. ...
ScopeExplorer(GenNode const &n)
Definition: gen-node.hpp:560
LumieraPriQueue r
Definition: test-priqueue.c:82
std::function< UICoord(Literal)> Locator
Locator is a functor to resolve to a topological location in the UI-tree.
generic data element node within a tree
Definition: gen-node.hpp:213
lib::idi::BareEntryID const & ID
Definition: id-scheme.hpp:87
bool matches(time::TimeValue t) const
Definition: gen-node.hpp:346
bool matches(const char *text) const
Definition: gen-node.hpp:345
static Access extractVal(VAL const &v)
bool matchDbl(double) const
Definition: gen-node.cpp:157
ID(GenNode const &node)
Definition: gen-node.hpp:227
bool matches(double number) const
Definition: gen-node.hpp:343