52 : m_count(0), m_maxChunks(maxChunks), m_chunks(chunkMem) {
60 memset(m_chunks, 0,
sizeof(*m_chunks) * m_maxChunks);
64 const Chunk chunk = {offset, size};
65 const ChunkIdx i = findInsertPosition(&chunk);
70 FW_ASSERT((offset + size) >= offset, static_cast<FwAssertArgType>(offset), static_cast<FwAssertArgType>(size));
76 return m_count ? &m_chunks[0] :
nullptr;
80 Chunk* chunk = &m_chunks[0];
82 if (size > chunk->
size) {
106 FW_ASSERT(start < total, static_cast<FwAssertArgType>(start), static_cast<FwAssertArgType>(total));
113 callback(&chunk, opaque);
118 if (start < m_chunks[0].offset) {
122 callback(&chunk, opaque);
127 while ((ret < maxGaps) && (i < m_count)) {
128 next_off = (i == (m_count - 1)) ? total : m_chunks[i + 1].
offset;
129 gap_start = (m_chunks[i].
offset + m_chunks[i].
size);
131 chunk.
offset = (gap_start > start) ? gap_start : start;
134 if (gap_start >= total) {
136 }
else if (start < next_off) {
139 callback(&chunk, opaque);
150 void CfdpChunkList::insertChunk(
ChunkIdx index,
const Chunk* chunk) {
151 FW_ASSERT(m_count < m_maxChunks, m_count, m_maxChunks);
152 FW_ASSERT(index <= m_count, index, m_count);
154 if (m_count && (index != m_count)) {
155 memmove(&m_chunks[index + 1], &m_chunks[index],
sizeof(*chunk) * (m_count - index));
157 memcpy(&m_chunks[index], chunk,
sizeof(*chunk));
162 void CfdpChunkList::eraseChunk(
ChunkIdx index) {
164 FW_ASSERT(index < m_count, index, m_count);
167 memmove(&m_chunks[index], &m_chunks[index + 1],
sizeof(*m_chunks) * (m_count - 1 - index));
176 memmove(&m_chunks[start], &m_chunks[end],
sizeof(*m_chunks) * (m_count - end));
177 m_count =
static_cast<ChunkIdx>(m_count -
static_cast<ChunkIdx>(end - start));
181 ChunkIdx CfdpChunkList::findInsertPosition(
const Chunk* chunk) {
189 step =
static_cast<ChunkIdx>(count / 2);
190 i =
static_cast<ChunkIdx>(i + step);
191 if (m_chunks[i].offset < chunk->offset) {
192 first =
static_cast<ChunkIdx>(i + 1);
202 bool CfdpChunkList::combineNext(
ChunkIdx i,
const Chunk* chunk) {
205 FileSize chunk_end = chunk->offset + chunk->size;
208 FW_ASSERT(chunk_end > chunk->offset, static_cast<FwAssertArgType>(chunk_end),
209 static_cast<FwAssertArgType>(chunk->offset));
212 for (; combined_i < m_count; ++combined_i) {
214 if (chunk_end < m_chunks[combined_i].offset) {
220 if (i != combined_i) {
222 chunk_end =
CfdpChunkMax(m_chunks[combined_i - 1].offset + m_chunks[combined_i - 1].size, chunk_end);
225 m_chunks[i].
size = chunk_end - chunk->offset;
226 m_chunks[i].
offset = chunk->offset;
229 eraseRange(static_cast<ChunkIdx>(i + 1), combined_i);
236 bool CfdpChunkList::combinePrevious(
ChunkIdx i,
const Chunk* chunk) {
242 FW_ASSERT(i <= m_maxChunks, i, m_maxChunks);
246 chunk_end = chunk->offset + chunk->size;
247 prev = &m_chunks[i - 1];
248 prev_end = prev->
offset + prev->size;
251 if (chunk->offset <= prev_end) {
253 if (prev_end < chunk_end) {
255 prev->size = chunk_end - prev->offset;
263 void CfdpChunkList::insert(
ChunkIdx i,
const Chunk* chunk) {
266 bool next = combineNext(i, chunk);
270 combined = combinePrevious(i, &m_chunks[i]);
275 combined = combinePrevious(i, chunk);
277 if (m_count < m_maxChunks) {
278 insertChunk(i, chunk);
280 smallest_i = findSmallestSize();
281 smallest_c = &m_chunks[smallest_i];
282 if (smallest_c->size < chunk->size) {
283 eraseChunk(smallest_i);
284 insertChunk(findInsertPosition(chunk), chunk);
291 ChunkIdx CfdpChunkList::findSmallestSize()
const {
295 for (i = 1; i < m_count; ++i) {
296 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.