fprime/Utils/Types/CircularBuffer.cpp
M Starch ec08d43dd3
Removes NATIVE_INT_TYPE, NATIVE_UINT_TYPE, and POINTER_CAST from Fw (#3286)
* NATIVE_INT_TYPE use in toString

* NATIVE_INT_TYPE use in SimpleObjRegistry

* NATIVE_INT_TYPE use in Asserts

* NATIVE_INT_TYPE use in Fw/Comp

* NATIVE_INT_TYPE use in getCapacity

* NATIVE_INT_TYPE use in getEntries

* NATIVE_INT_TYPE use in size/length

* NATIVE_INT_TYPE use in FILE_NAME_ARG

* NATIVE_INT_TYPE use in Fw (misc)

* NATIVE_INT_TYPE use in identifier

* NATIVE_INT_TYPE use in Fw (misc II)

* POINTER_CAST in Buffer

* POINTER_CAST in Serializable

* sp

* Removing no longer used DefaultTypes.hpp

* Fixes to accomidate Fw refactor

* Unit-test and CI fixes

* Fixing review comments - pt 1
2025-03-04 14:42:48 -08:00

166 lines
5.5 KiB
C++

/*
* CircularBuffer.cpp:
*
* Buffer used to efficiently store data in ring data structure. Uses an externally supplied
* data store as the backing for this buffer. Thus it is dependent on receiving sole ownership
* of the supplied buffer.
*
* This implementation file contains the function definitions.
*
* Created on: Apr 4, 2019
* Author: lestarch
* Revised March 2022
* Author: bocchino
*/
#include <FpConfig.hpp>
#include <Fw/Types/Assert.hpp>
#include <Utils/Types/CircularBuffer.hpp>
namespace Types {
CircularBuffer :: CircularBuffer() :
m_store(nullptr),
m_store_size(0),
m_head_idx(0),
m_allocated_size(0),
m_high_water_mark(0)
{
}
CircularBuffer :: CircularBuffer(U8* const buffer, const FwSizeType size) :
m_store(nullptr),
m_store_size(0),
m_head_idx(0),
m_allocated_size(0),
m_high_water_mark(0)
{
setup(buffer, size);
}
void CircularBuffer :: setup(U8* const buffer, const FwSizeType size) {
FW_ASSERT(size > 0);
FW_ASSERT(buffer != nullptr);
FW_ASSERT(m_store == nullptr && m_store_size == 0); // Not already setup
// Initialize buffer data
m_store = buffer;
m_store_size = size;
m_head_idx = 0;
m_allocated_size = 0;
m_high_water_mark = 0;
}
FwSizeType CircularBuffer :: get_allocated_size() const {
return m_allocated_size;
}
FwSizeType CircularBuffer :: get_free_size() const {
FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
FW_ASSERT(m_allocated_size <= m_store_size, static_cast<FwAssertArgType>(m_allocated_size));
return m_store_size - m_allocated_size;
}
FwSizeType CircularBuffer :: advance_idx(FwSizeType idx, FwSizeType amount) const {
FW_ASSERT(idx < m_store_size, static_cast<FwAssertArgType>(idx));
return (idx + amount) % m_store_size;
}
Fw::SerializeStatus CircularBuffer :: serialize(const U8* const buffer, const FwSizeType size) {
FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
FW_ASSERT(buffer != nullptr);
// Check there is sufficient space
if (size > get_free_size()) {
return Fw::FW_SERIALIZE_NO_ROOM_LEFT;
}
// Copy in all the supplied data
FwSizeType idx = advance_idx(m_head_idx, m_allocated_size);
for (U32 i = 0; i < size; i++) {
FW_ASSERT(idx < m_store_size, static_cast<FwAssertArgType>(idx));
m_store[idx] = buffer[i];
idx = advance_idx(idx);
}
m_allocated_size += size;
FW_ASSERT(m_allocated_size <= this->get_capacity(), static_cast<FwAssertArgType>(m_allocated_size));
m_high_water_mark = (m_high_water_mark > m_allocated_size) ? m_high_water_mark : m_allocated_size;
return Fw::FW_SERIALIZE_OK;
}
Fw::SerializeStatus CircularBuffer :: peek(char& value, FwSizeType offset) const {
FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
return peek(reinterpret_cast<U8&>(value), offset);
}
Fw::SerializeStatus CircularBuffer :: peek(U8& value, FwSizeType offset) const {
FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
// Check there is sufficient data
if ((sizeof(U8) + offset) > m_allocated_size) {
return Fw::FW_DESERIALIZE_BUFFER_EMPTY;
}
const FwSizeType idx = advance_idx(m_head_idx, offset);
FW_ASSERT(idx < m_store_size, static_cast<FwAssertArgType>(idx));
value = m_store[idx];
return Fw::FW_SERIALIZE_OK;
}
Fw::SerializeStatus CircularBuffer :: peek(U32& value, FwSizeType offset) const {
FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
// Check there is sufficient data
if ((sizeof(U32) + offset) > m_allocated_size) {
return Fw::FW_DESERIALIZE_BUFFER_EMPTY;
}
value = 0;
FwSizeType idx = advance_idx(m_head_idx, offset);
// Deserialize all the bytes from network format
for (FwSizeType i = 0; i < sizeof(U32); i++) {
FW_ASSERT(idx < m_store_size, static_cast<FwAssertArgType>(idx));
value = (value << 8) | static_cast<U32>(m_store[idx]);
idx = advance_idx(idx);
}
return Fw::FW_SERIALIZE_OK;
}
Fw::SerializeStatus CircularBuffer :: peek(U8* buffer, FwSizeType size, FwSizeType offset) const {
FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
FW_ASSERT(buffer != nullptr);
// Check there is sufficient data
if ((size + offset) > m_allocated_size) {
return Fw::FW_DESERIALIZE_BUFFER_EMPTY;
}
FwSizeType idx = advance_idx(m_head_idx, offset);
// Deserialize all the bytes from network format
for (FwSizeType i = 0; i < size; i++) {
FW_ASSERT(idx < m_store_size, static_cast<FwAssertArgType>(idx));
buffer[i] = m_store[idx];
idx = advance_idx(idx);
}
return Fw::FW_SERIALIZE_OK;
}
Fw::SerializeStatus CircularBuffer :: rotate(FwSizeType amount) {
FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
// Check there is sufficient data
if (amount > m_allocated_size) {
return Fw::FW_DESERIALIZE_BUFFER_EMPTY;
}
m_head_idx = advance_idx(m_head_idx, amount);
m_allocated_size -= amount;
return Fw::FW_SERIALIZE_OK;
}
FwSizeType CircularBuffer ::get_capacity() const {
FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
return m_store_size;
}
FwSizeType CircularBuffer ::get_high_water_mark() const {
return m_high_water_mark;
}
void CircularBuffer ::clear_high_water_mark() {
m_high_water_mark = 0;
}
} //End Namespace Types