48 #ifndef LIB_PATH_ARRAY_H 49 #define LIB_PATH_ARRAY_H 94 return reinterpret_cast<size_t&
> (p[0]);
104 size_t siz = 1 + size (unConst(
this)->storage_);
105 const char** alloc =
new const char*[siz];
106 std::copy (storage_, storage_+siz, alloc);
107 return reinterpret_cast<PStorage> (alloc);
122 template<
typename...ELMS>
125 : storage_{
new Literal[1 +
sizeof...(ELMS)]}
127 size(storage_) =
sizeof...(ELMS);
128 new(storage_+1)
Literal[
sizeof...(ELMS)] {forward<ELMS>(elms)...};
132 : storage_{r.storage_? r.
newCopy() :
nullptr}
135 Extension (Extension&& rr) noexcept
139 std::swap (storage_, rr.storage_);
142 Extension& operator= (Extension
const& o)
146 std::unique_ptr<Literal[]> cp;
151 storage_ = cp.release();
156 Extension& operator= (Extension&& rr) noexcept
160 std::swap (storage_, rr.storage_);
167 operator bool()
const {
return not empty(); }
168 bool empty()
const {
return not storage_;}
173 return storage_? size(unConst(
this)->storage_)
178 operator[] (
size_t idx)
const 180 REQUIRE (storage_ and idx < size());
181 return storage_[1+idx];
185 indexOf (
Literal const* pos)
const 187 REQUIRE (isValid (pos));
188 return pos - (storage_+1);
193 isValid (
Literal const* pos)
const 197 and pos < storage_ + (1 + size (unConst(
this)->storage_));
201 resizeTo (
size_t cnt)
207 auto target =
new const char* [cnt+1];
208 auto pos = std::copy (storage_, storage_+1+size(), target);
209 for ( ; pos < target+1+cnt; ++pos)
212 storage_ =
reinterpret_cast<PStorage> (target);
215 storage_ =
new Literal [cnt+1];
217 size (storage_) = cnt;
220 if (not storage_)
return;
227 size(storage_) = cnt;
237 using meta::pickInit;
250 template<
size_t chunk_size>
253 static_assert (0 < chunk_size,
"PathArray chunk_size must be nonempty");
255 using CcP =
const char*;
256 using LiteralArray = std::array<Literal, chunk_size>;
270 template<
size_t...prefix,
size_t...rest,
typename...ARGS>
274 : elms_{pickInit<prefix,CcP> (forward<ARGS>(args)...) ...}
275 , tail_{pickArg<rest> (forward<ARGS>(args)...) ...}
286 template<
typename...ARGS>
289 using Prefix =
typename meta::BuildIndexSeq<chunk_size>::Ascending;
294 template<
typename...ARGS>
297 :
PathArray(
typename Split<ARGS...>::Prefix()
298 ,
typename Split<ARGS...>::Rest()
299 ,forward<ARGS> (args)...)
313 return tail_? chunk_size + tail_.size()
314 : findInlineEnd() - elms_.begin();
320 return empty()? 0 : size()-1;
330 operator string()
const;
340 operator[] (
size_t idx)
const 342 Literal* elm = unConst(
this)->getPosition (idx);
345 +
" on PathArray of size "+ util::toString(size())
346 ,error::LUMIERA_ERROR_INDEX_BOUNDS);
359 if (elms_.begin() <= &content and &content < elms_.end())
360 return &content - elms_.begin();
361 if (tail_.isValid (&content))
362 return chunk_size + tail_.indexOf (&content);
364 throw error::Invalid (
"Referred content "+util::toString(&content)
365 +
" is not located within the storage of PathArray " 384 if (pos == src->elms_.end() and src->tail_)
385 pos = &src->tail_[0];
387 if (not src->isValid (pos))
392 ENSURE ( (src->elms_.begin() <= pos and pos < src->elms_.end())
393 or src->tail_.isValid(pos));
403 using const_reference =
Literal const&;
417 isValid (
Literal const* pos)
const 420 and (tail_.isValid(pos)
421 or (elms_.begin() <= pos and pos < elms_.end()
426 firstNonempty ()
const 428 iterator startPos{
this, elms_.begin()};
429 while (startPos && isnil (*startPos))
441 Literal const* lastPos = elms_.begin() + chunk_size-1;
442 Literal const* beforeStart = elms_.begin() - 1;
443 while (lastPos != beforeStart and not *lastPos)
459 if (idx < chunk_size)
460 elm = elms_[idx]? &elms_[idx] :
nullptr;
462 if (idx-chunk_size < tail_.size())
463 elm = &tail_[idx-chunk_size];
465 return const_cast<Literal*
> (elm);
475 if (chunk_size <= idx and size() <= idx)
476 tail_.resizeTo(idx+1 - chunk_size);
477 if (idx < chunk_size)
478 return elms_.begin() + idx;
480 ENSURE (idx-chunk_size < tail_.size());
481 return const_cast<Literal*
> (&tail_[idx-chunk_size]);
489 *
reinterpret_cast<const char**
> (pos) = val;
493 truncateTo (
size_t newSize)
495 if (newSize < chunk_size)
498 Literal* pos = getPosition(newSize);
500 for ( ; pos!=end; ++pos)
501 setContent (pos,
nullptr);
505 if (newSize-chunk_size < tail_.size())
506 tail_.resizeTo (newSize - chunk_size);
520 if (size() == 0)
return;
521 const char* fill = Symbol::EMPTY;
525 for ( ; pos!=end; ++pos)
527 setContent (pos, fill);
529 if (fill==Symbol::EMPTY)
535 pos = getPosition (chunk_size);
536 end = pos + tail_.size();
537 for ( ; pos!=end; ++pos)
539 setContent (pos, fill);
541 if (fill==Symbol::EMPTY)
547 while (idx and fill == *getPosition (--idx))
548 setContent (getPosition(idx),
nullptr);
550 if (idx >= chunk_size-1)
551 tail_.resizeTo (idx+1 - chunk_size);
560 template<
size_t chunk_size>
564 if (this->empty())
return "";
567 size_t expectedLen = this->size() * 10;
568 buff.reserve (expectedLen);
573 size_t len = buff.length();
584 template<
size_t cl,
size_t cr>
588 if (l.size() != r.size())
return false;
594 if (*lp != *rp)
return false;
598 return isnil(lp) and isnil(rp);
601 template<
size_t cl,
size_t cr>
Literal * expandPosition(size_t idx)
Helper template(s) for creating Lumiera Forward Iterators.
PStorage newCopy() const
allocate a copy.
inline string literal This is a marker type to indicate that
bool operator==(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
Supporting equality comparisons...
Literal const * findInlineEnd() const
find effective end of data in the inline array, i.e.
Implementation namespace for support and library code.
Derived specific exceptions within Lumiera's exception hierarchy.
Abstraction for path-like topological coordinates.
Marker types to indicate a literal string and a Symbol.
void normalise()
establish the contract of PathArray
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
friend void iterNext(const PathArray *, const Literal *&pos)
Implementation of Iteration-logic: pull next element.
friend bool checkPoint(const PathArray *src, const Literal *&pos)
Implementation of Iteration-logic: detect iteration end.
PathArray(IndexSeq< prefix... >, IndexSeq< rest... >, ARGS &&...args)
Lumiera error handling (C++ interface).
void setContent(Literal *pos, const char *val)
Literal * getPosition(size_t idx)
Heap-allocated extension storage for an immutable sequence of literal strings.
size_t indexOf(Literal const &content) const
reverse lookup of actual path content
Adapter for building an implementation of the »Lumiera Forward Iterator« concept. ...
Metaprogramming with type sequences based on variadic template parameters.