52 : m_count(0), m_maxChunks(maxChunks), m_chunks(chunkMem) {
60 memset(m_chunks, 0,
sizeof(*m_chunks) * m_maxChunks);
72 const Chunk chunk = {offset, size};
73 const ChunkIdx i = findInsertPosition(&chunk);
78 FW_ASSERT((offset + size) >= offset, static_cast<FwAssertArgType>(offset), static_cast<FwAssertArgType>(size));
84 return m_count ? &m_chunks[0] :
nullptr;
88 Chunk* chunk = &m_chunks[0];
90 if (size > chunk->
size) {
106 void* opaque)
const {
118 FW_ASSERT(start < total, static_cast<FwAssertArgType>(start), static_cast<FwAssertArgType>(total));
125 callback(&chunk, opaque);
130 if (start < m_chunks[0].offset) {
134 callback(&chunk, opaque);
139 while ((ret < maxGaps) && (i < m_count)) {
140 next_off = (i == (m_count - 1)) ? total : m_chunks[i + 1].
offset;
141 gap_start = (m_chunks[i].
offset + m_chunks[i].
size);
143 chunk.
offset = (gap_start > start) ? gap_start : start;
146 if (gap_start >= total) {
148 }
else if (start < next_off) {
151 callback(&chunk, opaque);
162 void CfdpChunkList::insertChunk(
ChunkIdx index,
const Chunk* chunk) {
163 FW_ASSERT(m_count < m_maxChunks, m_count, m_maxChunks);
164 FW_ASSERT(index <= m_count, index, m_count);
166 if (m_count && (index != m_count)) {
167 memmove(&m_chunks[index + 1], &m_chunks[index],
sizeof(*chunk) * (m_count - index));
169 memcpy(&m_chunks[index], chunk,
sizeof(*chunk));
174 void CfdpChunkList::eraseChunk(
ChunkIdx index) {
176 FW_ASSERT(index < m_count, index, m_count);
179 memmove(&m_chunks[index], &m_chunks[index + 1],
sizeof(*m_chunks) * (m_count - 1 - index));
188 memmove(&m_chunks[start], &m_chunks[end],
sizeof(*m_chunks) * (m_count - end));
189 m_count =
static_cast<ChunkIdx>(m_count -
static_cast<ChunkIdx>(end - start));
193 ChunkIdx CfdpChunkList::findInsertPosition(
const Chunk* chunk) {
201 step =
static_cast<ChunkIdx>(count / 2);
202 i =
static_cast<ChunkIdx>(i + step);
203 if (m_chunks[i].offset < chunk->offset) {
204 first =
static_cast<ChunkIdx>(i + 1);
214 bool CfdpChunkList::combineNext(
ChunkIdx i,
const Chunk* chunk) {
217 FileSize chunk_end = chunk->offset + chunk->size;
220 FW_ASSERT(chunk_end > chunk->offset, static_cast<FwAssertArgType>(chunk_end),
221 static_cast<FwAssertArgType>(chunk->offset));
224 for (; combined_i < m_count; ++combined_i) {
226 if (chunk_end < m_chunks[combined_i].offset) {
232 if (i != combined_i) {
234 chunk_end =
CfdpChunkMax(m_chunks[combined_i - 1].offset + m_chunks[combined_i - 1].size, chunk_end);
237 m_chunks[i].
size = chunk_end - chunk->offset;
238 m_chunks[i].
offset = chunk->offset;
241 eraseRange(static_cast<ChunkIdx>(i + 1), combined_i);
248 bool CfdpChunkList::combinePrevious(
ChunkIdx i,
const Chunk* chunk) {
254 FW_ASSERT(i <= m_maxChunks, i, m_maxChunks);
258 chunk_end = chunk->offset + chunk->size;
259 prev = &m_chunks[i - 1];
260 prev_end = prev->
offset + prev->size;
263 if (chunk->offset <= prev_end) {
265 if (prev_end < chunk_end) {
267 prev->size = chunk_end - prev->offset;
275 void CfdpChunkList::insert(
ChunkIdx i,
const Chunk* chunk) {
278 bool next = combineNext(i, chunk);
282 combined = combinePrevious(i, &m_chunks[i]);
287 combined = combinePrevious(i, chunk);
289 if (m_count < m_maxChunks) {
290 insertChunk(i, chunk);
292 smallest_i = findSmallestSize();
293 smallest_c = &m_chunks[smallest_i];
294 if (smallest_c->size < chunk->size) {
295 eraseChunk(smallest_i);
296 insertChunk(findInsertPosition(chunk), chunk);
303 ChunkIdx CfdpChunkList::findSmallestSize()
const {
307 for (i = 1; i < m_count; ++i) {
308 if (m_chunks[i].size < m_chunks[smallest].size) {
void removeFromFirst(FileSize size)
Remove a specified size from the first chunk.
void reset()
Reset the chunk list to empty state.
FileSize size
The size of the chunk.
void add(FileSize offset, FileSize size)
Add a chunk (file segment) to the list.
FileSize offset
The start offset of the chunk within the file.
U32 FileSize
File size and offset type.
void(*)(const Chunk *chunk, void *opaque) GapComputeCallback
Callback type for gap computation.
CfdpChunkList(ChunkIdx maxChunks, Chunk *chunkMem)
Constructor - initializes chunk list with pre-allocated memory.
RateGroupDivider component implementation.
const Chunk * getFirstChunk() const
Get the first chunk in the list.
static FileSize CfdpChunkMax(FileSize a, FileSize b)
Selects the larger of the two passed-in offsets.
U32 computeGaps(ChunkIdx maxGaps, FileSize total, FileSize start, GapComputeCallback callback, void *opaque) const
Compute gaps between chunks and invoke callback for each.
Pairs an offset with a size to identify a specific piece of a file.