GCC Code Coverage Report


Directory: ./
File: Svc/Ccsds/CfdpManager/Chunk.hpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 5 6 83.3%
Functions: 3 3 100.0%
Branches: 1 2 50.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title Chunk.hpp
3 // \brief CFDP chunks (spare gap tracking) header file
4 //
5 // This file is a port of CFDP chunk/gap tracking from the following files
6 // from the NASA Core Flight System (cFS) CFDP (CF) Application, version 3.0.0,
7 // adapted for use within the F-Prime (F') framework:
8 // - cf_chunks.h (CFDP chunk and gap tracking definitions)
9 //
10 // ======================================================================
11 //
12 // NASA Docket No. GSC-18,447-1
13 //
14 // Copyright (c) 2019 United States Government as represented by the
15 // Administrator of the National Aeronautics and Space Administration.
16 // All Rights Reserved.
17 //
18 // Licensed under the Apache License, Version 2.0 (the "License"); you may
19 // not use this file except in compliance with the License. You may obtain
20 // a copy of the License at
21 //
22 // http://www.apache.org/licenses/LICENSE-2.0
23 //
24 // Unless required by applicable law or agreed to in writing, software
25 // distributed under the License is distributed on an "AS IS" BASIS,
26 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27 // See the License for the specific language governing permissions and
28 // limitations under the License.
29 //
30 // ======================================================================
31
32 #ifndef CFDP_CHUNK_HPP
33 #define CFDP_CHUNK_HPP
34
35 #include <Fw/FPrimeBasicTypes.hpp>
36
37 #include <Svc/Ccsds/CfdpManager/Types/StatusEnumAc.hpp>
38 #include <config/FileSizeAliasAc.hpp>
39
40 namespace Svc {
41 namespace Ccsds {
42 namespace Cfdp {
43
44 using ChunkIdx = U16;
45
46 /**
47 * @brief Pairs an offset with a size to identify a specific piece of a file
48 */
49 struct Chunk {
50 FileSize offset; /**< \brief The start offset of the chunk within the file */
51 FileSize size; /**< \brief The size of the chunk */
52 };
53
54 /**
55 * @brief Selects the larger of the two passed-in offsets
56 *
57 * @param a First chunk offset
58 * @param b Second chunk offset
59 * @return the larger FileSize value
60 */
61 1 static inline FileSize CfdpChunkMax(FileSize a, FileSize b) {
62
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (a > b) {
63 1 return a;
64 } else {
65 return b;
66 }
67 }
68
69 /**
70 * @brief Callback type for gap computation
71 *
72 * Function pointer callback used by CfdpChunkList::computeGaps().
73 * The callback receives the gap chunk and an opaque context pointer.
74 */
75 using GapComputeCallback = void (*)(const Chunk* chunk, void* opaque);
76
77 /**
78 * @brief C++ class encapsulation of CFDP chunk list operations
79 *
80 * This class provides modern C++ encapsulation around the gap tracking functionality
81 * previously implemented as C-style free functions. The class does not own the backing
82 * memory for chunks; it takes a pointer to pre-allocated memory in the constructor,
83 * preserving the existing memory pooling system managed by Channel.
84 *
85 * The chunk list maintains file segments in offset-sorted order and provides operations
86 * for adding segments, computing gaps, and managing the list. This is primarily used for:
87 * - RX transactions: Track received file data segments to identify gaps for NAK packets
88 * - TX transactions: Track NAK segment requests for retransmission
89 */
90 class CfdpChunkList {
91 public:
92 // ----------------------------------------------------------------------
93 // Construction and Destruction
94 // ----------------------------------------------------------------------
95
96 /**
97 * @brief Constructor - initializes chunk list with pre-allocated memory
98 *
99 * @param maxChunks Maximum number of chunks this list can hold
100 * @param chunkMem Pointer to pre-allocated array of Chunk objects
101 *
102 * @note The class does NOT take ownership of chunkMem; memory is externally managed
103 */
104 CfdpChunkList(ChunkIdx maxChunks, Chunk* chunkMem);
105
106 // ----------------------------------------------------------------------
107 // Public Interface
108 // ----------------------------------------------------------------------
109
110 /**
111 * @brief Add a chunk (file segment) to the list
112 *
113 * Adds a new chunk representing a file segment at the given offset and size.
114 * The chunk may be combined with adjacent chunks if they are contiguous.
115 * If the list is full, the smallest chunk may be evicted.
116 *
117 * @param offset Starting offset of the chunk within the file
118 * @param size Size of the chunk in bytes
119 */
120 void add(FileSize offset, FileSize size);
121
122 /**
123 * @brief Reset the chunk list to empty state
124 *
125 * Removes all chunks from the list while preserving the max_chunks and
126 * memory pointer configuration. After reset, the list is in the same state
127 * as immediately after construction.
128 */
129 void reset();
130
131 /**
132 * @brief Get the first chunk in the list
133 *
134 * Returns a pointer to the first chunk (lowest offset) in the list without
135 * removing it from the list.
136 *
137 * @returns Pointer to the first chunk
138 * @retval nullptr if the list is empty
139 */
140 const Chunk* getFirstChunk() const;
141
142 /**
143 * @brief Remove a specified size from the first chunk
144 *
145 * Reduces the size of the first chunk by the specified amount. If the
146 * size exactly matches the chunk size, the entire chunk is removed.
147 * This is used for consuming data in-order during processing.
148 *
149 * @param size Number of bytes to remove from the first chunk
150 *
151 * @note The list must not be empty when calling this function
152 */
153 void removeFromFirst(FileSize size);
154
155 /**
156 * @brief Compute gaps between chunks and invoke callback for each
157 *
158 * Walks the chunk list and computes gaps (missing file segments) between
159 * chunks. For each gap found, invokes the provided callback function.
160 * This is used to generate NAK segment requests.
161 *
162 * @param maxGaps Maximum number of gaps to compute
163 * @param total Total size of the file
164 * @param start Starting offset for gap computation
165 * @param callback Callback function to invoke for each gap
166 * @param opaque Opaque pointer passed through to callback
167 *
168 * @returns Number of gaps computed (may be less than maxGaps if fewer gaps exist)
169 *
170 * @note A total of 0 (zero-length file) yields no gaps
171 */
172 U32 computeGaps(ChunkIdx maxGaps, FileSize total, FileSize start, GapComputeCallback callback, void* opaque) const;
173
174 /**
175 * @brief Get the current number of chunks in the list
176 * @returns Current chunk count
177 */
178 4 ChunkIdx getCount() const { return m_count; }
179
180 /**
181 * @brief Get the maximum number of chunks this list can hold
182 * @returns Maximum chunk capacity
183 */
184 1 ChunkIdx getMaxChunks() const { return m_maxChunks; }
185
186 private:
187 // ----------------------------------------------------------------------
188 // Private Implementation
189 // ----------------------------------------------------------------------
190
191 /**
192 * @brief Insert a chunk at a specific index
193 *
194 * Inserts the chunk at the specified index position, shifting existing
195 * chunks as needed. May combine with adjacent chunks if contiguous.
196 *
197 * @param index Index position to insert at
198 * @param chunk Chunk data to insert
199 */
200 void insertChunk(ChunkIdx index, const Chunk* chunk);
201
202 /**
203 * @brief Erase a single chunk at the given index
204 *
205 * Removes the chunk and shifts subsequent chunks to close the gap.
206 *
207 * @param index Index of chunk to erase
208 */
209 void eraseChunk(ChunkIdx index);
210
211 /**
212 * @brief Erase a range of chunks
213 *
214 * Removes chunks from start (inclusive) to end (exclusive) and shifts
215 * remaining chunks to close the gap.
216 *
217 * @param start Starting index (inclusive)
218 * @param end Ending index (exclusive)
219 */
220 void eraseRange(ChunkIdx start, ChunkIdx end);
221
222 /**
223 * @brief Find where a chunk should be inserted to maintain sorted order
224 *
225 * Uses binary search to find the insertion point based on chunk offset.
226 *
227 * @param chunk Chunk data to find insertion point for
228 * @returns Index where chunk should be inserted
229 */
230 ChunkIdx findInsertPosition(const Chunk* chunk);
231
232 /**
233 * @brief Attempt to combine chunk with the next chunk
234 *
235 * If the chunk is contiguous with the next chunk in the list, combines them.
236 *
237 * @param i Index of the current chunk
238 * @param chunk Chunk data to attempt combining
239 * @returns true if chunks were combined, false otherwise
240 */
241 bool combineNext(ChunkIdx i, const Chunk* chunk);
242
243 /**
244 * @brief Attempt to combine chunk with the previous chunk
245 *
246 * If the chunk is contiguous with the previous chunk in the list, combines them.
247 *
248 * @param i Index of the current chunk
249 * @param chunk Chunk data to attempt combining
250 * @returns true if chunks were combined, false otherwise
251 */
252 bool combinePrevious(ChunkIdx i, const Chunk* chunk);
253
254 /**
255 * @brief Insert a chunk, potentially combining with neighbors
256 *
257 * Inserts the chunk at position i and attempts to combine with adjacent chunks.
258 *
259 * @param i Position to insert at
260 * @param chunk Chunk data to insert
261 */
262 void insert(ChunkIdx i, const Chunk* chunk);
263
264 /**
265 * @brief Find the index of the chunk with the smallest size
266 *
267 * Used when the list is full and a chunk needs to be evicted.
268 *
269 * @returns Index of the smallest chunk, or 0 if list is empty
270 */
271 ChunkIdx findSmallestSize() const;
272
273 private:
274 // ----------------------------------------------------------------------
275 // Private Member Variables
276 // ----------------------------------------------------------------------
277
278 ChunkIdx m_count; //!< Current number of chunks in the list
279 ChunkIdx m_maxChunks; //!< Maximum number of chunks allowed
280 Chunk* m_chunks; //!< Pointer to pre-allocated chunk array (not owned)
281 };
282
283 } // namespace Cfdp
284 } // namespace Ccsds
285 } // namespace Svc
286
287 #endif /* !CFDP_CHUNK_HPP */
288