PtrLenReverse

Files CCore/inc/gadget/PtrLenReverse.h CCore/src/gadget/PtrLenReverse.cpp

PtrLenReverse

PtrLenReverse represents a range in the reverse order. It have a bunch of methods to work with a range in its reverse representation. They are similar to PtrLen methods.


template <class T>
struct PtrLenReverse
 {
  T *ptr;
  ulen len;

ptr points to the past-the-last element of the range.

len is the range length.

So the range itself is (ptr-len,len).

A reverse range can be constructed from the base pointer and the length using a constructor. But it's better to use the RangeReverse() and RangeReverse_const() functions.


  // constructors
  
  PtrLenReverse() noexcept : ptr(0),len(0) {}
  
  PtrLenReverse(NothingType) : ptr(0),len(0) {}
  
  PtrLenReverse(T *ptr_,ulen len_) : ptr(ptr_+len_),len(len_) {}

  operator PtrLenReverse<const T>() const;

ptr_ is the base pointer of the range.

You can cast to the const version.

The method reverse() creates the reverse range (i.e. the usual PtrLen object).


  // reverse

  PtrLen<T> reverse() const { return {ptr-len,len}; }

The set of 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[-1]; } // first element
  
  T * operator -> () const { return ptr-1; } // pointer to the first element
  
  void operator ++ () { ptr--; len--; } // advance
  
  void operator -- () { ptr++; len++; } // back
  
  PtrLenReverse<T> operator += (ulen delta); // advance on delta
   
  PtrLenReverse<T> takeup(ulen delta); // advance up to delta elements
  
  T & take(); // take first element and advance

  PtrLenReverse<T> getFinal() const;
  

"First element" here is the last element of the range.

operator += advances on the given number of elements and returns the reverse range of these elements. You must be sure the number does not exceed the range length.

takeup() is similar, but it checks the range length and advances up to the given number of elements.

getFinal() returns the "final" (past the last) cursor over the range.

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) and length can be selected.

You can select a desired part of the range using parts methods:


  // parts
  
  static PtrLenReverse<T> MakeFrom(T *ptr,ulen len);
  
  PtrLenReverse<T> prefix(ulen length) const; // prefix of the given length
  
  PtrLenReverse<T> prefix(PtrLenReverse<T> suffix) const; // prefix, complementary to the given suffix
  
  PtrLenReverse<T> suffix(ulen length) const; // suffix of the given length
  
  PtrLenReverse<T> part(ulen off,ulen length) const; // inner part with the given off(set) and length
  
  PtrLenReverse<T> part(ulen off) const; // suffix with the given off(set)
  
  PtrLenReverse<T> inner(ulen off,ulen endoff) const; // inner part with the given off(set) and offset from the end (endoff)
   

Parts are selected using the reverse order. I.e. "prefix" is, in fact, the last part of the range.

MakeFrom() creates a reverse range from the past-the-last pointer and the length.

You can pick an element of the range based on its index:


  // index access
  
  T & operator [] (ulen index) const;
   
  T & at(ulen index) const;
  
  T & back(ulen index) const; // 1 is the last
   

Again, the reverse order is used to arrange elements.

The last method is required to support range-based for with the PtrLenReverse:


  // begin()/end() support
  
  bool operator != (PtrLenReverse<T> end) const { return len!=end.len; }
 };

RangeReverse() and RangeReverse_const()

RangeReverse() and RangeReverse_const() is a family of Creator functions for the reverse range creation.


template <class T> 
PtrLenReverse<T> RangeReverse(PtrLenReverse<T> a);
 
template <class T> 
PtrLenReverse<T> RangeReverse(PtrLen<T> a);
 
template <class T,ulen Len> 
PtrLenReverse<T> RangeReverse(T (&buf)[Len]);
 
template <class T> 
PtrLenReverse<T> RangeReverse(T *ptr,ulen len);
 
template <class T> 
PtrLenReverse<T> RangeReverse(T *ptr,T *lim);

And the correspondent const-variants.

 
template <class T> 
PtrLenReverse<const T> RangeReverse_const(PtrLenReverse<T> a);
 
template <class T> 
PtrLenReverse<const T> RangeReverse_const(PtrLen<T> a);
 
template <class T,ulen Len> 
PtrLenReverse<const T> RangeReverse_const(T (&buf)[Len]);
 
template <class T> 
PtrLenReverse<const T> RangeReverse_const(T *ptr,ulen len);
 
template <class T> 
PtrLenReverse<const T> RangeReverse_const(T *ptr,T *lim);

Following generic functions can be used with objects of types with the Range Access Interface:


template <class S>
auto RangeReverse(S &&src);
 
template <class S>
auto RangeReverse_const(const S &src);