Add uc_bv_find_first_zero

This commit is contained in:
Nils O. Selåsdal
2025-07-20 21:44:11 +02:00
parent 5b5ca445e9
commit 7408c48dff
3 changed files with 51 additions and 1 deletions
+6 -1
View File
@@ -68,11 +68,16 @@ void uc_bv_set_all(struct UCBitVec *v);
/** Initialize bits from a array of ints, each array element maps to one bit.
* The bits are initialized from the int array so zero maps to zero and non-zero maps to one.
* e..g to set the 5 first bits, to 01110:
* int a[] = {0,1,1,1,0};
* int a[] = {0,1,1,1,0};
* set_bits_from_array(v,a,5);
* */
void uc_bv_set_bits_from_array(struct UCBitVec *v,const char *array,size_t array_len);
/** Find the index of the first zero bit in the bitvec.
* @param v The bitvec to search
* @return The index of the first zero bit, or -1 if all bits are set
*/
int uc_bv_find_first_zero(const struct UCBitVec *v);
#ifdef __cplusplus
}
+18
View File
@@ -2,6 +2,7 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "ucore/utils.h"
#include "ucore/bitvec.h"
#ifdef __GNUC__
@@ -12,6 +13,8 @@
#define unlikely(expr) (expr)
#endif
UC_STATIC_ASSERT(CHAR_BIT % 8 == 0);
static inline int bit_index(int b)
{
return b / (sizeof(uc_bv_integer) * CHAR_BIT);
@@ -88,3 +91,18 @@ void uc_bv_set_all(struct UCBitVec *v)
memset(v->vec,0xff,v->vec_len * sizeof(uc_bv_integer));
}
int uc_bv_find_first_zero(const struct UCBitVec *v)
{
const size_t bits_per_word = sizeof(uc_bv_integer) * CHAR_BIT;
for (size_t i = 0; i < v->vec_len; i++) {
uc_bv_integer inverted = ~v->vec[i];
if (inverted != 0) {
int bit_pos = __builtin_ffsl(inverted) - 1; // ffsl returns 1-based index
return (int)(i * bits_per_word + bit_pos);
}
}
return -1;
}
+27
View File
@@ -79,6 +79,31 @@ START_TEST (test_bitvec_setall_clearall)
uc_bv_free(v);
}
END_TEST
START_TEST (test_bitvec_find_first_zero)
{
uc_bv_integer buf[8];
struct UCBitVec v = UC_BV_STATIC_INIT(buf);
uc_bv_set_all(&v);
int bit = uc_bv_find_first_zero(&v);
ck_assert_int_eq(bit, -1);
uc_bv_clr_bit(&v, 0);
bit = uc_bv_find_first_zero(&v);
ck_assert_int_eq(bit, 0);
uc_bv_set_bit(&v, 0);
uc_bv_clr_bit(&v, 63);
bit = uc_bv_find_first_zero(&v);
ck_assert_int_eq(bit, 63);
uc_bv_set_bit(&v, 63);
uc_bv_clr_bit(&v, sizeof buf * CHAR_BIT - 1);
bit = uc_bv_find_first_zero(&v);
ck_assert_int_eq(bit, sizeof buf * CHAR_BIT - 1);
}
END_TEST
@@ -91,6 +116,8 @@ Suite *bitvec_suite(void)
tcase_add_test(tc, test_bitvec_set_bits_from_array);
tcase_add_test(tc, test_bitvec_clearbit);
tcase_add_test(tc, test_bitvec_setall_clearall);
tcase_add_test(tc, test_bitvec_find_first_zero);
suite_add_tcase(s, tc);
return s;