F´ Flight Software - C/C++ Documentation devel
A framework for building embedded system applications to NASA flight quality standards.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CircularBuffer.cpp
Go to the documentation of this file.
1/*
2 * CircularBuffer.cpp:
3 *
4 * Buffer used to efficiently store data in ring data structure. Uses an externally supplied
5 * data store as the backing for this buffer. Thus it is dependent on receiving sole ownership
6 * of the supplied buffer.
7 *
8 * This implementation file contains the function definitions.
9 *
10 * Created on: Apr 4, 2019
11 * Author: lestarch
12 * Revised March 2022
13 * Author: bocchino
14 */
15#include <FpConfig.hpp>
16#include <Fw/Types/Assert.hpp>
18
19#ifdef CIRCULAR_DEBUG
20 #include <Os/Log.hpp>
21#endif
22
23namespace Types {
24
25CircularBuffer :: CircularBuffer() :
26 m_store(nullptr),
27 m_store_size(0),
28 m_head_idx(0),
29 m_allocated_size(0),
30 m_high_water_mark(0)
31{
32
33}
34
35CircularBuffer :: CircularBuffer(U8* const buffer, const NATIVE_UINT_TYPE size) :
36 m_store(nullptr),
37 m_store_size(0),
38 m_head_idx(0),
39 m_allocated_size(0),
40 m_high_water_mark(0)
41{
42 setup(buffer, size);
43}
44
45void CircularBuffer :: setup(U8* const buffer, const NATIVE_UINT_TYPE size) {
46 FW_ASSERT(size > 0);
47 FW_ASSERT(buffer != nullptr);
48 FW_ASSERT(m_store == nullptr && m_store_size == 0); // Not already setup
49
50 // Initialize buffer data
51 m_store = buffer;
52 m_store_size = size;
53 m_head_idx = 0;
54 m_allocated_size = 0;
55 m_high_water_mark = 0;
56}
57
58NATIVE_UINT_TYPE CircularBuffer :: get_allocated_size() const {
59 return m_allocated_size;
60}
61
62NATIVE_UINT_TYPE CircularBuffer :: get_free_size() const {
63 FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
64 FW_ASSERT(m_allocated_size <= m_store_size, m_allocated_size);
65 return m_store_size - m_allocated_size;
66}
67
68NATIVE_UINT_TYPE CircularBuffer :: advance_idx(NATIVE_UINT_TYPE idx, NATIVE_UINT_TYPE amount) const {
69 FW_ASSERT(idx < m_store_size, idx);
70 return (idx + amount) % m_store_size;
71}
72
73Fw::SerializeStatus CircularBuffer :: serialize(const U8* const buffer, const NATIVE_UINT_TYPE size) {
74 FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
75 FW_ASSERT(buffer != nullptr);
76 // Check there is sufficient space
77 if (size > get_free_size()) {
79 }
80 // Copy in all the supplied data
81 NATIVE_UINT_TYPE idx = advance_idx(m_head_idx, m_allocated_size);
82 for (U32 i = 0; i < size; i++) {
83 FW_ASSERT(idx < m_store_size, idx);
84 m_store[idx] = buffer[i];
85 idx = advance_idx(idx);
86 }
87 m_allocated_size += size;
88 FW_ASSERT(m_allocated_size <= this->get_capacity(), m_allocated_size);
89 m_high_water_mark = (m_high_water_mark > m_allocated_size) ? m_high_water_mark : m_allocated_size;
91}
92
93Fw::SerializeStatus CircularBuffer :: peek(char& value, NATIVE_UINT_TYPE offset) const {
94 FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
95 return peek(reinterpret_cast<U8&>(value), offset);
96}
97
98Fw::SerializeStatus CircularBuffer :: peek(U8& value, NATIVE_UINT_TYPE offset) const {
99 FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
100 // Check there is sufficient data
101 if ((sizeof(U8) + offset) > m_allocated_size) {
103 }
104 const NATIVE_UINT_TYPE idx = advance_idx(m_head_idx, offset);
105 FW_ASSERT(idx < m_store_size, idx);
106 value = m_store[idx];
107 return Fw::FW_SERIALIZE_OK;
108}
109
110Fw::SerializeStatus CircularBuffer :: peek(U32& value, NATIVE_UINT_TYPE offset) const {
111 FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
112 // Check there is sufficient data
113 if ((sizeof(U32) + offset) > m_allocated_size) {
115 }
116 value = 0;
117 NATIVE_UINT_TYPE idx = advance_idx(m_head_idx, offset);
118
119 // Deserialize all the bytes from network format
120 for (NATIVE_UINT_TYPE i = 0; i < sizeof(U32); i++) {
121 FW_ASSERT(idx < m_store_size, idx);
122 value = (value << 8) | static_cast<U32>(m_store[idx]);
123 idx = advance_idx(idx);
124 }
125 return Fw::FW_SERIALIZE_OK;
126}
127
128Fw::SerializeStatus CircularBuffer :: peek(U8* buffer, NATIVE_UINT_TYPE size, NATIVE_UINT_TYPE offset) const {
129 FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
130 FW_ASSERT(buffer != nullptr);
131 // Check there is sufficient data
132 if ((size + offset) > m_allocated_size) {
134 }
135 NATIVE_UINT_TYPE idx = advance_idx(m_head_idx, offset);
136 // Deserialize all the bytes from network format
137 for (NATIVE_UINT_TYPE i = 0; i < size; i++) {
138 FW_ASSERT(idx < m_store_size, idx);
139 buffer[i] = m_store[idx];
140 idx = advance_idx(idx);
141 }
142 return Fw::FW_SERIALIZE_OK;
143}
144
145Fw::SerializeStatus CircularBuffer :: rotate(NATIVE_UINT_TYPE amount) {
146 FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
147 // Check there is sufficient data
148 if (amount > m_allocated_size) {
150 }
151 m_head_idx = advance_idx(m_head_idx, amount);
152 m_allocated_size -= amount;
153 return Fw::FW_SERIALIZE_OK;
154}
155
156NATIVE_UINT_TYPE CircularBuffer ::get_capacity() const {
157 FW_ASSERT(m_store != nullptr && m_store_size != 0); // setup method was called
158 return m_store_size;
159}
160
161NATIVE_UINT_TYPE CircularBuffer ::get_high_water_mark() const {
162 return m_high_water_mark;
163}
164
165void CircularBuffer ::clear_high_water_mark() {
166 m_high_water_mark = 0;
167}
168
169#ifdef CIRCULAR_DEBUG
170void CircularBuffer :: print() {
171 NATIVE_UINT_TYPE idx = m_head_idx;
172 Os::Log::logMsg("Ring: ", 0, 0, 0, 0, 0, 0);
173 for (NATIVE_UINT_TYPE i = 0; i < m_allocated_size; ++i) {
174 Os::Log::logMsg("%c", m_store[idx], 0, 0, 0, 0, 0);
175 idx = advance_idx(idx);
176 }
177 Os::Log::logMsg("\n", 0, 0, 0, 0, 0, 0);
178}
179#endif
180} //End Namespace Types
#define FW_ASSERT(...)
Definition Assert.hpp:14
uint8_t U8
8-bit unsigned integer
Definition BasicTypes.h:26
PlatformUIntType NATIVE_UINT_TYPE
Definition BasicTypes.h:52
C++-compatible configuration header for fprime configuration.
static void logMsg(const char *fmt, POINTER_CAST a0=0, POINTER_CAST a1=0, POINTER_CAST a2=0, POINTER_CAST a3=0, POINTER_CAST a4=0, POINTER_CAST a5=0, POINTER_CAST a6=0, POINTER_CAST a7=0, POINTER_CAST a8=0, POINTER_CAST a9=0)
Definition Logger.cpp:18
void setup(U8 *const buffer, const NATIVE_UINT_TYPE size)
SerializeStatus
forward declaration for string
@ FW_DESERIALIZE_BUFFER_EMPTY
Deserialization buffer was empty when trying to read more data.
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.
@ FW_SERIALIZE_NO_ROOM_LEFT
No room left in the buffer to serialize data.