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 Francois Berder

Test suite can be found in this application, CircularBufferTest

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?

UserRevisionLine numberNew 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