diff --git a/src/sparsemap.c b/src/sparsemap.c index f8db713..4e2b826 100644 --- a/src/sparsemap.c +++ b/src/sparsemap.c @@ -438,7 +438,7 @@ __sm_chunk_map_set(__sm_chunk_t *map, size_t idx, bool value, size_t *pos, sm_bi * SM_BITS_PER_VECTOR */ static size_t -__sm_chunk_map_select(__sm_chunk_t *map, size_t n, ssize_t *offset, bool value) +__sm_chunk_map_select(__sm_chunk_t *map, size_t n, sparsemap_idx_t *offset, bool value) { size_t ret = 0; register uint8_t *p; @@ -509,12 +509,10 @@ __sm_chunk_map_select(__sm_chunk_t *map, size_t n, ssize_t *offset, bool value) } } } - *offset = (ssize_t)n; + *offset = n; return ret; } -extern void print_bits(char *name, uint64_t value); // GSB - /** @brief Counts the bits matching \b value in the range [0, \b idx] * inclusive after ignoring the first \b offset bits in the chunk. * @@ -1067,7 +1065,6 @@ sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value) /* Get the __sm_chunk_t which manages this index */ ssize_t offset = __sm_get_chunk_map_offset(map, idx); bool dont_grow = false; - if (map->m_data_used + sizeof(sm_idx_t) + sizeof(sm_bitvec_t) * 2 > map->m_capacity) { errno = ENOSPC; return SPARSEMAP_IDX_MAX; @@ -1137,7 +1134,7 @@ sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value) } size_t size = __sm_chunk_map_get_size(&chunk); - offset += (ssize_t)(sizeof(sm_idx_t) + size); + offset += (sizeof(sm_idx_t) + size); p += sizeof(sm_idx_t) + size; uint8_t buf[sizeof(sm_idx_t) + sizeof(sm_bitvec_t) * 2] = { 0 }; @@ -1170,7 +1167,7 @@ sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value) break; case SM_NEEDS_TO_GROW: if (!dont_grow) { - offset += (ssize_t)(sizeof(sm_idx_t) + position * sizeof(sm_bitvec_t)); + offset += (sizeof(sm_idx_t) + position * sizeof(sm_bitvec_t)); __sm_insert_data(map, offset, (uint8_t *)&fill, sizeof(sm_bitvec_t)); } __sm_chunk_map_set(&chunk, idx - start, value, &position, &fill, true); @@ -1182,7 +1179,7 @@ sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value) __sm_remove_data(map, offset, sizeof(sm_idx_t) + sizeof(sm_bitvec_t) * 2); __sm_set_chunk_map_count(map, __sm_get_chunk_map_count(map) - 1); } else { - offset += (ssize_t)(sizeof(sm_idx_t) + position * sizeof(sm_bitvec_t)); + offset += (sizeof(sm_idx_t) + position * sizeof(sm_bitvec_t)); __sm_remove_data(map, offset, sizeof(sm_bitvec_t)); } break; @@ -1258,7 +1255,7 @@ __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 *src, *dst, *dst_tail; + uint8_t *src, *dst; 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); @@ -1283,20 +1280,28 @@ sparsemap_merge(sparsemap_t *map, sparsemap_t *other) __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(buf, src + sizeof(sm_idx_t), size); - __sm_insert_data(map, src_start, &buf[0], sizeof(buf)); + size_t src_size = __sm_chunk_map_get_size(&src_chunk); + size_t offset = src_start + (sizeof(sm_idx_t) + src_size); + __sm_insert_data(map, offset, &buf[0], sizeof(buf)); + *(sm_idx_t *)dst = src_start; - 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; + __sm_chunk_t dst_chunk; + __sm_chunk_map_init(&dst_chunk, dst + sizeof(sm_idx_t)); /* Update the chunk count and data_used. */ __sm_set_chunk_map_count(map, __sm_get_chunk_map_count(map) + 1); + if (other->m_data_used != 0) { + other->m_data_used += sizeof(sm_idx_t) + sizeof(sm_bitvec_t); + } + size_t capacity = __sm_chunk_map_get_capacity(&src_chunk); + + /* Reduce the capacity of the source-chunk map. */ + __sm_chunk_map_set_capacity(&dst_chunk, offset % capacity); + + /* + uint8_t *src_data = __sm_get_chunk_map_data(other, src_start); + memcpy(&buf, src_data, src_size); + */ /* Carry on to the next chunk. */ src += sizeof(sm_idx_t) + __sm_chunk_map_get_size(&src_chunk); @@ -1441,7 +1446,7 @@ sparsemap_select(sparsemap_t *map, sparsemap_idx_t n, bool value) __sm_chunk_t chunk; __sm_chunk_map_init(&chunk, p); - ssize_t new_n = (ssize_t)n; + ssize_t new_n = n; size_t index = __sm_chunk_map_select(&chunk, n, &new_n, value); if (new_n == -1) { return start + index; diff --git a/tests/test.c b/tests/test.c index 4eeba93..f1feeb8 100644 --- a/tests/test.c +++ b/tests/test.c @@ -631,6 +631,8 @@ test_api_merge(const MunitParameter params[], void *data) assert_ptr_not_null(map); assert_ptr_not_null(other); + sparsemap_merge(map, other); + sparsemap_set(other, 0, true); sparsemap_merge(map, other); @@ -640,6 +642,21 @@ test_api_merge(const MunitParameter params[], void *data) sparsemap_clear(map); sparsemap_clear(other); + sparsemap_set(map, 0, true); + sparsemap_set(other, 0, true); + sparsemap_merge(map, other); + + sparsemap_clear(map); + sparsemap_clear(other); + + sparsemap_set(map, 0, true); + sparsemap_merge(map, other); + + assert_true(sparsemap_is_set(map, 0)); + + sparsemap_clear(map); + sparsemap_clear(other); + sparsemap_set(other, 2049, true); sparsemap_merge(map, other);