This commit is contained in:
Gregory Burd 2024-04-30 10:44:43 -04:00
parent bd8a1f0b0c
commit b399e8af78
2 changed files with 41 additions and 5 deletions

View file

@ -825,7 +825,8 @@ __sm_get_fully_aligned_offset(size_t idx)
*
* @param[in] map The sparsemap_t in question.
* @param[in] idx The index of the chunk map to locate.
* @returns the byte offset of a __sm_chunk_t in m_data.
* @returns the byte offset of a __sm_chunk_t in m_data, or -1 there
* are no chunks.
*/
static size_t
__sm_get_chunk_map_offset(sparsemap_t *map, sparsemap_idx_t idx)
@ -843,7 +844,7 @@ __sm_get_chunk_map_offset(sparsemap_t *map, sparsemap_idx_t idx)
__sm_assert(s == __sm_get_aligned_offset(s));
__sm_chunk_t chunk;
__sm_chunk_map_init(&chunk, p + sizeof(sm_idx_t));
if (s >= idx || (unsigned long)idx < s + __sm_chunk_map_get_capacity(&chunk)) {
if (s >= idx || idx < s + __sm_chunk_map_get_capacity(&chunk)) {
break;
}
p += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&chunk);
@ -1070,7 +1071,7 @@ sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value)
return SPARSEMAP_IDX_MAX;
}
/* If there is no __sm_chunk_t and the bit is set to zero then return
/* If there are no __sm_chunk_t and the bit is set to zero then return
immediately; otherwise create an initial __sm_chunk_t. */
if (offset == -1) {
if (value == false) {
@ -1270,6 +1271,7 @@ sparsemap_merge(sparsemap_t *map, sparsemap_t *other)
__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);
*(sm_idx_t *)dst = __sm_get_aligned_offset(src_start);
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--;
@ -1280,14 +1282,24 @@ sparsemap_merge(sparsemap_t *map, sparsemap_t *other)
__sm_chunk_t src_chunk;
__sm_chunk_map_init(&src_chunk, src + sizeof(sm_idx_t));
size_t src_size = __sm_chunk_map_get_size(&src_chunk);
__sm_insert_data(map, dst_start, src, src_size);
uint8_t buf[sizeof(sm_idx_t) + sizeof(sm_bitvec_t) * 2] = { 0 };
if (dst_count == 0) {
__sm_append_data(map, &buf[0], sizeof(buf));
} else {
size_t offset = __sm_get_chunk_map_offset(map, dst_start);
__sm_insert_data(map, offset, &buf[0], sizeof(buf));
}
memcpy(dst + sizeof(sm_idx_t), &src_chunk, src_size);
*(sm_idx_t *)dst = src_start;
/* Update the chunk count and data_used. */
__sm_set_chunk_map_count(map, __sm_get_chunk_map_count(map) + 1);
/* Carry on to the next chunk. */
__sm_chunk_t dst_chunk;
__sm_chunk_map_init(&dst_chunk, dst + sizeof(sm_idx_t));
src += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&src_chunk);
dst += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&dst_chunk);
src_count--;
}
}

View file

@ -631,8 +631,10 @@ test_api_merge(const MunitParameter params[], void *data)
assert_ptr_not_null(map);
assert_ptr_not_null(other);
// Merge two empty maps to get an empty map.
sparsemap_merge(map, other);
// Merge a single set bit in the first chunk into the empty map.
sparsemap_set(other, 0, true);
sparsemap_merge(map, other);
@ -642,6 +644,7 @@ test_api_merge(const MunitParameter params[], void *data)
sparsemap_clear(map);
sparsemap_clear(other);
// Merge two maps with the same single bit set.
sparsemap_set(map, 0, true);
sparsemap_set(other, 0, true);
sparsemap_merge(map, other);
@ -649,6 +652,7 @@ test_api_merge(const MunitParameter params[], void *data)
sparsemap_clear(map);
sparsemap_clear(other);
// Merge an empty map with one that has the first bit set.
sparsemap_set(map, 0, true);
sparsemap_merge(map, other);
@ -680,12 +684,32 @@ test_api_merge(const MunitParameter params[], void *data)
assert_true(sparsemap_is_set(map, 8193));
for (int i = 0; i < 10000; i++) {
if (i == 2050 || i == 1 || i == 2049 || i == 4097 || i == 8193)
if (i == 2049 || i == 1 || i == 2050 || i == 4097 || i == 8193)
continue;
else
assert_false(sparsemap_is_set(map, i));
}
sparsemap_clear(map);
sparsemap_clear(other);
sparsemap_set(map, 0, true);
sparsemap_set(map, 2048, true);
sparsemap_set(map, 2049, true);
sparsemap_set(map, 8193, true);
for (int i = 2049; i < 4096; i++) {
sparsemap_set(other, i, true);
}
sparsemap_merge(map, other);
assert(sparsemap_is_set(map, 0));
assert(sparsemap_is_set(map, 2048));
assert(sparsemap_is_set(map, 8193));
for (int i = 2049; i < 4096; i++) {
assert(sparsemap_is_set(map, i));
}
free(other);
return MUNIT_OK;
}