This commit is contained in:
Gregory Burd 2024-04-29 17:01:45 -04:00
parent e5e4a0f960
commit 1ab6c90257
2 changed files with 54 additions and 30 deletions

View file

@ -52,7 +52,7 @@ void __attribute__((format(printf, 4, 5))) __sm_diag_(const char *file, int line
#define __sm_assert(expr) \ #define __sm_assert(expr) \
if (!(expr)) \ if (!(expr)) \
fprintf(stderr, "%s:%d:%s(): assertion failed! %s", __FILE__, __LINE__, __func__, #expr) fprintf(stderr, "%s:%d:%s(): assertion failed! %s\n", __FILE__, __LINE__, __func__, #expr)
#define __sm_when_diag(expr) \ #define __sm_when_diag(expr) \
if (1) \ if (1) \
@ -1260,45 +1260,51 @@ __sm_chunk_map_merge(sparsemap_t *map, sparsemap_idx_t offset, __sm_chunk_t src)
void void
sparsemap_merge(sparsemap_t *map, sparsemap_t *other) sparsemap_merge(sparsemap_t *map, sparsemap_t *other)
{ {
uint8_t *dst = __sm_get_chunk_map_data(map, 0), uint8_t *src, *dst, *dst_tail;
*dst_tail = __sm_get_chunk_map_end(map), size_t src_count = __sm_get_chunk_map_count(other),
*src = __sm_get_chunk_map_data(other, 0); dst_count = __sm_get_chunk_map_count(map);
size_t i, src_count = __sm_get_chunk_map_count(other), dst_count = __sm_get_chunk_map_count(map); dst = __sm_get_chunk_map_data(map, 0);
for (i = 0; i < src_count + dst_count;) { src = __sm_get_chunk_map_data(other, 0);
__sm_chunk_t src_chunk, dst_chunk; /* Foreach destination chunk, is there a source chunk with the same starting
sm_idx_t src_start = *(sm_idx_t *)src; offset? If so, if so let's merge them. */
for (size_t i = 0; i < dst_count + src_count; i++) {
__sm_chunk_t dst_chunk;
sm_idx_t dst_start = *(sm_idx_t *)dst; sm_idx_t dst_start = *(sm_idx_t *)dst;
__sm_chunk_map_init(&src_chunk, src + sizeof(sm_idx_t));
__sm_chunk_map_init(&dst_chunk, dst + sizeof(sm_idx_t)); __sm_chunk_map_init(&dst_chunk, dst + sizeof(sm_idx_t));
size_t j = 0;
if (src_start == dst_start) { if (i < dst_count) {
/* Chunks overlap, merge them. */ while (j < src_count) {
__sm_chunk_map_merge(map, src_start, src_chunk); __sm_chunk_t src_chunk;
src = SM_NEXT_CHUNK_ADDR(src); sm_idx_t src_start = *(sm_idx_t *)src;
dst = SM_NEXT_CHUNK_ADDR(dst); __sm_chunk_map_init(&src_chunk, src + sizeof(sm_idx_t));
i += 2; if (src_start == dst_start) {
} else if (src_start < dst_start || i > dst_count) { /* Chunks overlap, merge them. */
/* Copy the src chunk into the dest map. */ __sm_chunk_map_merge(map, src_start, src_chunk);
size_t s = __sm_chunk_map_get_size(&src_chunk); dst = SM_NEXT_CHUNK_ADDR(dst);
src = SM_NEXT_CHUNK_ADDR(src);
/* Copy the index (sm_idx_t) */ j = SIZE_MAX;
*(sm_idx_t *)dst_tail = src_start; break;
dst_tail += sizeof(sm_idx_t); }
dst = SM_NEXT_CHUNK_ADDR(dst);
j++;
}
}
if (j != SIZE_MAX) {
__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));
/* Copy the chunk data to the buffer. */ /* Copy the chunk data to the buffer. */
memcpy(dst_tail, src, s); dst_tail = __sm_get_chunk_map_end(map);
*(sm_idx_t *)dst_tail = src_start;
size_t size = __sm_chunk_map_get_size(&src_chunk);
memcpy(dst_tail + sizeof(sm_idx_t), src + sizeof(sm_idx_t), size);
/* Update the chunk count and data_used. */ /* Update the chunk count and data_used. */
map->m_data_used = 0; map->m_data_used = 0;
__sm_set_chunk_map_count(map, __sm_get_chunk_map_count(map) + 1); __sm_set_chunk_map_count(map, __sm_get_chunk_map_count(map) + 1);
src = SM_NEXT_CHUNK_ADDR(src); src = SM_NEXT_CHUNK_ADDR(src);
i += 1;
if (i > dst_count) {
dst = SM_NEXT_CHUNK_ADDR(dst);
i += 1;
}
} }
} }
} }

View file

@ -631,11 +631,29 @@ test_api_merge(const MunitParameter params[], void *data)
assert_ptr_not_null(map); assert_ptr_not_null(map);
assert_ptr_not_null(other); assert_ptr_not_null(other);
sparsemap_set(other, 0, true);
sparsemap_merge(map, other);
assert_true(sparsemap_is_set(other, 0));
assert_true(sparsemap_is_set(map, 0));
sparsemap_clear(map);
sparsemap_clear(other);
sparsemap_set(other, 2049, true);
sparsemap_merge(map, other);
assert_true(sparsemap_is_set(map, 2049));
sparsemap_clear(map);
sparsemap_clear(other);
sparsemap_set(map, 0, true); sparsemap_set(map, 0, true);
sparsemap_set(other, 1, true); sparsemap_set(other, 1, true);
sparsemap_set(other, 2049, true); sparsemap_set(other, 2049, true);
sparsemap_set(other, 8193, true); sparsemap_set(other, 8193, true);
sparsemap_set(other, 8194, true); sparsemap_set(other, 8194, true);
sparsemap_merge(map,other); sparsemap_merge(map,other);
assert_true(sparsemap_is_set(map, 0)); assert_true(sparsemap_is_set(map, 0));