90 #ifndef LIB_DIFF_RECORD_H 91 #define LIB_DIFF_RECORD_H 112 template<
class BA,
class DEFAULT>
127 template<
typename VAL>
149 template<
typename VAL>
162 static const string TYPE_NIL;
163 static const Symbol TYPE_NIL_SYM;
169 template<
typename A,
typename C>
171 : type_(isnil(typeID)? TYPE_NIL:
string(typeID))
172 , attribs_(std::forward<A> (att))
173 , children_(std::forward<C> (chi))
176 template<
typename A,
typename C>
177 Record(
Symbol typeID, std::initializer_list<A>
const&& att
178 , std::initializer_list<C>
const&& chi)
179 : type_(isnil(typeID)? TYPE_NIL:
string(typeID))
184 template<
typename SEQ>
189 auto p = std::begin(con);
190 auto e = std::end(con);
191 for ( ; p!=e && isAttribute(*p); ++p)
193 type_ = extractTypeID(*p);
195 attribs_.push_back (*p);
197 children_.push_back (*p);
200 Record (std::initializer_list<VAL>
const&& ili)
208 operator std::string()
const;
214 return attribs_.size();
220 return children_.size();
226 return attribs_.empty()
227 and children_.empty();
238 hasAttribute (
string key)
const 240 return attribs_.end() != findKey(key);
244 contains (VAL
const& val)
const 246 return util::contains (children_, val);
250 get (
string key)
const 252 ElmIter found = findKey (key);
253 if (attribs_.end() == found)
256 return extractVal (*found);
260 child (
size_t idx)
const 262 if (children_.size() <= idx)
264 +
" out of bounds [0.."+util::toString(children_.size())
266 ,error::LUMIERA_ERROR_INDEX_BOUNDS);
267 return children_[idx];
313 using scopeIter =
typename iter_stl::_SeqT<const Storage>::Range;
321 scopeIter attribs()
const {
return iter_stl::eachElm(attribs_); }
322 scopeIter scope()
const {
return iter_stl::eachElm(children_); }
345 static const ElmIter END;
346 if (pos != END && pos == src->attribs_.end() && !src->children_.empty())
348 pos = src->children_.begin();
352 if (pos != END && (pos != src->children_.end()))
362 static bool isAttribute (VAL
const& v);
363 static bool isTypeID (VAL
const& v);
364 static string extractTypeID (VAL
const& v);
365 static string renderAttribute (VAL
const& a);
366 static string extractKey (VAL
const& v);
367 static Access extractVal (VAL
const& v);
369 static VAL buildAttribute (
string const& key, X&& payload);
373 findKey (
string key)
const 375 return std::find_if (attribs_.begin()
379 return key == extractKey(elm);
387 return r1.type_ == r2.type_
388 and r1.attribs_ == r2.attribs_
389 and r1.children_ == r2.children_;
395 return not (r1 == r2);
399 template<
typename VAL>
402 template<
typename VAL>
407 template<
typename VAL>
421 Mutator (Rec
const& startingPoint)
422 : record_(startingPoint)
427 : record_(std::move (startingPoint))
436 swap (Rec& existingInstance) noexcept
438 std::swap (existingInstance, record_);
444 return record_.empty();
451 setType (
string const& newTypeID)
453 record_.type_ = newTypeID;
457 type (
string const& typeID)
465 set (
string const& key, X&& content)
467 VAL attribute(Rec::buildAttribute (key, std::forward<X>(content)));
468 return set (std::move (attribute));
472 set (VAL&& attribute)
474 string key = Rec::extractKey(attribute);
476 throw error::Invalid (
"Attempt to set an attribute with empty key");
478 Rec::Storage& as =record_.attribs_;
479 auto found = std::find_if (as.begin(),as.end()
482 return key == extractKey(elm);
484 if (as.end() == found)
485 as.push_back (std::forward<VAL> (attribute));
487 (*found) = (std::forward<VAL> (attribute));
492 appendAttrib (VAL
const& newAttrib)
494 REQUIRE (Rec::isAttribute(newAttrib));
495 record_.attribs_.push_back (newAttrib);
500 appendChild (VAL
const& newChild)
502 record_.children_.push_back (newChild);
507 prependChild (VAL
const& newChild)
509 record_.children_.insert (record_.children_.begin(), newChild);
536 return std::tie (record_.attribs_, record_.children_);
550 throw error::State(
"Record is empty, unable to access (last) element.");
552 if (record_.children_.empty())
553 return record_.attribs_.back();
555 return record_.children_.back();
569 VAL genNode(
string const& symbolicID);
571 template<
typename X,
typename...ARGS>
572 Mutator&& attrib (
string const& key, X&& initialiser, ARGS&& ...args)
574 set (key, std::forward<X>(initialiser));
575 return attrib (std::forward<ARGS>(args)...);
577 Mutator&& attrib () {
return move(*
this); }
580 template<
typename X,
typename...ARGS>
581 Mutator&& scope (X
const& initialiser, ARGS&& ...args)
583 appendChild (VAL(initialiser));
584 return scope (std::forward<ARGS>(args)...);
586 Mutator&& scope () {
return move(*
this); }
600 template<
typename VAL>
619 template<
typename VAL>
653 std::swap(record_, o.record_);
659 operator bool()
const 661 return bool(record_);
676 throw error::Logic(
"attempt to dereference an unbound record reference" 677 ,error::LUMIERA_ERROR_BOTTOM_VALUE);
687 operator string()
const 689 return "Ref->" + (empty()? util::BOTTOM_INDICATOR
697 return r1.record_ == r2.record_;
702 return r1.record_ != r2.record_;
718 using Storage = std::vector<string>;
719 using ElmIter =
typename Storage::const_iterator;
732 size_t pos = v.find(
'=');
733 if (string::npos == pos)
736 return util::trim (v.substr (0,pos));
743 size_t pos = v.find(
'=');
744 if (string::npos == pos)
747 return util::trim (v.substr (pos+1, v.length() - pos));
754 return string::npos != v.find(
'=');
761 return isAttribute(v)
762 &&
"type" == extractKey(v);
769 return extractVal(v);
776 return extractKey(attrib) +
" = " + extractVal(attrib);
784 return string(key +
" = " + extractVal(payload));
794 template<
typename VAL>
801 + (TYPE_NIL==type_?
"" : type_)
802 + (isnil(this->attribs())?
"" :
"| "+join (
transformIterator (this->attribs(), renderAttribute))+
" ")
803 + (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.