81 #ifndef LIB_DIFF_RECORD_H 82 #define LIB_DIFF_RECORD_H 103 template<
class BA,
class DEFAULT>
118 template<
typename VAL>
140 template<
typename VAL>
153 static const string TYPE_NIL;
154 static const Symbol TYPE_NIL_SYM;
160 template<
typename A,
typename C>
162 : type_(isnil(typeID)? TYPE_NIL:
string(typeID))
163 , attribs_(std::forward<A> (att))
164 , children_(std::forward<C> (chi))
167 template<
typename A,
typename C>
168 Record(
Symbol typeID, std::initializer_list<A>
const&& att
169 , std::initializer_list<C>
const&& chi)
170 : type_(isnil(typeID)? TYPE_NIL:
string(typeID))
175 template<
typename SEQ>
180 auto p = std::begin(con);
181 auto e = std::end(con);
182 for ( ; p!=e && isAttribute(*p); ++p)
184 type_ = extractTypeID(*p);
186 attribs_.push_back (*p);
188 children_.push_back (*p);
191 Record (std::initializer_list<VAL>
const&& ili)
199 operator std::string()
const;
205 return attribs_.size();
211 return children_.size();
217 return attribs_.empty()
218 and children_.empty();
229 hasAttribute (
string key)
const 231 return attribs_.end() != findKey(key);
235 contains (VAL
const& val)
const 237 return util::contains (children_, val);
241 get (
string key)
const 243 ElmIter found = findKey (key);
244 if (attribs_.end() == found)
247 return extractVal (*found);
251 child (
size_t idx)
const 253 if (children_.size() <= idx)
255 +
" out of bounds [0.."+util::toString(children_.size())
257 ,error::LUMIERA_ERROR_INDEX_BOUNDS);
258 return children_[idx];
304 using scopeIter =
typename iter_stl::_SeqT<const Storage>::Range;
312 scopeIter attribs()
const {
return iter_stl::eachElm(attribs_); }
313 scopeIter scope()
const {
return iter_stl::eachElm(children_); }
336 static const ElmIter END;
337 if (pos != END && pos == src->attribs_.end() && !src->children_.empty())
339 pos = src->children_.begin();
343 if (pos != END && (pos != src->children_.end()))
353 static bool isAttribute (VAL
const& v);
354 static bool isTypeID (VAL
const& v);
355 static string extractTypeID (VAL
const& v);
356 static string renderAttribute (VAL
const& a);
357 static string extractKey (VAL
const& v);
358 static Access extractVal (VAL
const& v);
360 static VAL buildAttribute (
string const& key, X&& payload);
364 findKey (
string key)
const 366 return std::find_if (attribs_.begin()
370 return key == extractKey(elm);
378 return r1.type_ == r2.type_
379 and r1.attribs_ == r2.attribs_
380 and r1.children_ == r2.children_;
386 return not (r1 == r2);
390 template<
typename VAL>
393 template<
typename VAL>
398 template<
typename VAL>
412 Mutator (Rec
const& startingPoint)
413 : record_(startingPoint)
418 : record_(std::move (startingPoint))
427 swap (Rec& existingInstance) noexcept
430 swap (existingInstance, record_);
436 return record_.empty();
443 setType (
string const& newTypeID)
445 record_.type_ = newTypeID;
449 type (
string const& typeID)
457 set (
string const& key, X&& content)
459 VAL attribute(Rec::buildAttribute (key, std::forward<X>(content)));
460 return set (std::move (attribute));
464 set (VAL&& attribute)
466 string key = Rec::extractKey(attribute);
468 throw error::Invalid (
"Attempt to set an attribute with empty key");
470 Rec::Storage& as =record_.attribs_;
471 auto found = std::find_if (as.begin(),as.end()
474 return key == extractKey(elm);
476 if (as.end() == found)
477 as.push_back (std::forward<VAL> (attribute));
479 (*found) = (std::forward<VAL> (attribute));
484 appendAttrib (VAL
const& newAttrib)
486 REQUIRE (Rec::isAttribute(newAttrib));
487 record_.attribs_.push_back (newAttrib);
492 appendChild (VAL
const& newChild)
494 record_.children_.push_back (newChild);
499 prependChild (VAL
const& newChild)
501 record_.children_.insert (record_.children_.begin(), newChild);
528 return std::tie (record_.attribs_, record_.children_);
542 throw error::State(
"Record is empty, unable to access (last) element.");
544 if (record_.children_.empty())
545 return record_.attribs_.back();
547 return record_.children_.back();
561 VAL genNode(
string const& symbolicID);
563 template<
typename X,
typename...ARGS>
564 Mutator&& attrib (
string const& key, X&& initialiser, ARGS&& ...args)
566 set (key, std::forward<X>(initialiser));
567 return attrib (std::forward<ARGS>(args)...);
569 Mutator&& attrib () {
return move(*
this); }
572 template<
typename X,
typename...ARGS>
573 Mutator&& scope (X
const& initialiser, ARGS&& ...args)
575 appendChild (VAL(initialiser));
576 return scope (std::forward<ARGS>(args)...);
578 Mutator&& scope () {
return move(*
this); }
592 template<
typename VAL>
611 template<
typename VAL>
645 std::swap (record_, o.record_);
651 operator bool()
const 653 return bool(record_);
668 throw error::Logic(
"attempt to dereference an unbound record reference" 669 ,error::LUMIERA_ERROR_BOTTOM_VALUE);
679 operator string()
const 681 return "Ref->" + (empty()? util::BOTTOM_INDICATOR
689 return r1.record_ == r2.record_;
694 return r1.record_ != r2.record_;
710 using Storage = std::vector<string>;
711 using ElmIter =
typename Storage::const_iterator;
724 size_t pos = v.find(
'=');
725 if (string::npos == pos)
728 return util::trim (v.substr (0,pos));
735 size_t pos = v.find(
'=');
736 if (string::npos == pos)
739 return util::trim (v.substr (pos+1, v.length() - pos));
746 return string::npos != v.find(
'=');
753 return isAttribute(v)
754 &&
"type" == extractKey(v);
761 return extractVal(v);
768 return extractKey(attrib) +
" = " + extractVal(attrib);
776 return string(key +
" = " + extractVal(payload));
786 template<
typename VAL>
793 + (TYPE_NIL==type_?
"" : type_)
794 + (isnil(this->attribs())?
"" :
"| "+join (
transformIterator (this->attribs(), renderAttribute))+
" ")
795 + (isnil(this->scope())?
"" :
"|{"+join (this->scope())+
"}")
type erased baseclass for building a combined hash and symbolic ID.
friend void iterNext(const Record *, ElmIter &pos)
Implementation of Iteration-logic: pull next element.
Helper template(s) for creating Lumiera Forward Iterators.
Types marked with this mix-in may be moved but not copied.
Record< VAL >::Mutator & mutateInPlace(Record< VAL > &record_to_mutate)
open an existing record for modification in-place.
friend bool checkPoint(const Record *src, ElmIter &pos)
Implementation of Iteration-logic: detect iteration end.
iterator begin() const
default iteration exposes all data within this "object", starting with the attributes ...
Implementation namespace for support and library code.
Record(Mutator const &mut)
copy-initialise (or convert) from the given Mutator instance.
Derived specific exceptions within Lumiera's exception hierarchy.
Token or Atom with distinct identity.
Mix-Ins to allow or prohibit various degrees of copying and cloning.
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBu...
string Access
data access by value copy
RecordRef(Target &o) noexcept
create a reference bound to the given target; can not be rebound
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
wrapped record reference.
Lumiera error handling (C++ interface).
RecordRef() noexcept
by default create an invalid ("bottom") reference
Preconfigured adapters for some STL container standard usage situations.
auto transformIterator(IT const &src, FUN processingFunc)
Build a TransformIter: convenience free function shortcut, picking up the involved types automaticall...
object-like record of data.
Adapter for building an implementation of the »Lumiera Forward Iterator« concept. ...
VAL const & accessLast()
get the tail element.