39 #ifndef LIB_PATH_ARRAY_H 40 #define LIB_PATH_ARRAY_H 85 return reinterpret_cast<size_t&
> (p[0]);
95 size_t siz = 1 + size (unConst(
this)->storage_);
96 const char** alloc =
new const char*[siz];
97 std::copy (storage_, storage_+siz, alloc);
98 return reinterpret_cast<PStorage> (alloc);
113 template<
typename...ELMS>
116 : storage_{
new Literal[1 +
sizeof...(ELMS)]}
118 size(storage_) =
sizeof...(ELMS);
119 new(storage_+1)
Literal[
sizeof...(ELMS)] {forward<ELMS>(elms)...};
123 : storage_{r.storage_? r.
newCopy() :
nullptr}
126 Extension (Extension&& rr) noexcept
130 std::swap (storage_, rr.storage_);
133 Extension& operator= (Extension o)
135 std::swap (storage_, o.storage_);
141 operator bool()
const {
return not empty(); }
142 bool empty()
const {
return not storage_;}
147 return storage_? size(unConst(
this)->storage_)
152 operator[] (
size_t idx)
const 154 REQUIRE (storage_ and idx < size());
155 return storage_[1+idx];
159 indexOf (
Literal const* pos)
const 161 REQUIRE (isValid (pos));
162 return pos - (storage_+1);
167 isValid (
Literal const* pos)
const 171 and pos < storage_ + (1 + size (unConst(
this)->storage_));
175 resizeTo (
size_t cnt)
181 auto target =
new const char* [cnt+1];
182 auto pos = std::copy (storage_, storage_+1+size(), target);
183 for ( ; pos < target+1+cnt; ++pos)
186 storage_ =
reinterpret_cast<PStorage> (target);
189 storage_ =
new Literal [cnt+1];
191 size (storage_) = cnt;
194 if (not storage_)
return;
201 size(storage_) = cnt;
211 using meta::pickInit;
224 template<
size_t chunk_size>
227 static_assert (0 < chunk_size,
"PathArray chunk_size must be nonempty");
229 using CcP =
const char*;
230 using LiteralArray = std::array<Literal, chunk_size>;
244 template<
size_t...prefix,
size_t...rest,
typename...ARGS>
248 : elms_{pickInit<prefix,CcP> (forward<ARGS>(args)...) ...}
249 , tail_{pickArg<rest> (forward<ARGS>(args)...) ...}
260 template<
typename...ARGS>
263 using Prefix =
typename meta::BuildIndexSeq<chunk_size>::Ascending;
268 template<
typename...ARGS>
271 :
PathArray(
typename Split<ARGS...>::Prefix()
272 ,
typename Split<ARGS...>::Rest()
273 ,forward<ARGS> (args)...)
287 return tail_? chunk_size + tail_.size()
288 : findInlineEnd() - elms_.begin();
294 return empty()? 0 : size()-1;
304 operator string()
const;
314 operator[] (
size_t idx)
const 316 Literal* elm = unConst(
this)->getPosition (idx);
319 +
" on PathArray of size "+ util::toString(size())
320 ,error::LUMIERA_ERROR_INDEX_BOUNDS);
333 if (elms_.begin() <= &content and &content < elms_.end())
334 return &content - elms_.begin();
335 if (tail_.isValid (&content))
336 return chunk_size + tail_.indexOf (&content);
338 throw error::Invalid (
"Referred content "+util::toString(&content)
339 +
" is not located within the storage of PathArray " 358 if (pos == src->elms_.end() and src->tail_)
359 pos = &src->tail_[0];
361 if (not src->isValid (pos))
366 ENSURE ( (src->elms_.begin() <= pos and pos < src->elms_.end())
367 or src->tail_.isValid(pos));
377 using const_reference =
Literal const&;
391 isValid (
Literal const* pos)
const 394 and (tail_.isValid(pos)
395 or (elms_.begin() <= pos and pos < elms_.end()
400 firstNonempty ()
const 402 iterator startPos{
this, elms_.begin()};
403 while (startPos && isnil (*startPos))
415 Literal const* lastPos = elms_.begin() + chunk_size-1;
416 Literal const* beforeStart = elms_.begin() - 1;
417 while (lastPos != beforeStart and not *lastPos)
433 if (idx < chunk_size)
434 elm = elms_[idx]? &elms_[idx] :
nullptr;
436 if (idx-chunk_size < tail_.size())
437 elm = &tail_[idx-chunk_size];
439 return const_cast<Literal*
> (elm);
449 if (chunk_size <= idx and size() <= idx)
450 tail_.resizeTo(idx+1 - chunk_size);
451 if (idx < chunk_size)
452 return elms_.begin() + idx;
454 ENSURE (idx-chunk_size < tail_.size());
455 return const_cast<Literal*
> (&tail_[idx-chunk_size]);
463 *
reinterpret_cast<const char**
> (pos) = val;
467 truncateTo (
size_t newSize)
469 if (newSize < chunk_size)
472 Literal* pos = getPosition(newSize);
474 for ( ; pos!=end; ++pos)
475 setContent (pos,
nullptr);
479 if (newSize-chunk_size < tail_.size())
480 tail_.resizeTo (newSize - chunk_size);
494 if (size() == 0)
return;
495 const char* fill = Symbol::EMPTY;
499 for ( ; pos!=end; ++pos)
501 setContent (pos, fill);
503 if (fill==Symbol::EMPTY)
509 pos = getPosition (chunk_size);
510 end = pos + tail_.size();
511 for ( ; pos!=end; ++pos)
513 setContent (pos, fill);
515 if (fill==Symbol::EMPTY)
521 while (idx and fill == *getPosition (--idx))
522 setContent (getPosition(idx),
nullptr);
524 if (idx >= chunk_size-1)
525 tail_.resizeTo (idx+1 - chunk_size);
534 template<
size_t chunk_size>
538 if (this->empty())
return "";
541 size_t expectedLen = this->size() * 10;
542 buff.reserve (expectedLen);
547 size_t len = buff.length();
558 template<
size_t cl,
size_t cr>
562 if (l.size() != r.size())
return false;
568 if (*lp != *rp)
return false;
572 return isnil(lp) and isnil(rp);
575 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.