aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/bitvec.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2009-12-14 22:04:31 +0100
committerHarald Welte <laforge@gnumonks.org>2009-12-14 22:04:31 +0100
commitd57f163bd4040cddf59cb145affba2c2d2570c42 (patch)
tree2077e28f687804a223e749b4c4bb5e8f31f65856 /openbsc/src/bitvec.c
parentda760d3d19bc6da3ef676a2fbaa65fb841cd5af5 (diff)
bitvec updates and code simplification
* introduce a new bitvec_get_bit_pos() function to determine the bit value at a given position inside a bit vector * make sure bitvec_{get,set}_bit_pos() share code as possible
Diffstat (limited to 'openbsc/src/bitvec.c')
-rw-r--r--openbsc/src/bitvec.c49
1 files changed, 40 insertions, 9 deletions
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;