diff options
-rw-r--r-- | openbsc/include/openbsc/bitvec.h | 3 | ||||
-rw-r--r-- | openbsc/src/bitvec.c | 49 |
2 files changed, 43 insertions, 9 deletions
diff --git a/openbsc/include/openbsc/bitvec.h b/openbsc/include/openbsc/bitvec.h index 80ed4ad0a..a365e2a2d 100644 --- a/openbsc/include/openbsc/bitvec.h +++ b/openbsc/include/openbsc/bitvec.h @@ -39,6 +39,9 @@ struct bitvec { u_int8_t *data; /* pointer to data array */ }; +/* check if the bit is 0 or 1 for a given position inside a bitvec */ +enum bit_value bitvec_get_bit_pos(struct bitvec *bv, unsigned int bitnr); + /* Set a bit at given position */ int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnum, enum bit_value bit); diff --git a/openbsc/src/bitvec.c b/openbsc/src/bitvec.c index ac2554475..8c82b8776 100644 --- a/openbsc/src/bitvec.c +++ b/openbsc/src/bitvec.c @@ -35,15 +35,10 @@ static inline unsigned int bytenum_from_bitnum(unsigned int bitnum) return bytenum; } -int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr, - enum bit_value bit) +/* convert ZERO/ONE/L/H to a bitmask at given pos in a byte */ +static u_int8_t bitval2mask(enum bit_value bit, u_int8_t bitnum) { - unsigned int bytenum = bytenum_from_bitnum(bitnr); - unsigned int bitnum = 7 - (bitnr % 8); - u_int8_t bitval; - - if (bytenum >= bv->data_len) - return -EINVAL; + int bitval; switch (bit) { case ZERO: @@ -59,8 +54,41 @@ int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr, bitval = ((0x2b ^ (1 << bitnum)) & (1 << bitnum)); break; default: - return -EINVAL; + return 0; } + return bitval; +} + +/* check if the bit is 0 or 1 for a given position inside a bitvec */ +enum bit_value bitvec_get_bit_pos(struct bitvec *bv, unsigned int bitnr) +{ + unsigned int bytenum = bytenum_from_bitnum(bitnr); + unsigned int bitnum = 7 - (bitnr % 8); + u_int8_t bitval; + + if (bytenum >= bv->data_len) + return -EINVAL; + + bitval = bitval2mask(ONE, bitnum); + + if (bv->data[bytenum] & bitval) + return ONE; + + return ZERO; +} + +/* set the bit at a given position inside a bitvec */ +int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr, + enum bit_value bit) +{ + unsigned int bytenum = bytenum_from_bitnum(bitnr); + unsigned int bitnum = 7 - (bitnr % 8); + u_int8_t bitval; + + if (bytenum >= bv->data_len) + return -EINVAL; + + bitval = bitval2mask(ONE, bitnum); /* first clear the bit */ bv->data[bytenum] &= ~(1 << bitnum); @@ -71,6 +99,7 @@ int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr, return 0; } +/* set the next bit inside a bitvec */ int bitvec_set_bit(struct bitvec *bv, enum bit_value bit) { int rc; @@ -82,6 +111,7 @@ int bitvec_set_bit(struct bitvec *bv, enum bit_value bit) return rc; } +/* set multiple bits (based on array of bitvals) at current pos */ int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count) { int i, rc; @@ -95,6 +125,7 @@ int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count) return 0; } +/* set multiple bits (based on numeric value) at current pos */ int bitvec_set_uint(struct bitvec *bv, unsigned int ui, int num_bits) { int i, rc; |