getFreeELement function added

This commit is contained in:
Robin Müller 2020-08-24 14:55:32 +02:00
parent 49d4b6ebc7
commit b7612bee37
2 changed files with 263 additions and 89 deletions

View File

@ -1,68 +1,135 @@
#include "SimpleRingBuffer.h" #include "../container/SimpleRingBuffer.h"
#include <string.h> #include <cstring>
SimpleRingBuffer::SimpleRingBuffer(uint32_t size, bool overwriteOld) : SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
RingBufferBase<>(0, size, overwriteOld), buffer(NULL) { size_t maxExcessBytes) :
buffer = new uint8_t[size]; RingBufferBase<>(0, size, overwriteOld),
} maxExcessBytes(maxExcessBytes) {
if(maxExcessBytes > size) {
SimpleRingBuffer::~SimpleRingBuffer() { this->maxExcessBytes = size;
delete[] buffer; }
} else {
this->maxExcessBytes = maxExcessBytes;
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, }
uint32_t amount) { buffer = new uint8_t[size + maxExcessBytes];
if (availableWriteSpace() >= amount || overwriteOld) { }
uint32_t amountTillWrap = writeTillWrap();
if (amountTillWrap >= amount) { SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size,
memcpy(&buffer[write], data, amount); bool overwriteOld, size_t maxExcessBytes):
} else { RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {
memcpy(&buffer[write], data, amountTillWrap); if(maxExcessBytes > size) {
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap); this->maxExcessBytes = size;
} }
incrementWrite(amount); else {
return HasReturnvaluesIF::RETURN_OK; this->maxExcessBytes = maxExcessBytes;
} else { }
return HasReturnvaluesIF::RETURN_FAILED; }
}
}
SimpleRingBuffer::~SimpleRingBuffer() {
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, uint32_t amount, delete[] buffer;
bool readRemaining, uint32_t* trueAmount) { }
uint32_t availableData = availableReadData(READ_PTR);
uint32_t amountTillWrap = readTillWrap(READ_PTR);
if (availableData < amount) { ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
if (readRemaining) { size_t amount) {
amount = availableData; if (availableWriteSpace() >= amount or overwriteOld) {
} else { size_t amountTillWrap = writeTillWrap();
return HasReturnvaluesIF::RETURN_FAILED; if (amountTillWrap < amount) {
} if((amount - amountTillWrap + excessBytes) > maxExcessBytes) {
} return HasReturnvaluesIF::RETURN_FAILED;
if (trueAmount != NULL) { }
*trueAmount = amount; excessBytes = amount - amountTillWrap;
} }
if (amountTillWrap >= amount) { *writePointer = &buffer[write];
memcpy(data, &buffer[read[READ_PTR]], amount); return HasReturnvaluesIF::RETURN_OK;
} else { }
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap); else {
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap); return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; }
}
void SimpleRingBuffer::confirmBytesWritten(size_t amount) {
ReturnValue_t SimpleRingBuffer::deleteData(uint32_t amount, if(getExcessBytes() > 0) {
bool deleteRemaining, uint32_t* trueAmount) { moveExcessBytesToStart();
uint32_t availableData = availableReadData(READ_PTR); }
if (availableData < amount) { incrementWrite(amount);
if (deleteRemaining) {
amount = availableData; }
} else {
return HasReturnvaluesIF::RETURN_FAILED; ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
} size_t amount) {
} if (availableWriteSpace() >= amount or overwriteOld) {
if (trueAmount != NULL) { size_t amountTillWrap = writeTillWrap();
*trueAmount = amount; if (amountTillWrap >= amount) {
} // remaining size in buffer is sufficient to fit full amount.
incrementRead(amount, READ_PTR); memcpy(&buffer[write], data, amount);
return HasReturnvaluesIF::RETURN_OK; }
} else {
memcpy(&buffer[write], data, amountTillWrap);
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap);
}
incrementWrite(amount);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount,
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
size_t availableData = getAvailableReadData(READ_PTR);
size_t amountTillWrap = readTillWrap(READ_PTR);
if (availableData < amount) {
if (readRemaining) {
// more data available than amount specified.
amount = availableData;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
if (trueAmount != nullptr) {
*trueAmount = amount;
}
if (amountTillWrap >= amount) {
memcpy(data, &buffer[read[READ_PTR]], amount);
} else {
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap);
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap);
}
if(incrementReadPtr) {
deleteData(amount, readRemaining);
}
return HasReturnvaluesIF::RETURN_OK;
}
size_t SimpleRingBuffer::getExcessBytes() const {
return excessBytes;
}
void SimpleRingBuffer::moveExcessBytesToStart() {
if(excessBytes > 0) {
std::memcpy(buffer, &buffer[size], excessBytes);
excessBytes = 0;
}
}
ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
bool deleteRemaining, size_t* trueAmount) {
size_t availableData = getAvailableReadData(READ_PTR);
if (availableData < amount) {
if (deleteRemaining) {
amount = availableData;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
if (trueAmount != nullptr) {
*trueAmount = amount;
}
incrementRead(amount, READ_PTR);
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -1,21 +1,128 @@
#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ #ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ #define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
#include "RingBufferBase.h" #include "../container/RingBufferBase.h"
#include <stddef.h> #include <cstddef>
class SimpleRingBuffer: public RingBufferBase<> { /**
public: * @brief Circular buffer implementation, useful for buffering
SimpleRingBuffer(uint32_t size, bool overwriteOld); * into data streams.
virtual ~SimpleRingBuffer(); * @details
ReturnValue_t writeData(const uint8_t* data, uint32_t amount); * Note that the deleteData() has to be called to increment the read pointer.
ReturnValue_t readData(uint8_t* data, uint32_t amount, bool readRemaining = false, uint32_t* trueAmount = NULL); * This class allocated dynamically, so
ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false, uint32_t* trueAmount = NULL); * @ingroup containers
private: */
// static const uint8_t TEMP_READ_PTR = 1; class SimpleRingBuffer: public RingBufferBase<> {
static const uint8_t READ_PTR = 0; public:
uint8_t* buffer; /**
}; * This constructor allocates a new internal buffer with the supplied size.
*
#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ * @param size
* @param overwriteOld If the ring buffer is overflowing at a write
* operation, the oldest data will be overwritten.
* @param maxExcessBytes These additional bytes will be allocated in addtion
* to the specified size to accomodate contiguous write operations
* with getFreeElement.
*
*/
SimpleRingBuffer(const size_t size, bool overwriteOld,
size_t maxExcessBytes = 0);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
* @param maxExcessBytes
* If the buffer can accomodate additional bytes for contigous write
* operations with getFreeElement, this is the maximum allowed additional
* size
*/
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld,
size_t maxExcessBytes = 0);
virtual ~SimpleRingBuffer();
/**
* Write to circular buffer and increment write pointer by amount.
* @param data
* @param amount
* @return -@c RETURN_OK if write operation was successfull
* -@c RETURN_FAILED if
*/
ReturnValue_t writeData(const uint8_t* data, size_t amount);
/**
* Returns a pointer to a free element. If the remaining buffer is
* not large enough, the data will be written past the actual size
* and the amount of excess bytes will be cached. This function
* does not increment the write pointer!
* @param writePointer Pointer to a pointer which can be used to write
* contiguous blocks into the ring buffer
* @param amount
* @return
*/
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
/**
* This increments the write pointer and also copies the excess bytes
* to the beginning. It should be called if the write operation
* conducted after calling getFreeElement() was performed.
* @return
*/
void confirmBytesWritten(size_t amount);
virtual size_t getExcessBytes() const;
/**
* Helper functions which moves any excess bytes to the start
* of the ring buffer.
* @return
*/
virtual void moveExcessBytesToStart();
/**
* Read from circular buffer at read pointer.
* @param data
* @param amount
* @param incrementReadPtr
* If this is set to true, the read pointer will be incremented.
* If readRemaining is set to true, the read pointer will be incremented
* accordingly.
* @param readRemaining
* If this is set to true, the data will be read even if the amount
* specified exceeds the read data available.
* @param trueAmount [out]
* If readRemaining was set to true, the true amount read will be assigned
* to the passed value.
* @return
* - @c RETURN_OK if data was read successfully
* - @c RETURN_FAILED if not enough data was available and readRemaining
* was set to false.
*/
ReturnValue_t readData(uint8_t* data, size_t amount,
bool incrementReadPtr = false, bool readRemaining = false,
size_t* trueAmount = nullptr);
/**
* Delete data by incrementing read pointer.
* @param amount
* @param deleteRemaining
* If the amount specified is larger than the remaing size to read and this
* is set to true, the remaining amount will be deleted as well
* @param trueAmount [out]
* If deleteRemaining was set to true, the amount deleted will be assigned
* to the passed value.
* @return
*/
ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
size_t* trueAmount = nullptr);
private:
static const uint8_t READ_PTR = 0;
uint8_t* buffer = nullptr;
size_t maxExcessBytes;
size_t excessBytes = 0;
};
#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */