diff --git a/Makefile b/Makefile index 492eebe..1eb7777 100644 --- a/Makefile +++ b/Makefile @@ -5,9 +5,9 @@ SHARED_LIB = libsparsemap.so LIBS = -lm #CFLAGS = -Wall -Wextra -Wpedantic -Of -std=c11 -Iinclude/ -fPIC $(LIBS) -#CFLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC $(LIBS) +CFLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC $(LIBS) #CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -O0 -g -std=c11 -Iinclude/ -fPIC $(LIBS) -CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -Ofast -g -std=c11 -Iinclude/ -fPIC $(LIBS) +#CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -Ofast -g -std=c11 -Iinclude/ -fPIC $(LIBS) #CFLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC $(LIBS) #CFLAGS = -Wall -Wextra -Wpedantic -Ofast -g -std=c11 -Iinclude/ -fPIC $(LIBS) #CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -Og -g -fsanitize=address,leak,object-size,pointer-compare,pointer-subtract,null,return,bounds,pointer-overflow,undefined -fsanitize-address-use-after-scope -std=c11 -Iinclude/ -fPIC $(LIBS) @@ -39,16 +39,16 @@ $(SHARED_LIB): $(OBJS) examples: $(STATIC_LIB) $(EXAMPLES) $(TEST_OBJS) -soak: tests/soak.c - tests/soak - mls: examples/mls -test: $(TESTS) +tests: $(TESTS) -check: test +test: tests env ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./tests/test +soak: tests + env ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./tests/soak + tests/test: $(TEST_OBJS) $(LIB_OBJS) $(STATIC_LIB) $(CC) $^ -o $@ $(TEST_FLAGS) @@ -76,19 +76,19 @@ examples/%.o: examples/%.c $(CC) $(CFLAGS) -c -o $@ $^ examples/ex_1: $(LIB_OBJS) examples/ex_1.o $(STATIC_LIB) - $(CC) $^ -o $@ $(CFLAGS) $(TEST_FLAGS) + $(CC) $^ -o $@ $(TEST_FLAGS) examples/ex_2: $(LIB_OBJS) examples/ex_2.o $(STATIC_LIB) - $(CC) $^ -o $@ $(CFLAGS) $(TEST_FLAGS) + $(CC) $^ -o $@ $(TEST_FLAGS) examples/ex_3: $(LIB_OBJS) examples/ex_3.o $(STATIC_LIB) - $(CC) $^ -o $@ $(CFLAGS) $(TEST_FLAGS) + $(CC) $^ -o $@ $(TEST_FLAGS) examples/ex_4: $(LIB_OBJS) examples/ex_4.o $(STATIC_LIB) - $(CC) $^ -o $@ $(CFLAGS) $(TEST_FLAGS) + $(CC) $^ -o $@ $(TEST_FLAGS) tests/soak: $(LIB_OBJS) tests/soak.o $(STATIC_LIB) - $(CC) $^ -o $@ $(CFLAGS) $(TEST_FLAGS) + $(CC) $^ -o $@ $(TEST_FLAGS) todo: rg -i 'todo|gsb|abort' diff --git a/include/sparsemap.h b/include/sparsemap.h index 571f431..65d4245 100644 --- a/include/sparsemap.h +++ b/include/sparsemap.h @@ -263,8 +263,10 @@ void sparsemap_scan(sparsemap_t *map, void (*scanner)(sm_idx_t vec[], size_t n, * * @param[in] map The sparsemap reference. * @param[in] other The bitmap to merge into \b map. + * @returns 0 on success, -1 and sets errno to ENOSPC when the merge might + * require more space than available. */ -void sparsemap_merge(sparsemap_t *map, sparsemap_t *other); +int sparsemap_merge(sparsemap_t *map, sparsemap_t *other); /** @brief Splits the bitmap by assigning all bits starting at \b offset to the * \b other bitmap while removing them from \b map. diff --git a/src/sparsemap.c b/src/sparsemap.c index 10ed7a6..0520da9 100644 --- a/src/sparsemap.c +++ b/src/sparsemap.c @@ -821,6 +821,7 @@ __sm_get_size_impl(sparsemap_t *map) return SM_SIZEOF_OVERHEAD + p - start; } +#ifdef DIAGNOSTIC /** @brief Aligns to SM_BITS_PER_VECTOR a given index \b idx. * * @param[in] idx The index to align. @@ -832,6 +833,7 @@ __sm_get_aligned_offset(size_t idx) const size_t capacity = SM_BITS_PER_VECTOR; return (idx / capacity) * capacity; } +#endif /** @brief Aligns to SM_CHUNK_MAP_CAPACITY a given index \b idx. * @@ -1264,13 +1266,20 @@ sparsemap_scan(sparsemap_t *map, void (*scanner)(sm_idx_t[], size_t, void *aux), } } -void +int sparsemap_merge(sparsemap_t *map, sparsemap_t *other) { 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; + size_t src_count = __sm_get_chunk_map_count(other); + size_t dst_count = __sm_get_chunk_map_count(map); + size_t max_chunk_count = src_count + dst_count; + + /* Estimate worst-case overhead required for merge. */ + if (map->m_data_used + src_count * (sizeof(sm_idx_t) + sizeof(sm_bitvec_t) * 2) > map->m_capacity) { + errno = ENOSPC; + return -1; + } - // TODO: ensure there is space, or ENOSPC 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++) { @@ -1321,6 +1330,7 @@ sparsemap_merge(sparsemap_t *map, sparsemap_t *other) src_count--; } } + return 0; } void