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:
Sat Jan 18 22:32:30 2014 +0000
Revision:
7:e2d532183250
Parent:
6:242d0e9f13d1
Child:
8:d318a6948091
Fix to peek() not handling the buffer length correctly; Add "chomp" method

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 7:e2d532183250 84
feb11 0:5d058c917599 85 private :
johnb 5:abe8909f9603 86
johnb 5:abe8909f9603 87 typedef uint16_t CircularBufferIndex_t;
feb11 0:5d058c917599 88
johnb 5:abe8909f9603 89 CircularBufferIndex_t readIndex, writeIndex;
feb11 0:5d058c917599 90 uint8_t buffer[T];
feb11 0:5d058c917599 91
feb11 0:5d058c917599 92 };
feb11 0:5d058c917599 93
feb11 0:5d058c917599 94 template<size_t T>
feb11 0:5d058c917599 95 CircularBuffer<T>::CircularBuffer():
johnb 6:242d0e9f13d1 96 readIndex(0),
feb11 1:9953890d59e2 97 writeIndex(0)
feb11 0:5d058c917599 98 {
feb11 0:5d058c917599 99 }
feb11 0:5d058c917599 100
feb11 0:5d058c917599 101 template<size_t T>
johnb 7:e2d532183250 102 void CircularBuffer<T>::chomp(uint32_t length)
johnb 7:e2d532183250 103 {
johnb 7:e2d532183250 104 if( length >= getSize() )
johnb 7:e2d532183250 105 {
johnb 7:e2d532183250 106 readIndex = writeIndex;
johnb 7:e2d532183250 107 } else {
johnb 7:e2d532183250 108 readIndex = (readIndex + length) % T;
johnb 7:e2d532183250 109 }
johnb 7:e2d532183250 110 }
johnb 7:e2d532183250 111
johnb 7:e2d532183250 112 template<size_t T>
feb11 2:6f3630f5fa06 113 uint32_t CircularBuffer<T>::read(uint8_t *data, uint32_t length)
feb11 0:5d058c917599 114 {
feb11 2:6f3630f5fa06 115 uint32_t n = 0;
feb11 3:9a45d6675e65 116 while(n < length && getSize() > 0)
feb11 0:5d058c917599 117 {
feb11 2:6f3630f5fa06 118 if(readIndex == T)
feb11 2:6f3630f5fa06 119 readIndex = 0;
feb11 2:6f3630f5fa06 120 data[n++] = buffer[readIndex++];
feb11 0:5d058c917599 121 }
feb11 0:5d058c917599 122
feb11 2:6f3630f5fa06 123 return n;
feb11 0:5d058c917599 124 }
feb11 0:5d058c917599 125
feb11 0:5d058c917599 126 template<size_t T>
johnb 5:abe8909f9603 127 uint32_t CircularBuffer<T>::peek(uint8_t *data, uint32_t length) const
johnb 5:abe8909f9603 128 {
johnb 5:abe8909f9603 129 uint32_t n = 0;
johnb 5:abe8909f9603 130 CircularBufferIndex_t src = readIndex;
johnb 7:e2d532183250 131 while((n < length ) && (n < getSize()))
johnb 5:abe8909f9603 132 {
johnb 5:abe8909f9603 133 if(src == T) {
johnb 5:abe8909f9603 134 src = 0;
johnb 5:abe8909f9603 135 }
johnb 5:abe8909f9603 136 data[n++] = buffer[src++];
johnb 5:abe8909f9603 137 }
johnb 5:abe8909f9603 138
johnb 5:abe8909f9603 139 return n;
johnb 5:abe8909f9603 140 }
johnb 5:abe8909f9603 141
johnb 5:abe8909f9603 142 template<size_t T>
feb11 2:6f3630f5fa06 143 uint32_t CircularBuffer<T>::write(uint8_t *data, uint32_t length)
feb11 0:5d058c917599 144 {
feb11 2:6f3630f5fa06 145 uint32_t n = 0;
feb11 3:9a45d6675e65 146 while(n < length && getSize() < T)
feb11 0:5d058c917599 147 {
feb11 0:5d058c917599 148 if(writeIndex == T)
feb11 0:5d058c917599 149 writeIndex = 0;
feb11 2:6f3630f5fa06 150 buffer[writeIndex++] = data[n++];
feb11 0:5d058c917599 151 }
feb11 0:5d058c917599 152
feb11 2:6f3630f5fa06 153 return n;
feb11 2:6f3630f5fa06 154 }
feb11 2:6f3630f5fa06 155
feb11 2:6f3630f5fa06 156 template<size_t T>
feb11 2:6f3630f5fa06 157 uint32_t CircularBuffer<T>::getCapacity() const
feb11 2:6f3630f5fa06 158 {
feb11 2:6f3630f5fa06 159 return T;
feb11 2:6f3630f5fa06 160 }
feb11 2:6f3630f5fa06 161
feb11 2:6f3630f5fa06 162 template<size_t T>
feb11 2:6f3630f5fa06 163 uint32_t CircularBuffer<T>::getSize() const
feb11 2:6f3630f5fa06 164 {
johnb 6:242d0e9f13d1 165 return ((writeIndex >= readIndex) ? (writeIndex - readIndex) : (T + writeIndex - readIndex));
feb11 3:9a45d6675e65 166 }
feb11 3:9a45d6675e65 167
feb11 3:9a45d6675e65 168 template<size_t T>
feb11 3:9a45d6675e65 169 bool CircularBuffer<T>::isEmpty() const
feb11 3:9a45d6675e65 170 {
feb11 3:9a45d6675e65 171 return getSize() == 0;
feb11 3:9a45d6675e65 172 }
feb11 3:9a45d6675e65 173
feb11 3:9a45d6675e65 174 template<size_t T>
feb11 3:9a45d6675e65 175 bool CircularBuffer<T>::isFull() const
feb11 3:9a45d6675e65 176 {
feb11 3:9a45d6675e65 177 return getSize() == T;
feb11 0:5d058c917599 178 }
feb11 0:5d058c917599 179
feb11 0:5d058c917599 180 typedef CircularBuffer<32> SmallCircularBuffer;
feb11 0:5d058c917599 181 typedef CircularBuffer<128> MediumCircularBuffer;
feb11 2:6f3630f5fa06 182 typedef CircularBuffer<512> BigCircularBuffer;
feb11 0:5d058c917599 183
feb11 0:5d058c917599 184 #endif