From 1ab6c90257a18992957466728b6b29b025793628 Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Mon, 29 Apr 2024 17:01:45 -0400 Subject: [PATCH] WIP --- src/sparsemap.c | 66 +++++++++++++++++++++++++++---------------------- tests/test.c | 18 ++++++++++++++ 2 files changed, 54 insertions(+), 30 deletions(-) diff --git a/src/sparsemap.c b/src/sparsemap.c index 726a047..874c7cf 100644 --- a/src/sparsemap.c +++ b/src/sparsemap.c @@ -52,7 +52,7 @@ void __attribute__((format(printf, 4, 5))) __sm_diag_(const char *file, int line #define __sm_assert(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) \ if (1) \ @@ -1260,45 +1260,51 @@ __sm_chunk_map_merge(sparsemap_t *map, sparsemap_idx_t offset, __sm_chunk_t src) void sparsemap_merge(sparsemap_t *map, sparsemap_t *other) { - uint8_t *dst = __sm_get_chunk_map_data(map, 0), - *dst_tail = __sm_get_chunk_map_end(map), - *src = __sm_get_chunk_map_data(other, 0); + uint8_t *src, *dst, *dst_tail; + size_t src_count = __sm_get_chunk_map_count(other), + 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); - for (i = 0; i < src_count + dst_count;) { - __sm_chunk_t src_chunk, dst_chunk; - sm_idx_t src_start = *(sm_idx_t *)src; + dst = __sm_get_chunk_map_data(map, 0); + src = __sm_get_chunk_map_data(other, 0); + /* Foreach destination chunk, is there a source chunk with the same starting + 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_chunk_map_init(&src_chunk, src + sizeof(sm_idx_t)); __sm_chunk_map_init(&dst_chunk, dst + sizeof(sm_idx_t)); - - if (src_start == dst_start) { - /* Chunks overlap, merge them. */ - __sm_chunk_map_merge(map, src_start, src_chunk); - src = SM_NEXT_CHUNK_ADDR(src); - dst = SM_NEXT_CHUNK_ADDR(dst); - i += 2; - } else if (src_start < dst_start || i > dst_count) { - /* Copy the src chunk into the dest map. */ - size_t s = __sm_chunk_map_get_size(&src_chunk); - - /* Copy the index (sm_idx_t) */ - *(sm_idx_t *)dst_tail = src_start; - dst_tail += sizeof(sm_idx_t); + size_t j = 0; + if (i < dst_count) { + while (j < src_count) { + __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 (src_start == dst_start) { + /* Chunks overlap, merge them. */ + __sm_chunk_map_merge(map, src_start, src_chunk); + dst = SM_NEXT_CHUNK_ADDR(dst); + src = SM_NEXT_CHUNK_ADDR(src); + j = SIZE_MAX; + break; + } + 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. */ - 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. */ map->m_data_used = 0; __sm_set_chunk_map_count(map, __sm_get_chunk_map_count(map) + 1); - src = SM_NEXT_CHUNK_ADDR(src); - i += 1; - if (i > dst_count) { - dst = SM_NEXT_CHUNK_ADDR(dst); - i += 1; - } } } } diff --git a/tests/test.c b/tests/test.c index ac226da..6494d31 100644 --- a/tests/test.c +++ b/tests/test.c @@ -631,11 +631,29 @@ test_api_merge(const MunitParameter params[], void *data) assert_ptr_not_null(map); 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(other, 1, true); sparsemap_set(other, 2049, true); sparsemap_set(other, 8193, true); sparsemap_set(other, 8194, true); + sparsemap_merge(map,other); assert_true(sparsemap_is_set(map, 0));