WIP
This commit is contained in:
parent
e30cb230ab
commit
47aa5c4801
2 changed files with 30 additions and 26 deletions
|
@ -109,7 +109,6 @@ enum __SM_CHUNK_INFO {
|
|||
};
|
||||
|
||||
#define SM_CHUNK_GET_FLAGS(from, at) (((from)) & ((sm_bitvec_t)SM_FLAG_MASK << ((at)*2))) >> ((at)*2)
|
||||
#define SM_NEXT_CHUNK_ADDR(chunk) (uint8_t *)((chunk) + sizeof(sm_idx_t) + __sm_chunk_map_get_size((__sm_chunk_t *)&(chunk)));
|
||||
|
||||
typedef struct {
|
||||
sm_bitvec_t *m_data;
|
||||
|
@ -1216,9 +1215,7 @@ size_t
|
|||
sparsemap_get_size(sparsemap_t *map)
|
||||
{
|
||||
if (map->m_data_used) {
|
||||
__sm_when_diag({
|
||||
__sm_assert(map->m_data_used == __sm_get_size_impl(map));
|
||||
});
|
||||
__sm_when_diag({ __sm_assert(map->m_data_used == __sm_get_size_impl(map)); });
|
||||
return map->m_data_used;
|
||||
}
|
||||
return map->m_data_used = __sm_get_size_impl(map);
|
||||
|
@ -1248,7 +1245,8 @@ sparsemap_scan(sparsemap_t *map, void (*scanner)(sm_idx_t[], size_t), size_t ski
|
|||
}
|
||||
|
||||
void
|
||||
__sm_chunk_map_merge(sparsemap_t *map, sparsemap_idx_t offset, __sm_chunk_t src) {
|
||||
__sm_chunk_map_merge(sparsemap_t *map, sparsemap_idx_t offset, __sm_chunk_t src)
|
||||
{
|
||||
size_t capacity = __sm_chunk_map_get_capacity(&src);
|
||||
for (sparsemap_idx_t j = 0; j < capacity; j++, offset++) {
|
||||
if (__sm_chunk_map_is_set(&src, j)) {
|
||||
|
@ -1261,41 +1259,47 @@ void
|
|||
sparsemap_merge(sparsemap_t *map, sparsemap_t *other)
|
||||
{
|
||||
uint8_t *src, *dst, *dst_tail;
|
||||
size_t src_count = __sm_get_chunk_map_count(other),
|
||||
dst_count = __sm_get_chunk_map_count(map),
|
||||
max_chunk_count = src_count + dst_count;
|
||||
size_t src_count = __sm_get_chunk_map_count(other), dst_count = __sm_get_chunk_map_count(map), max_chunk_count = src_count + dst_count;
|
||||
|
||||
dst = __sm_get_chunk_map_data(map, 0);
|
||||
src = __sm_get_chunk_map_data(other, 0);
|
||||
for (size_t i = 0; i < max_chunk_count && src_count; i++) {
|
||||
__sm_chunk_t dst_chunk;
|
||||
sm_idx_t dst_start = *(sm_idx_t *)dst;
|
||||
__sm_chunk_map_init(&dst_chunk, dst + sizeof(sm_idx_t));
|
||||
|
||||
__sm_chunk_t src_chunk;
|
||||
sm_idx_t src_start = *(sm_idx_t *)src;
|
||||
__sm_chunk_map_init(&src_chunk, src + sizeof(sm_idx_t));
|
||||
|
||||
if (dst_count > 0 && src_start == dst_start) {
|
||||
if (src_start == dst_start && dst_count > 0) {
|
||||
/* Chunks overlap, merge them. */
|
||||
__sm_chunk_t src_chunk;
|
||||
__sm_chunk_map_init(&src_chunk, src + sizeof(sm_idx_t));
|
||||
__sm_chunk_t dst_chunk;
|
||||
__sm_chunk_map_init(&dst_chunk, dst + sizeof(sm_idx_t));
|
||||
__sm_chunk_map_merge(map, src_start, src_chunk);
|
||||
src = SM_NEXT_CHUNK_ADDR(src);
|
||||
dst = SM_NEXT_CHUNK_ADDR(dst);
|
||||
src += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&src_chunk);
|
||||
dst += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&dst_chunk);
|
||||
dst_count--;
|
||||
src_count--;
|
||||
continue;
|
||||
} else {
|
||||
/* Copy the chunk data directly into the buffer. */
|
||||
// TODO capacity check? ENOMEM
|
||||
dst_tail = __sm_get_chunk_map_end(map);
|
||||
*(sm_idx_t *)dst_tail = src_start;
|
||||
}
|
||||
if (src_start < dst_start || dst_count == 0) {
|
||||
__sm_chunk_t src_chunk;
|
||||
__sm_chunk_map_init(&src_chunk, src + sizeof(sm_idx_t));
|
||||
uint8_t buf[sizeof(sm_idx_t) + sizeof(sm_bitvec_t) * 2] = { 0 };
|
||||
size_t size = __sm_chunk_map_get_size(&src_chunk);
|
||||
memcpy(dst_tail + sizeof(sm_idx_t), src + sizeof(sm_idx_t), size);
|
||||
memcpy(buf, src + sizeof(sm_idx_t), size);
|
||||
__sm_insert_data(map, src_start, &buf[0], sizeof(buf));
|
||||
|
||||
size_t aligned_idx = __sm_get_fully_aligned_offset(src_start);
|
||||
if (src_start - aligned_idx < SM_CHUNK_MAX_CAPACITY) {
|
||||
__sm_chunk_t dst_chunk;
|
||||
__sm_chunk_map_init(&dst_chunk, dst + sizeof(sm_idx_t));
|
||||
__sm_chunk_map_set_capacity(&dst_chunk, src_start - aligned_idx);
|
||||
}
|
||||
*(sm_idx_t *)src = src_start = aligned_idx;
|
||||
|
||||
/* Update the chunk count and data_used. */
|
||||
map->m_data_used = 0;
|
||||
__sm_set_chunk_map_count(map, __sm_get_chunk_map_count(map) + 1);
|
||||
src = SM_NEXT_CHUNK_ADDR(src);
|
||||
|
||||
/* Carry on to the next chunk. */
|
||||
src += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&src_chunk);
|
||||
src_count--;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -654,7 +654,7 @@ test_api_merge(const MunitParameter params[], void *data)
|
|||
sparsemap_set(other, 4097, true);
|
||||
sparsemap_set(other, 8193, true);
|
||||
|
||||
sparsemap_merge(map,other);
|
||||
sparsemap_merge(map, other);
|
||||
|
||||
assert_true(sparsemap_is_set(map, 1));
|
||||
assert_true(sparsemap_is_set(map, 2049));
|
||||
|
|
Loading…
Reference in a new issue