Some useful stuff

Dependents:   FtEncoder FtControlSet

Buffer.h

Committer:
humlet
Date:
2013-03-28
Revision:
1:bf8fc4455615
Child:
2:8882925900db

File content as of revision 1:bf8fc4455615:

#include<cstdint>


/// a template for a simple buffer class holding at max N elements of type T
/// Can be used as stack, queue or ring buffer
/// There is heap and a stack based implemenation
template<class T, uint32_t N>
class Buffer
{
protected:

    static const T outOfBoundsAccessDefaultReturn=T();
    /// the buffer for the stored elements, initialized in the concrete specializations
    T* elements;
    /// points to the oldest element (if not empty; equal to the latest if only one element stored)
    uint32_t startCsr;
    /// points one element behind the latest
    uint32_t endCsr;
    /// number of elements currently stored in the Buffer
    uint32_t nElements;

    /// private helper that increments revolving cursors
    inline void incrCsr(uint32_t& csr) {
        if(++csr>=N) csr=0;
    }
    /// private helper that decrements revolving cursors
    inline void decrCsr(uint32_t& csr) {
        if(--csr>=N) csr=N-1; // will get quite large on underlow since csr is unsigned
    }

    /// guess what: a constructor! But this class is kind of abtract,
    /// so it has been declared protected to remove it from the public interface
    Buffer():elements(0),startCsr(0),endCsr(0),nElements(0) {};

public:

    /// virtual destructor
    virtual ~Buffer() {};

    /// if used as queue or stack, use this function to insert new element to the buffer
    /// returns true on success and false if full
    inline bool push(const T& element) {
        bool ok = !isFull();
        if(ok) {
            elements[endCsr]=element;
            incrCsr(endCsr);
            ++nElements;
        }
        return ok;
    }

    /// if used as ring buffer, use this function to insert new elements to the buffer
    inline void pushCircular(const T& element) {
        elements[endPos]=element;
        incrCsr(endCsr);
        if(isFull())incrCsr(startCsr);
        ++nElements;
    }

    /// pop the latest element from buffer. Returns a default instance of type T if empty
    inline const T& popLatest() {
        if(isEmpty())return outOfBoundsAccessDefaultReturn;
        decrCsr(endCsr);
        --nElements;
        return elements[endCsr];
    }

    /// pop the oldest element from buffer. Returns a default instance of type T if empty
    inline const T& popOldest() {
        if(isEmpty())return outOfBoundsAccessDefaultReturn;
        T& oldest = elements[startCsr];
        incrCsr(startCsr);
        --nElements;
        return oldest;
    }

    /// returns true if buffer is empty
    inline bool isEmpty() const {
        return nElements==0;
    }

    /// returns true if buffer is full
    inline bool isFull() const {
        return nElements==N;
    }

    /// retuns number of currently stored elements
    inline uint32_t size() const {
        return nElements;
    }

    /// returns maximum number of storable elements
    inline uint32_t maxSize() const {
        return N;
    }

    /// read only access operator: Element with index 0 is the oldest and the one with index size()-1 the latest
    inline const T& operator[](uint32_t idx)const {
        return operator[](idx);
    }

    /// read/write access operator: Element with index 0 is the oldest and the one with index size()-1 the latest
    inline T& operator[](uint32_t idx) {
        if(idx>=nElements())return outOfBoundsAccessDefaultReturn;
        idx+=startCsr;
        if(idx>=N)idx-=N;
        return elements[idx];
    }
};

/// concrete Buffer class template that implements the elements storage as simple C-array
/// this baby can be copied using default implicit operator and copy ctors
template<class T, uint32_t N>
class BufferOnStack : public Buffer<T,N>
{
    T storage[N];
public:
    /// create a Buffe class with storage on stack, static or global.
    BufferOnStack():Buffer<T,N>() {
        Buffer<T,N>::elements=storage;
    }
};

/// concrete Buffer class template that allocates the elements storage on the heap
/// This cannot be copied unless you implement the needed ctor and assignment op
template<class T, uint32_t N>
class BufferOnHeap : public Buffer<T,N>
{
public:
    /// constructor
    BufferOnHeap():Buffer<T,N>() {
        Buffer<T,N>::elements=new T[N];
    }
    /// destructor
    virtual ~BufferOnHeap() {
        delete[] Buffer<T,N>::elements;
    }

protected:
    /// no copy ctor
    BufferOnHeap(BufferOnHeap&) {};
    ///no assignment
    BufferOnHeap& operator=(BufferOnHeap&) {}
};