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  explicit
228  ID (GenNode const& node)
229  : ID(node.idi)
230  { }
231 
232  // standard copy operations acceptable
233 
234  operator string() const
235  {
236  return "ID(\""+getSym()+"\")";
237  }
238  };
239 
240 
241  //------GenNode Data fields---
242 
245 
246 
247  template<typename X>
248  GenNode(X&& val)
249  : idi(&val, buildChildID<X>())
250  , data(std::forward<X>(val))
251  { }
252 
253  template<typename X>
254  GenNode(string const& symbolicID, X&& val)
255  : idi(&val, symbolicID)
256  , data(std::forward<X>(val))
257  { }
258 
259  GenNode(string const& symbolicID, const char* text)
260  : GenNode(symbolicID, string(text))
261  { }
262 
263  GenNode(const char* text)
264  : GenNode(string(text))
265  { }
266 
268  GenNode(GenNode const&) =default;
269  GenNode(GenNode&&) =default;
270  GenNode(GenNode& o) : GenNode((GenNode const&)o) { }
271  GenNode(Ref const& r);
272  GenNode(Ref & r);
273  GenNode(Ref && r);
274 
291  GenNode&
292  operator= (GenNode const& o)
293  {
294  if (&o != this)
295  {
296  data = o.data;
297  idi = o.idi;
298  }
299  return *this;
300  }
301 
302  GenNode&
303  operator= (GenNode&& o)
304  {
305  ASSERT (&o != this);
306  data = std::forward<DataCap>(o.data);
307  idi = std::forward<ID>(o.idi);
308  return *this;
309  }
310 
311  //note: NOT defining a swap operation, because swapping inline storage is pointless!
312 
313 
314 
315 
317  operator string() const
318  {
319  return "GenNode-"+string(idi)+"-"+string(data);
320  }
321 
322  bool
323  isNamed() const
324  {
325  return not util::startsWith (idi.getSym(), "_CHILD_");
326  }
327 
328  bool
329  isTypeID() const
330  {
331  return "type" == idi.getSym();
332  }
333 
334  template<typename X>
335  bool contains (X const& elm) const;
336 
337 
338  bool matches (GenNode const& o) const { return this->matches(o.idi); }
339  bool matches (ID const& id) const { return idi == id; }
340  bool matches (int number) const { return data.matchNum(number);}
341  bool matches (int64_t number) const { return data.matchNum(number);}
342  bool matches (short number) const { return data.matchNum(number);}
343  bool matches (char number) const { return data.matchNum(number);}
344  bool matches (double number) const { return data.matchDbl(number);}
345  bool matches (string text) const { return data.matchTxt(text);}
346  bool matches (const char* text) const { return data.matchTxt(text);}
347  bool matches (time::TimeValue t) const { return data.matchTime(t); }
348  bool matches (bool b) const { return data.matchBool(b); }
349  bool matches (hash::LuidH h) const { return data.matchLuid(h); }
350  bool matches (RecRef const& ref) const { return data.matchRec(ref); }
351  bool matches (Rec const& rec) const { return data.matchRec(rec); }
352 
353  class ScopeExplorer;
354 
355  struct ScopeExplorerIterator;
357 
358  iterator begin() ;
359  iterator begin() const;
360  iterator end() ;
361  iterator end() const;
362 
363 
365 
373  friend ChildDataIter
374  childData (GenNode const& n)
375  {
376  return ChildDataIter{ n.data.childIter()
377  , [](GenNode const& child) ->DataCap const&
378  {
379  return child.data;
380  }
381  };
382  }
383 
384  friend ChildDataIter
385  childData (Rec::scopeIter&& scopeIter)
386  {
387  return ChildDataIter{ std::forward<Rec::scopeIter>(scopeIter)
388  , [](GenNode const& child) ->DataCap const&
389  {
390  return child.data;
391  }
392  };
393  }
394 
395 
396  friend string
397  name (GenNode const& node)
398  {
399  return node.idi.getSym();
400  }
401 
402  friend bool
403  operator== (GenNode const& n1, GenNode const& n2)
404  {
405  return n1.idi == n2.idi
406  && n1.data.matchData(n2.data);
407  }
408 
409  friend bool
410  operator!= (GenNode const& n1, GenNode const& n2)
411  {
412  return not (n1 == n2);
413  }
414 
428  {
429  bool
430  operator() (GenNode const& left, GenNode const& right) const
431  {
432  return left.idi.getSym() < right.idi.getSym();
433  }
434  };
435 
436 
437  protected:
439  GenNode (ID&& id, DataCap&& d)
440  : idi(std::move(id))
441  , data(std::move(d))
442  { }
443 
444  template<typename X>
445  static GenNode::ID
446  fabricateRefID (string const& symbolicID)
447  {
448  X* typeID(0);
449  return ID(typeID, symbolicID);
450  }
451 
452  private:
453  template<typename X>
454  static string
456  {
457  return "_CHILD_" + idi::generateSymbolicID<X>();
458  }
459  };
460 
461 
462 
470  template<typename ELM>
472  {
475 
476  template<class X>
477  static Yes check(typename variant::CanBuildFrom<X, DataValues>::Type*);
478  template<class X>
479  static No check(...);
480 
481  public:
482  static const bool value = (sizeof(Yes)==sizeof(check<ELM>(0)));
483  };
484 
485 
486 
487 
488  /* === iteration / recursive expansion === */
489 
490 
498  {
499  const GenNode* node_;
501 
503  : node_(nullptr)
504  { }
505 
506  Locator(GenNode const& n)
507  : node_(&n)
508  { }
509 
510  Locator(Rec const& r)
511  : node_(nullptr)
512  , scope_(r.begin())
513  { }
514 
515  const GenNode *
516  get() const
517  {
518  return node_? node_
519  : scope_? scope_.operator->()
520  : nullptr;
521  }
522 
523  /* === Iteration control API for IterStateWrapper == */
524 
525  bool
526  checkPoint() const
527  {
528  return this->get();
529  }
530 
531  GenNode const&
532  yield() const
533  {
534  return *get();
535  }
536 
537  void
539  {
540  if (node_)
541  node_ = nullptr;
542  else
543  ++scope_;
544  }
545  };
546 
547 
554  {
556 
557  std::deque<ScopeIter> scopes_;
558 
559  public:
562  {
563  scopes_.emplace_back(n);
564  }
565 
566  size_t
567  depth() const
568  {
569  return scopes_.size();
570  }
571 
572  /* === Iteration control API for IterStateWrapper == */
573 
574  bool
575  checkPoint() const
576  {
577  return not scopes_.empty()
578  and bool(scopes_.back());
579  }
580 
581  GenNode const&
582  yield() const
583  {
584  return *(scopes_.back());
585  }
586 
587  void
589  {
590  ScopeIter& current = scopes_.back();
591  scopes_.emplace_back (current->data.expand());
592  ++current;
593  while (not scopes_.empty() and not scopes_.back())
594  scopes_.pop_back();
595  }
596 
597  friend bool
599  {
600  return not s1.scopes_.empty()
601  && not s2.scopes_.empty()
602  && s1.scopes_.size() == s2.scopes_.size()
603  && s1.yield() == s2.yield();
604  }
605  };
606 
607 
609  inline DataCap::Locator
611  {
612  Rec* val = unConst(this)->maybeGet<Rec>();
613  if (!val)
614  return Locator();
615  else
616  return Locator(*val);
617  }
618 
619 
621  : IterStateWrapper<const GenNode, ScopeExplorer>
622  {
624 
625  size_t level() const { return unConst(this)->stateCore().depth(); }
626  };
627 
628 
629  inline GenNode::iterator GenNode::begin() { return iterator(*this); }
630  inline GenNode::iterator GenNode::begin() const { return iterator(*this); }
631  inline GenNode::iterator GenNode::end() { return iterator(); }
632  inline GenNode::iterator GenNode::end() const { return iterator(); }
633 
634  template<typename X>
635  inline bool
636  GenNode::contains (X const& elm) const
637  {
638  for (auto & n : *this)
639  if (n.matches(elm))
640  return true;
641  return false;
642  }
643 
644 
645 
646 
647  /* === References : special treatment on element access === */
648 
649  template<typename X>
650  inline X&
652  {
653  return Variant<DataValues>::get<X>();
654  }
655 
656  template<typename X>
657  inline X const&
658  DataCap::get() const
659  {
660  return Variant<DataValues>::get<X>();
661  }
662 
676  template<>
677  inline Rec&
679  {
680  Rec* rec = maybeGet<Rec>();
681  if (rec) return *rec;
682 
683  return Variant<DataValues>::get<RecRef>();
684  }
685 
686  template<>
687  inline Rec const&
688  DataCap::get() const
689  {
690  Rec* rec = unConst(this)->maybeGet<Rec>();
691  if (rec) return *rec;
692 
693  return Variant<DataValues>::get<RecRef>();
694  }
695 
703  inline string
705  {
706  Rec* nested = unConst(this)->maybeGet<Rec>();
707  if (!nested)
708  {
709  RecRef* ref = unConst(this)->maybeGet<RecRef>();
710  if (ref and not ref->empty())
711  nested = ref->get();
712  }
713 
714  return nested? nested->getType()
716  }
717 
718  inline bool
720  {
721  return util::BOTTOM_INDICATOR != recordType();
722  }
723 
724 
725 
726 
733  struct Ref
734  : GenNode
735  {
739  explicit
740  Ref(string const& symbolicID)
741  : GenNode(fabricateRefID<Rec> (symbolicID)//note: seeds the type hash with Rec, not RecRef
742  , DataCap(RecRef())) // note: places NIL into the reference part
743  { }
744 
748  Ref(GenNode& oNode)
749  : GenNode(ID(oNode)
750  , DataCap(RecRef(oNode.data.get<Rec>())))
751  { }
752 
753  static const Ref I;
754  static const Ref NO;
755  static const Ref END;
756  static const Ref THIS;
757  static const Ref CHILD;
758  static const Ref ATTRIBS;
759  };
760 
761 
762  // slice down on copy construction...
763  inline GenNode::GenNode(Ref const& r) : idi(r.idi), data(r.data) { }
764  inline GenNode::GenNode(Ref & r) : idi(r.idi), data(r.data) { }
765  inline GenNode::GenNode(Ref && r) : idi(std::move(r.idi)),
766  data(std::move(r.data)) { }
767 
768 
769  /* === Specialisation to add fluent GenNode builder API to Record<GenNode> === */
770 
771  template<>
772  inline GenNode
774  {
775  return GenNode(std::move(record_));
776  }
777 
778  template<>
779  inline GenNode
780  MakeRec::genNode(string const& symbolicID)
781  {
782  return GenNode(symbolicID, std::move(record_));
783  }
784 
785 
786  /* === Extension point to apply a tree-diff === */
787 
792  template<>
794 
795 
796 
797  /* === Specialisation for handling of attributes in Record<GenNode> === */
798 
799  template<>
800  inline bool
801  Rec::isAttribute (GenNode const& attrib)
802  {
803  return attrib.isNamed();
804  }
805 
806  template<>
807  inline bool
808  Rec::isTypeID (GenNode const& attrib)
809  {
810  return attrib.isTypeID();
811  }
812 
813  template<>
814  inline string
815  Rec::extractTypeID (GenNode const& v)
816  {
817  return isTypeID(v)? v.data.get<string>()
818  : Rec::TYPE_NIL;
819  }
820 
821  template<>
822  inline string
823  Rec::extractKey (GenNode const& v)
824  {
825  return isAttribute(v)? v.idi.getSym()
826  : "";
827  }
828 
829  template<>
830  inline GenNode const&
831  Rec::extractVal (GenNode const& v)
832  {
833  return v;
834  }
835 
836  template<>
837  inline string
838  Rec::renderAttribute (GenNode const& a)
839  {
840  return a.idi.getSym() +" = "+ string(a.data);
841  }
842 
843  template<>
844  template<typename X>
845  inline GenNode
846  Rec::buildAttribute (string const& key, X&& payload)
847  {
848  return GenNode(key, std::forward<X>(payload));
849  }
850 
851 
852 
853 }// namespace lib::diff
854 
855 namespace variant {
856  using diff::Rec;
857 
862  template<typename TYPES>
863  struct CanBuildFrom<diff::MakeRec, Node<Rec, TYPES>>
864  : std::true_type
865  {
866  using Type = Rec;
867  };
868 
869 }} // namespace lib::variant
870 #endif /*LIB_DIFF_GEN_NODE_H*/
static GenNode::ID fabricateRefID(string const &symbolicID)
Definition: gen-node.hpp:446
static string extractTypeID(VAL const &v)
bool matches(RecRef const &ref) const
Definition: gen-node.hpp:350
static const Ref I
symbolic ID ref "_I_"
Definition: gen-node.hpp:753
bool isTypeID() const
Definition: gen-node.hpp:329
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:254
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:471
iterator begin()
Definition: gen-node.hpp:629
static VAL buildAttribute(string const &key, X &&payload)
std::deque< ScopeIter > scopes_
Definition: gen-node.hpp:557
static string extractKey(VAL const &v)
Constructor for a specially crafted &#39;ref GenNode&#39;.
Definition: gen-node.hpp:733
Locator(GenNode const &n)
Definition: gen-node.hpp:506
bool operator!=(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
bool matches(int64_t number) const
Definition: gen-node.hpp:341
friend ChildDataIter childData(Rec::scopeIter &&scopeIter)
Definition: gen-node.hpp:385
bool isNested() const
determine if payload constitutes a nested scope ("object")
Definition: gen-node.hpp:719
int data
Definition: test-priqueue.c:84
friend ChildDataIter childData(GenNode const &n)
visit the data of nested child elements
Definition: gen-node.hpp:374
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:439
bool matches(ID const &id) const
Definition: gen-node.hpp:339
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:757
GenNode(string const &symbolicID, const char *text)
Definition: gen-node.hpp:259
DataCap(DataCap &o)
Definition: gen-node.hpp:166
typename meta::Strip< CON >::TypeReferred::iterator iterator
bool matches(char number) const
Definition: gen-node.hpp:343
GenNode(const char *text)
Definition: gen-node.hpp:263
static string renderAttribute(VAL const &a)
GenNode const & yield() const
Definition: gen-node.hpp:582
Building block for monad-like depth-first expansion of a GenNode.
Definition: gen-node.hpp:553
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:340
Implementation namespace for support and library code.
scopeIter scope() const
Definition: record.hpp:314
static string buildChildID()
Definition: gen-node.hpp:455
bool isNamed() const
Definition: gen-node.hpp:323
string const & getSym() const
Definition: entry-id.hpp:165
bool matches(string text) const
Definition: gen-node.hpp:345
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:755
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:427
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:342
Target * get() const noexcept
Definition: record.hpp:673
GenNode const & yield() const
Definition: gen-node.hpp:532
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:760
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:397
bool matches(bool b) const
Definition: gen-node.hpp:348
bool matchRec(RecRef const &) const
Definition: gen-node.cpp:260
static const Ref NO
symbolic ID ref "_NO_"
Definition: gen-node.hpp:754
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:636
ID(X *, string const &symbolicID)
Definition: gen-node.hpp:221
Locator expand() const
Definition: gen-node.hpp:610
Lumiera error handling (C++ interface).
bool matches(hash::LuidH h) const
Definition: gen-node.hpp:349
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:351
bool matches(GenNode const &o) const
Definition: gen-node.hpp:338
static const Ref ATTRIBS
symbolic ID ref "_ATTRIBS_"
Definition: gen-node.hpp:758
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:704
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:740
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:631
Ref(GenNode &oNode)
build reference to a Record, using the original ID
Definition: gen-node.hpp:748
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:756
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:270
Adapter for building an implementation of the »Lumiera Forward Iterator« concept. ...
ScopeExplorer(GenNode const &n)
Definition: gen-node.hpp:561
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:347
bool matches(const char *text) const
Definition: gen-node.hpp:346
static Access extractVal(VAL const &v)
bool matchDbl(double) const
Definition: gen-node.cpp:157
ID(GenNode const &node)
Definition: gen-node.hpp:228
bool matches(double number) const
Definition: gen-node.hpp:344