diff --git a/librz/include/rz_util/rz_bitvector.h b/librz/include/rz_util/rz_bitvector.h index 85fb02a741..bc053bb525 100644 --- a/librz/include/rz_util/rz_bitvector.h +++ b/librz/include/rz_util/rz_bitvector.h @@ -40,6 +40,7 @@ RZ_API void rz_bv_free(RZ_NULLABLE RzBitVector *bv); // read and write to a bit RZ_API bool rz_bv_set(RZ_NONNULL RzBitVector *bv, ut32 pos, bool b); RZ_API bool rz_bv_set_all(RZ_NONNULL RzBitVector *bv, bool b); +RZ_API bool rz_bv_set_range(RZ_NONNULL RzBitVector *bv, ut32 pos_start, ut32 pos_end, bool b); RZ_API bool rz_bv_toggle(RZ_NONNULL RzBitVector *bv, ut32 pos); RZ_API bool rz_bv_toggle_all(RZ_NONNULL RzBitVector *bv); RZ_API RZ_OWN RzBitVector *rz_bv_append_zero(RZ_NONNULL RzBitVector *bv, ut32 delta_len); @@ -85,6 +86,7 @@ RZ_API ut32 rz_bv_to_ut32(RZ_NONNULL const RzBitVector *x); RZ_API ut64 rz_bv_to_ut64(RZ_NONNULL const RzBitVector *x); // misc RZ_API bool rz_bv_is_zero_vector(RZ_NONNULL const RzBitVector *x); +RZ_API bool rz_bv_is_all_one(RZ_NONNULL const RzBitVector *x); RZ_API RZ_OWN RzBitVector *rz_bv_new_from_ut64(ut32 length, ut64 value); RZ_API RZ_OWN RzBitVector *rz_bv_new_from_st64(ut32 length, st64 value); RZ_API RZ_OWN RzBitVector *rz_bv_new_from_bytes_le(RZ_IN RZ_NONNULL const ut8 *buf, ut32 bit_offset, ut32 size); diff --git a/librz/util/bitvector.c b/librz/util/bitvector.c index ae002fac24..cf9d7a9413 100644 --- a/librz/util/bitvector.c +++ b/librz/util/bitvector.c @@ -1464,3 +1464,42 @@ RZ_API ut64 rz_bv_to_ut64(RZ_NONNULL const RzBitVector *x) { } return ret; } + +/** + * set a range of bits to bool value `b`, the range is inclusive + * pos_end element is also included + * \param bv RzBitVector + * \param pos_start start index of range + * \param pos_end end index of range + * \param b bool value + * \return return true if success, else return false + */ +RZ_API bool rz_bv_set_range(RZ_NONNULL RzBitVector *bv, ut32 pos_start, ut32 pos_end, bool b) { + rz_return_val_if_fail(bv, false); + if (pos_start > bv->len - 1 || pos_end > bv->len - 1) { + return false; + } + + for (ut32 i = pos_start; i <= pos_end; ++i) { + rz_bv_set(bv, i, b); + } + + return true; +} + +/** + * check if bitvector's bits are all set to bit 1 + * \param x RzBitVector + * \return true if all bits of bv `x` are set to 1 + */ +RZ_API bool rz_bv_is_all_one(RZ_NONNULL const RzBitVector *x) { + rz_return_val_if_fail(x, false); + // could not use ~0 as full-vector when bits < 64 + + for (ut32 i = 0; i < x->len; ++i) { + if (rz_bv_get(x, i) == 0) { + return false; + } + } + return true; +} diff --git a/test/unit/test_bitvector.c b/test/unit/test_bitvector.c index 4d727e5500..c43a4f7427 100644 --- a/test/unit/test_bitvector.c +++ b/test/unit/test_bitvector.c @@ -970,33 +970,53 @@ static bool test_rz_bv_len_bytes(void) { mu_end; } -bool test_rz_bv_set_all(void) { +bool test_rz_bv_set_operations(void) { RzBitVector *bv = rz_bv_new(43); rz_bv_set_all(bv, true); mu_assert_streq_free(rz_bv_as_hex_string(bv, false), "0x7ffffffffff", "set all 1"); + mu_assert_true(rz_bv_is_all_one(bv), "all bits are 1"); rz_bv_set_all(bv, false); mu_assert_streq_free(rz_bv_as_hex_string(bv, false), "0x0", "set all 0"); + mu_assert_false(rz_bv_is_all_one(bv), "not all 1"); rz_bv_free(bv); bv = rz_bv_new(64); rz_bv_set_all(bv, true); mu_assert_streq_free(rz_bv_as_hex_string(bv, false), "0xffffffffffffffff", "set all 1"); + mu_assert_true(rz_bv_is_all_one(bv), "all bits are 1"); rz_bv_set_all(bv, false); mu_assert_streq_free(rz_bv_as_hex_string(bv, false), "0x0", "set all 0"); + mu_assert_false(rz_bv_is_all_one(bv), "not all 1"); rz_bv_free(bv); bv = rz_bv_new(73); rz_bv_set_all(bv, true); mu_assert_streq_free(rz_bv_as_hex_string(bv, false), "0x1ffffffffffffffffff", "set all 1"); + mu_assert_true(rz_bv_is_all_one(bv), "all bits are 1"); rz_bv_set_all(bv, false); mu_assert_streq_free(rz_bv_as_hex_string(bv, false), "0x0", "set all 0"); + mu_assert_false(rz_bv_is_all_one(bv), "not all 1"); rz_bv_free(bv); bv = rz_bv_new(80); rz_bv_set_all(bv, true); mu_assert_streq_free(rz_bv_as_hex_string(bv, false), "0xffffffffffffffffffff", "set all 1"); + mu_assert_true(rz_bv_is_all_one(bv), "all bits are 1"); rz_bv_set_all(bv, false); mu_assert_streq_free(rz_bv_as_hex_string(bv, false), "0x0", "set all 0"); + mu_assert_false(rz_bv_is_all_one(bv), "not all 1"); + rz_bv_free(bv); + + bv = rz_bv_new(42); + rz_bv_set_range(bv, 0, bv->len - 1, true); + mu_assert_true(rz_bv_is_all_one(bv), "set all 1 by set_range"); + // 11 1111 1111 1111 1100 0000 0011 1111 1111 1111 1111 + rz_bv_set_range(bv, 18, 25, false); + mu_assert_streq_free(rz_bv_as_hex_string(bv, false), "0x3fffc03ffff", "range set 18~25 to 0"); + rz_bv_free(bv); + + bv = rz_bv_new(16); + mu_assert_false(rz_bv_set_range(bv, 16, 20, true), "set out of range"); rz_bv_free(bv); mu_end; } @@ -1125,7 +1145,7 @@ bool all_tests() { mu_run_test(test_rz_bv_div); mu_run_test(test_rz_bv_mod); mu_run_test(test_rz_bv_len_bytes); - mu_run_test(test_rz_bv_set_all); + mu_run_test(test_rz_bv_set_operations); mu_run_test(test_rz_bv_set_to_bytes_le); mu_run_test(test_rz_bv_copy_nbits);