C027 updated to work with latest mBed libraries

Dependents:   Cellular_HelloMQTT UBLOXModemDriver UBLOXMQTTDriver

Fork of C027_Support by u-blox

Pipe.h

Committer:
mazgch
Date:
2013-11-19
Revision:
13:e2446fcdc246
Parent:
9:e7a5959ffae1
Child:
21:c4d64830bf02

File content as of revision 13:e2446fcdc246:

#pragma once 

template <class T>
class Pipe
{
private:
    inline int _inc(int i, int n = 1)
    {
        i += n;
        if (i >= _s)
            i -= _s;
        return i;
    }
public:
    Pipe(int n, T* b = NULL)
    {
        _a = b ? NULL : new T[n];
        _r = 0;
        _w = 0;
        _b = b ? b : _a;
        _s = n;
    }    
    virtual ~Pipe(void)
    {
        if (_a) 
            delete [] _a;
    }
    // writing thread
    bool writeable(void) // = not full
    {
        return free() > 0;
    }
    int free(void)      // number of elements that can be added
    {
        int s = _r - _w;
        if (s <= 0)
            s += _s;
        return s - 1;
    }
    T putc(T c)
    {
        int i = _w;
        int j = i;
        i = _inc(i);
        while (i == _r) // = !writeable() 
            /*wait for space*/;
        _b[j] = c;
        _w = i; 
        return c;
    }
    int put(const T* p, int n, bool t = false)
    {
        int c = n;
        while (c)
        {
            int f;
            for (;;) // wait for space
            {
                f = free();
                if (f)  break;        // data avail
                if (!t) return n - c; // no more space and not blocking
            }
            // check free space
            if (c < f) f = c;
            int w = _w;
            int m = _s - w; 
            // check wrap
            if (f > m) f = m;
            memcpy(&_b[w], p, f);
            _w = _inc(w, f);
            c -= f;
            p += f;
        }
        return n - c;
    }
    // reading thread 
    // --------------------------------------------------------
    //! check if there are any values available
    bool readable(void) // = not empty
    {
        return (_r != _w);
    }
    //! get the number of values avialable in the buffer 
    virtual int size(void)
    {
        int s = _w - _r;
        if (s < 0)
            s += _s;
        return s;
    }
    //! get a value from buffer (this function will block if no values available)
    T getc(void)
    {
        int r = _r;
        while (r == _w) // = !readable()
            /*wait for data*/;
        T t = _b[r];
        _r = _inc(r);
        return t;
    }
    //! get values from buffer
    virtual int get(T* p, int n, bool t = false)
    {
        int c = n;
        while (c)
        {
            int f;
            for (;;) // wait for data
            {
                f = size();
                if (f)  break;        // free space
                if (!t) return n - c; // no space and not blocking
            }
            // check available data
            if (c < f) f = c;
            int r = _r;
            int m = _s - r; 
            // check wrap
            if (f > m) f = m;
            memcpy(p, &_b[r], f);
            _r = _inc(r, f);
            c -= f;
            p += f;
        }
        return n - c;
    }
    
    // the following functions are useful if you like to inspect or parse the buffer
    
    //! reset the parsing index and return the number of available elments 
    virtual int start(void) 
    {
        _o = _r; 
        return size(); 
    }
    //! get the next element and increment 
    virtual T next(void)
    {
        int o = _o;
        T t = _b[o]; 
        _o = _inc(o); 
        return t; 
    }
    //! commit the index 
    virtual void done(void) 
    {
        _r = _o; 
    } 
    
private:
    T*            _b; //!< buffer
    T*            _a; //!< allocated buffer
    int           _s; //!< size of buffer (s - 1) elements can be stored
    volatile int  _w; //!< write index 
    volatile int  _r; //!< read index 
    int           _o; //!< offest index used by parsing functions  
};