Small library for using circular buffers (forked from François Berder's implementation in order to add methods and fix problems)
Dependents: CircularBufferTest XBeeApi
Fork of CircularBuffer by
Test suite can be found in this application, CircularBufferTest
CircularBuffer.h@8:d318a6948091, 2014-01-30 (annotated)
- Committer:
- johnb
- Date:
- Thu Jan 30 20:15:33 2014 +0000
- Revision:
- 8:d318a6948091
- Parent:
- 7:e2d532183250
Add [] operator
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
feb11 | 0:5d058c917599 | 1 | #ifndef CIRCULAR_BUFFER_H |
feb11 | 0:5d058c917599 | 2 | #define CIRCULAR_BUFFER_H |
feb11 | 0:5d058c917599 | 3 | |
johnb | 5:abe8909f9603 | 4 | #include <cstddef> |
johnb | 5:abe8909f9603 | 5 | #include <stdint.h> |
johnb | 5:abe8909f9603 | 6 | |
feb11 | 4:e15dee1d59ee | 7 | /** This class implements a static circular buffer. |
johnb | 5:abe8909f9603 | 8 | |
johnb | 5:abe8909f9603 | 9 | CirularBuffer class originally by François Berder ( see http://mbed.org/users/feb11/code/CircularBuffer/ ) |
johnb | 5:abe8909f9603 | 10 | Additions by John Bailey ( http://mbed.org/users/johnb/ ) |
feb11 | 4:e15dee1d59ee | 11 | */ |
feb11 | 0:5d058c917599 | 12 | template<size_t T> |
feb11 | 0:5d058c917599 | 13 | class CircularBuffer |
feb11 | 0:5d058c917599 | 14 | { |
feb11 | 0:5d058c917599 | 15 | public : |
johnb | 5:abe8909f9603 | 16 | |
feb11 | 4:e15dee1d59ee | 17 | /** Default constructor |
feb11 | 4:e15dee1d59ee | 18 | */ |
feb11 | 0:5d058c917599 | 19 | CircularBuffer(); |
feb11 | 0:5d058c917599 | 20 | |
johnb | 5:abe8909f9603 | 21 | /** Reads data from buffer (data is removed from the buffer as |
johnb | 5:abe8909f9603 | 22 | opposed to the peek method which allows inspection of the |
johnb | 5:abe8909f9603 | 23 | contents without modifying the buffer) |
feb11 | 4:e15dee1d59ee | 24 | |
feb11 | 4:e15dee1d59ee | 25 | \param data output buffer |
feb11 | 4:e15dee1d59ee | 26 | \param length Maximum number of bytes to read |
feb11 | 4:e15dee1d59ee | 27 | \return Number of bytes read |
feb11 | 4:e15dee1d59ee | 28 | |
feb11 | 4:e15dee1d59ee | 29 | \note The return value cannot exceed max(length,capacity) |
feb11 | 4:e15dee1d59ee | 30 | */ |
feb11 | 2:6f3630f5fa06 | 31 | uint32_t read(uint8_t *data, uint32_t length); |
johnb | 5:abe8909f9603 | 32 | |
johnb | 5:abe8909f9603 | 33 | /** Reads data from buffer leaving the data in the buffer |
johnb | 5:abe8909f9603 | 34 | (as opposed to the read method which removed the returned |
johnb | 5:abe8909f9603 | 35 | data from the buffer) |
johnb | 5:abe8909f9603 | 36 | |
johnb | 5:abe8909f9603 | 37 | \param data output buffer |
johnb | 5:abe8909f9603 | 38 | \param length Maximum number of bytes to read |
johnb | 5:abe8909f9603 | 39 | \return Number of bytes read |
johnb | 5:abe8909f9603 | 40 | |
johnb | 5:abe8909f9603 | 41 | \note The return value cannot exceed max(length,capacity) |
johnb | 5:abe8909f9603 | 42 | */ |
johnb | 5:abe8909f9603 | 43 | uint32_t peek(uint8_t *data, uint32_t length) const; |
feb11 | 4:e15dee1d59ee | 44 | |
feb11 | 4:e15dee1d59ee | 45 | /** Writes data in buffer |
feb11 | 4:e15dee1d59ee | 46 | |
feb11 | 4:e15dee1d59ee | 47 | \param data input buffer |
feb11 | 4:e15dee1d59ee | 48 | \param length Maximum number of bytes to write |
feb11 | 4:e15dee1d59ee | 49 | \return Number of bytes wrote |
feb11 | 4:e15dee1d59ee | 50 | |
feb11 | 4:e15dee1d59ee | 51 | \note The return value cannot exceed max(length,capacity) |
feb11 | 4:e15dee1d59ee | 52 | */ |
feb11 | 2:6f3630f5fa06 | 53 | uint32_t write(uint8_t *data, uint32_t length); |
feb11 | 3:9a45d6675e65 | 54 | |
feb11 | 4:e15dee1d59ee | 55 | /** Returns the total capacity of this buffer |
feb11 | 4:e15dee1d59ee | 56 | \return Capacity of buffer |
feb11 | 4:e15dee1d59ee | 57 | */ |
feb11 | 2:6f3630f5fa06 | 58 | uint32_t getCapacity() const; |
feb11 | 4:e15dee1d59ee | 59 | |
feb11 | 4:e15dee1d59ee | 60 | /** Returns the number of bytes available in the buffer |
feb11 | 4:e15dee1d59ee | 61 | \return Number of bytes available in the buffer |
feb11 | 4:e15dee1d59ee | 62 | */ |
feb11 | 3:9a45d6675e65 | 63 | uint32_t getSize() const; |
feb11 | 4:e15dee1d59ee | 64 | |
feb11 | 4:e15dee1d59ee | 65 | /** Checks if this buffer is empty |
feb11 | 4:e15dee1d59ee | 66 | \return True if the buffer is empty, false otherwise |
feb11 | 4:e15dee1d59ee | 67 | */ |
feb11 | 3:9a45d6675e65 | 68 | bool isEmpty() const; |
feb11 | 4:e15dee1d59ee | 69 | |
feb11 | 4:e15dee1d59ee | 70 | /** Checks if this buffer is full |
feb11 | 4:e15dee1d59ee | 71 | \return True if the buffer is full, false otherwise |
feb11 | 4:e15dee1d59ee | 72 | */ |
feb11 | 3:9a45d6675e65 | 73 | bool isFull() const; |
feb11 | 2:6f3630f5fa06 | 74 | |
johnb | 7:e2d532183250 | 75 | /* Remove the specified number of bytes from the front of the buffer |
johnb | 7:e2d532183250 | 76 | This is more efficient than using read() to access the bytes then |
johnb | 7:e2d532183250 | 77 | junking them. |
johnb | 7:e2d532183250 | 78 | |
johnb | 7:e2d532183250 | 79 | \param length The number of bytes to remove. If the specified |
johnb | 7:e2d532183250 | 80 | number of bytes don't exist in the buffer, the buffer will |
johnb | 7:e2d532183250 | 81 | just be emptied |
johnb | 7:e2d532183250 | 82 | */ |
johnb | 7:e2d532183250 | 83 | void chomp( uint32_t length ); |
johnb | 8:d318a6948091 | 84 | |
johnb | 8:d318a6948091 | 85 | /* Read a single byte from the buffer. The byte is not removed. |
johnb | 8:d318a6948091 | 86 | The called must be responsible for ensuring that p_length < getSize() |
johnb | 8:d318a6948091 | 87 | |
johnb | 8:d318a6948091 | 88 | \param p_length The index of the byte to read, relative to the start |
johnb | 8:d318a6948091 | 89 | of the circulat buffer |
johnb | 8:d318a6948091 | 90 | \returns The byte at the specified position or a garbage byte in the |
johnb | 8:d318a6948091 | 91 | case that the buffer is too short to support the request */ |
johnb | 8:d318a6948091 | 92 | uint8_t operator[]( uint32_t p_length ) const; |
johnb | 7:e2d532183250 | 93 | |
feb11 | 0:5d058c917599 | 94 | private : |
johnb | 5:abe8909f9603 | 95 | |
johnb | 5:abe8909f9603 | 96 | typedef uint16_t CircularBufferIndex_t; |
feb11 | 0:5d058c917599 | 97 | |
johnb | 5:abe8909f9603 | 98 | CircularBufferIndex_t readIndex, writeIndex; |
feb11 | 0:5d058c917599 | 99 | uint8_t buffer[T]; |
feb11 | 0:5d058c917599 | 100 | |
feb11 | 0:5d058c917599 | 101 | }; |
feb11 | 0:5d058c917599 | 102 | |
feb11 | 0:5d058c917599 | 103 | template<size_t T> |
feb11 | 0:5d058c917599 | 104 | CircularBuffer<T>::CircularBuffer(): |
johnb | 6:242d0e9f13d1 | 105 | readIndex(0), |
feb11 | 1:9953890d59e2 | 106 | writeIndex(0) |
feb11 | 0:5d058c917599 | 107 | { |
feb11 | 0:5d058c917599 | 108 | } |
feb11 | 0:5d058c917599 | 109 | |
feb11 | 0:5d058c917599 | 110 | template<size_t T> |
johnb | 7:e2d532183250 | 111 | void CircularBuffer<T>::chomp(uint32_t length) |
johnb | 7:e2d532183250 | 112 | { |
johnb | 7:e2d532183250 | 113 | if( length >= getSize() ) |
johnb | 7:e2d532183250 | 114 | { |
johnb | 7:e2d532183250 | 115 | readIndex = writeIndex; |
johnb | 7:e2d532183250 | 116 | } else { |
johnb | 7:e2d532183250 | 117 | readIndex = (readIndex + length) % T; |
johnb | 7:e2d532183250 | 118 | } |
johnb | 7:e2d532183250 | 119 | } |
johnb | 7:e2d532183250 | 120 | |
johnb | 7:e2d532183250 | 121 | template<size_t T> |
feb11 | 2:6f3630f5fa06 | 122 | uint32_t CircularBuffer<T>::read(uint8_t *data, uint32_t length) |
feb11 | 0:5d058c917599 | 123 | { |
feb11 | 2:6f3630f5fa06 | 124 | uint32_t n = 0; |
feb11 | 3:9a45d6675e65 | 125 | while(n < length && getSize() > 0) |
feb11 | 0:5d058c917599 | 126 | { |
feb11 | 2:6f3630f5fa06 | 127 | if(readIndex == T) |
feb11 | 2:6f3630f5fa06 | 128 | readIndex = 0; |
feb11 | 2:6f3630f5fa06 | 129 | data[n++] = buffer[readIndex++]; |
feb11 | 0:5d058c917599 | 130 | } |
feb11 | 0:5d058c917599 | 131 | |
feb11 | 2:6f3630f5fa06 | 132 | return n; |
feb11 | 0:5d058c917599 | 133 | } |
feb11 | 0:5d058c917599 | 134 | |
feb11 | 0:5d058c917599 | 135 | template<size_t T> |
johnb | 5:abe8909f9603 | 136 | uint32_t CircularBuffer<T>::peek(uint8_t *data, uint32_t length) const |
johnb | 5:abe8909f9603 | 137 | { |
johnb | 5:abe8909f9603 | 138 | uint32_t n = 0; |
johnb | 5:abe8909f9603 | 139 | CircularBufferIndex_t src = readIndex; |
johnb | 7:e2d532183250 | 140 | while((n < length ) && (n < getSize())) |
johnb | 5:abe8909f9603 | 141 | { |
johnb | 5:abe8909f9603 | 142 | if(src == T) { |
johnb | 5:abe8909f9603 | 143 | src = 0; |
johnb | 5:abe8909f9603 | 144 | } |
johnb | 5:abe8909f9603 | 145 | data[n++] = buffer[src++]; |
johnb | 5:abe8909f9603 | 146 | } |
johnb | 5:abe8909f9603 | 147 | |
johnb | 5:abe8909f9603 | 148 | return n; |
johnb | 5:abe8909f9603 | 149 | } |
johnb | 5:abe8909f9603 | 150 | |
johnb | 5:abe8909f9603 | 151 | template<size_t T> |
feb11 | 2:6f3630f5fa06 | 152 | uint32_t CircularBuffer<T>::write(uint8_t *data, uint32_t length) |
feb11 | 0:5d058c917599 | 153 | { |
feb11 | 2:6f3630f5fa06 | 154 | uint32_t n = 0; |
feb11 | 3:9a45d6675e65 | 155 | while(n < length && getSize() < T) |
feb11 | 0:5d058c917599 | 156 | { |
feb11 | 0:5d058c917599 | 157 | if(writeIndex == T) |
feb11 | 0:5d058c917599 | 158 | writeIndex = 0; |
feb11 | 2:6f3630f5fa06 | 159 | buffer[writeIndex++] = data[n++]; |
feb11 | 0:5d058c917599 | 160 | } |
feb11 | 0:5d058c917599 | 161 | |
feb11 | 2:6f3630f5fa06 | 162 | return n; |
feb11 | 2:6f3630f5fa06 | 163 | } |
feb11 | 2:6f3630f5fa06 | 164 | |
feb11 | 2:6f3630f5fa06 | 165 | template<size_t T> |
feb11 | 2:6f3630f5fa06 | 166 | uint32_t CircularBuffer<T>::getCapacity() const |
feb11 | 2:6f3630f5fa06 | 167 | { |
feb11 | 2:6f3630f5fa06 | 168 | return T; |
feb11 | 2:6f3630f5fa06 | 169 | } |
feb11 | 2:6f3630f5fa06 | 170 | |
feb11 | 2:6f3630f5fa06 | 171 | template<size_t T> |
feb11 | 2:6f3630f5fa06 | 172 | uint32_t CircularBuffer<T>::getSize() const |
feb11 | 2:6f3630f5fa06 | 173 | { |
johnb | 6:242d0e9f13d1 | 174 | return ((writeIndex >= readIndex) ? (writeIndex - readIndex) : (T + writeIndex - readIndex)); |
feb11 | 3:9a45d6675e65 | 175 | } |
feb11 | 3:9a45d6675e65 | 176 | |
feb11 | 3:9a45d6675e65 | 177 | template<size_t T> |
feb11 | 3:9a45d6675e65 | 178 | bool CircularBuffer<T>::isEmpty() const |
feb11 | 3:9a45d6675e65 | 179 | { |
feb11 | 3:9a45d6675e65 | 180 | return getSize() == 0; |
feb11 | 3:9a45d6675e65 | 181 | } |
feb11 | 3:9a45d6675e65 | 182 | |
feb11 | 3:9a45d6675e65 | 183 | template<size_t T> |
feb11 | 3:9a45d6675e65 | 184 | bool CircularBuffer<T>::isFull() const |
feb11 | 3:9a45d6675e65 | 185 | { |
feb11 | 3:9a45d6675e65 | 186 | return getSize() == T; |
feb11 | 0:5d058c917599 | 187 | } |
feb11 | 0:5d058c917599 | 188 | |
johnb | 8:d318a6948091 | 189 | template<size_t T> |
johnb | 8:d318a6948091 | 190 | uint8_t CircularBuffer<T>::operator[]( uint32_t p_length ) const |
johnb | 8:d318a6948091 | 191 | { |
johnb | 8:d318a6948091 | 192 | return buffer[(readIndex + p_length) % T]; |
johnb | 8:d318a6948091 | 193 | } |
johnb | 8:d318a6948091 | 194 | |
johnb | 8:d318a6948091 | 195 | |
feb11 | 0:5d058c917599 | 196 | typedef CircularBuffer<32> SmallCircularBuffer; |
feb11 | 0:5d058c917599 | 197 | typedef CircularBuffer<128> MediumCircularBuffer; |
feb11 | 2:6f3630f5fa06 | 198 | typedef CircularBuffer<512> BigCircularBuffer; |
feb11 | 0:5d058c917599 | 199 | |
feb11 | 0:5d058c917599 | 200 | #endif |