diff --git a/vlib/bitfield/bitfield.v b/vlib/bitfield/bitfield.v index d6a5d08855d70d..69c1e8f117915d 100644 --- a/vlib/bitfield/bitfield.v +++ b/vlib/bitfield/bitfield.v @@ -232,6 +232,85 @@ pub fn (mut instance BitField) toggle_bit(bitnr int) { instance.field[bitslot(bitnr)] ^= bitmask(bitnr) } +// set_if sets bit number 'bit_nr' to 1 (count from 0) if `cond` is true or clear the bit. +@[inline] +pub fn (mut instance BitField) set_if(cond bool, bitnr int) { + if bitnr >= instance.size { + return + } + if cond { + instance.field[bitslot(bitnr)] |= bitmask(bitnr) + } else { + instance.field[bitslot(bitnr)] &= ~bitmask(bitnr) + } +} + +// toggle_bits changes the value (from 0 to 1 or from 1 to 0) of bits +// Example: toggle_bits(1,3,5,7) +@[inline] +pub fn (mut instance BitField) toggle_bits(a ...int) { + for bitnr in a { + if bitnr >= instance.size { + return + } + instance.field[bitslot(bitnr)] ^= bitmask(bitnr) + } +} + +// set_bits sets multiple bits in the array to 1. +// Example: set_bits(1,3,5,7) +@[inline] +pub fn (mut instance BitField) set_bits(a ...int) { + for bitnr in a { + if bitnr >= instance.size { + return + } + instance.field[bitslot(bitnr)] |= bitmask(bitnr) + } +} + +// clear_bits clear multiple bits in the array to 0. +// Example: clear_bits(1,3,5,7) +@[inline] +pub fn (mut instance BitField) clear_bits(a ...int) { + for bitnr in a { + if bitnr >= instance.size { + return + } + instance.field[bitslot(bitnr)] &= ~bitmask(bitnr) + } +} + +// has test if *at least one* of the bits is set +// Example: has(1,3,5,7) +@[inline] +pub fn (mut instance BitField) has(a ...int) bool { + for bitnr in a { + if bitnr >= instance.size { + return false + } + if int((instance.field[bitslot(bitnr)] >> (bitnr % bitfield.slot_size)) & u32(1)) == 1 { + return true + } + } + return false +} + +// all test if *all* of the bits are set +// Example: all(1,3,5,7) +@[inline] +pub fn (mut instance BitField) all(a ...int) bool { + for bitnr in a { + if bitnr >= instance.size { + return false + } + if int((instance.field[bitslot(bitnr)] >> (bitnr % bitfield.slot_size)) & u32(1)) == 0 { + return false + } + } + return true +} + // bf_and performs logical AND operation on every pair of bits from 'input1' and // 'input2' and returns the result as a new array. If inputs differ in size, // the tail of the longer one is ignored. diff --git a/vlib/bitfield/bitfield_test.v b/vlib/bitfield/bitfield_test.v index 9bfadfbc019bb6..e1f0af36d177c2 100644 --- a/vlib/bitfield/bitfield_test.v +++ b/vlib/bitfield/bitfield_test.v @@ -14,6 +14,33 @@ fn test_bf_set_clear_toggle_get() { assert instance.get_bit(47) == 0 instance.toggle_bit(47) assert instance.get_bit(47) == 1 + instance.set_if(true, 48) + assert instance.get_bit(48) == 1 + instance.set_if(false, 48) + assert instance.get_bit(48) == 0 +} + +fn test_bf_multiple_flags() { + mut instance := bitfield.new(75) + + // 1,3,5,7,9 set + instance.set_bits(1, 3, 5, 7, 9) + assert instance.all(1, 3, 5, 7, 9) + assert instance.all(1, 3, 20) == false + assert instance.has(1, 20, 30, 40) + assert instance.has(20, 30, 40) == false + + // 1,3 set + instance.clear_bits(5, 7, 9) + assert instance.all(1, 3, 5, 7, 9) == false + assert instance.all(1, 3) + assert instance.has(3, 20, 30, 40) + + // 3,5,7 set + instance.toggle_bits(1, 5, 7) + assert instance.all(3, 5, 7) + assert instance.all(1, 3, 5, 7) == false + assert instance.has(5, 20, 30, 40) } fn test_bf_insert_extract() {