Add rz_bv_append_inplace() (#6592)

Warning: this also swaps the arguments of the old rz_bv_append() to be
consistend with the new inplace variant.
The reason why the inplace function has the low as the first operand is
that it can be more efficient to append to an existing vector inplace
than to prepend to it. Then, the first argument is being used as the
in-out one in all other inplace functions.
This commit is contained in:
Florian Märkl 2026-07-03 17:31:30 +02:00 committed by GitHub
parent 22ce81d719
commit ff4d6608c0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 26 additions and 7 deletions

View file

@ -134,7 +134,7 @@ void *rz_il_handler_append(RzILVM *vm, RzILOpBitVector *op, RzILTypePure *type)
RzBitVector *high = rz_il_evaluate_bitv(vm, op_append->high);
RzBitVector *low = rz_il_evaluate_bitv(vm, op_append->low);
RzBitVector *result = high && low ? rz_bv_append(high, low) : NULL;
RzBitVector *result = high && low ? rz_bv_append(low, high) : NULL;
rz_bv_free(low);
rz_bv_free(high);

View file

@ -40,7 +40,8 @@ typedef struct bitvector_t {
RZ_API bool rz_bv_init(RZ_NONNULL RzBitVector *bv, ut32 length);
RZ_API RZ_OWN RzBitVector *rz_bv_new(ut32 length);
RZ_API RZ_OWN RzBitVector *rz_bv_dup(const RZ_NONNULL RzBitVector *bv);
RZ_API RZ_OWN RzBitVector *rz_bv_append(RZ_NONNULL RzBitVector *bv1, RZ_NONNULL RzBitVector *bv2);
RZ_API RZ_OWN RzBitVector *rz_bv_append(RZ_NONNULL const RzBitVector *low, RZ_NONNULL const RzBitVector *high);
RZ_API void rz_bv_append_inplace(RZ_INOUT RZ_NONNULL RzBitVector *low, RZ_NONNULL const RzBitVector *high);
RZ_API ut32 rz_bv_copy(RZ_NONNULL RzBitVector *dst, RZ_NONNULL const RzBitVector *src);
RZ_API ut32 rz_bv_copy_nbits(
RZ_NONNULL RzBitVector *dst, ut32 dst_start_pos,

View file

@ -601,19 +601,31 @@ RZ_API RZ_OWN RzBitVector *rz_bv_cut_tail(RZ_NONNULL RzBitVector *bv, ut32 delta
}
/**
* Append bv2 to bv1 to get new bitvector
* \param high bitvector to occupy the most significant part of the result
* Append high to low to get new bitvector
* \param low bitvector to occupy the least significant part of the result
* \param high bitvector to occupy the most significant part of the result
* \return ret RzBitVector, the new bitvector
*/
RZ_API RZ_OWN RzBitVector *rz_bv_append(RZ_NONNULL RzBitVector *high, RZ_NONNULL RzBitVector *low) {
rz_return_val_if_fail(high && low, NULL);
RZ_API RZ_OWN RzBitVector *rz_bv_append(RZ_NONNULL const RzBitVector *low, RZ_NONNULL const RzBitVector *high) {
rz_return_val_if_fail(low && high, NULL);
RzBitVector *ret = rz_bv_new(high->len + low->len);
rz_bv_copy_nbits(ret, 0, low, 0, low->len);
rz_bv_copy_nbits(ret, low->len, high, 0, high->len);
return ret;
}
/**
* Append high to low to get new bitvector
* \param low bitvector to occupy the least significant part of the result, and pointer to write the result to
* \param high bitvector to occupy the most significant part of the result
*/
RZ_API void rz_bv_append_inplace(RZ_INOUT RZ_NONNULL RzBitVector *low, RZ_NONNULL const RzBitVector *high) {
rz_return_if_fail(low && low);
ut32 low_len = low->len;
rz_bv_cast_inplace(low, low->len + high->len, false);
rz_bv_copy_nbits(low, low_len, high, 0, high->len);
}
/**
* Set a bit at position to true or false
* \param bv RzBitVector, pointer to bv

View file

@ -724,7 +724,7 @@ bool test_rz_bv_operation(void) {
mu_assert_streq_free(s, "0x0", "string hex value of bv");
rz_bv_free(res);
res = rz_bv_append(x, y);
res = rz_bv_append(y, x);
mu_assert("append x and y", is_equal_bv(res, concat));
s = rz_bv_as_string(res);
mu_assert_streq_free(s, "000010001011", "string bit value of bv");
@ -732,6 +732,12 @@ bool test_rz_bv_operation(void) {
mu_assert_streq_free(s, "0x08b", "string hex value of bv");
rz_bv_free(res);
res = rz_bv_new_from_ut64(4, 0x5);
rz_bv_append_inplace(res, x);
s = rz_bv_as_hex_string(res, true);
mu_assert_streq_free(s, "0x085", "string hex value of bv");
rz_bv_free(res);
rz_bv_free(prep);
rz_bv_free(append);
rz_bv_free(cut_h);