Files CCore/inc/gadget/PtrStepLen.h CCore/src/gadget/PtrStepLen.cpp
PtrStepLen is similar to the PtrLen. It represents a range of objects.
template <class T>
struct PtrStepLen
{
T *ptr;
ulen step;
ulen len;
Three members are used to specify a range: ptr, step and len. ptr is the address of the first range element. len is the number of elements of the range. step is the distance from any range element to the next. I.e. the range consists of the elements { ptr[0] , ptr[step] , ... , ptr[index*step] , ... , ptr[(len-1)*step] }.
// constructors PtrStepLen() noexcept : ptr(0),step(0),len(0) {} PtrStepLen(NothingType) : PtrStepLen() {} PtrStepLen(T *ptr_,ulen step_,ulen len_) : ptr(ptr_),step(step_),len(len_) {} operator PtrStepLen<const T>() const { return {ptr,step,len}; }
Three constructors are provided: two to create a null range and third to create a range with the given ptr, step and len values. You can also cast to the const version. All other methods have direct equivalents and the same behavior as methods of the PtrLen.
Cursor methods:
// cursor ulen operator + () const { return len; } // get length // range is not empty bool operator ! () const { return !len; } // range is empty T & operator * () const { return *ptr; } // first element T * operator -> () const { return ptr; } // pointer to the first element void operator ++ () { ptr+=step; len--; } // advance void operator -- () { ptr-=step; len++; } // back PtrStepLen<T> operator += (ulen delta); // assume delta<=len, advance on delta PtrStepLen<T> takeup(ulen delta); // advance up to delta elements T & take(); // assume len>0, take first element and advance PtrStepLen<T> getFinal() const { return {ptr+len*step,step,0}; }
Methods fit() can be used to check the length of the range:
// fit bool fit(ulen length) const { return length<=len; } bool fit(ulen off,ulen length) const { return off<=len && length<=(len-off) ; }
The first checks is there at least the length elements. The second can be used to check if the subrange with the given off(set) from the begin and length can be selected.
You can select a desired part of the range using parts methods:
// parts PtrStepLen<T> prefix(ulen length) const; // assume fit(length), prefix of the given length PtrStepLen<T> prefix(PtrStepLen<T> suffix) const; // prefix, complementary to the given suffix PtrStepLen<T> suffix(ulen length) const; // assume fit(length), suffix of the given length PtrStepLen<T> part(ulen off,ulen length) const; // assume fit(off,length), inner part with the given off(set) and length PtrStepLen<T> part(ulen off) const; // assume fit(off), suffix with the given off(set) PtrStepLen<T> inner(ulen off,ulen endoff) const; // assume fit(off,endoff), inner part with the given off(set) and offset from the end (endoff)
You can pick an element of the range based on its index:
// index access T & operator [] (ulen index) const; T & at(ulen index) const; // with the index guard T & back(ulen index) const; // reverse order, index 1 means the last element
The last method is required to support range-based for with the PtrStepLen:
// begin()/end() support bool operator != (PtrStepLen<T> end) const { return len!=end.len; } }; /* begin()/end() */ template <class T> PtrStepLen<T> begin(PtrStepLen<T> a) { return a; } template <class T> PtrStepLen<T> end(PtrStepLen<T>) { return Nothing; }