@@ -64,6 +64,7 @@ tests/msgfile/msgfile_test
tests/ussd/ussd_test
tests/smscb/smscb_test
tests/bits/bitrev_test
+tests/bits/bitvec_test
tests/a5/a5_test
tests/comp128/comp128_test
tests/auth/milenage_test
@@ -31,6 +31,7 @@
*/
#include <stdint.h>
+#include <stdbool.h>
/*! \brief A single GSM bit
*
@@ -58,10 +59,14 @@ int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnum,
enum bit_value bit);
int bitvec_set_bit(struct bitvec *bv, enum bit_value bit);
int bitvec_get_bit_high(struct bitvec *bv);
-int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count);
-int bitvec_set_uint(struct bitvec *bv, unsigned int in, int count);
-int bitvec_get_uint(struct bitvec *bv, int num_bits);
+int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, unsigned count);
+int bitvec_set_uint(struct bitvec *bv, unsigned int in, unsigned count);
+int bitvec_get_uint(struct bitvec *bv, unsigned num_bits);
int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, enum bit_value val);
int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit);
+void bitvec_print(struct bitvec *bv);
+void bitvec_zero(struct bitvec *bv);
+unsigned bitvec_rl(struct bitvec *bv, bool b);
+void bitvec_shiftl(struct bitvec *bv, unsigned n);
/*! @} */
@@ -30,7 +30,11 @@
#include <errno.h>
#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <osmocom/core/bits.h>
#include <osmocom/core/bitvec.h>
#define BITNUM_FROM_COMP(byte, bit) ((byte*8)+bit)
@@ -188,7 +192,7 @@ int bitvec_get_bit_high(struct bitvec *bv)
* \param[in] bits array of \ref bit_value
* \param[in] count number of bits to set
*/
-int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count)
+int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, unsigned count)
{
int i, rc;
@@ -202,7 +206,7 @@ int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count)
}
/*! \brief set multiple bits (based on numeric value) at current pos */
-int bitvec_set_uint(struct bitvec *bv, unsigned int ui, int num_bits)
+int bitvec_set_uint(struct bitvec *bv, unsigned int ui, unsigned num_bits)
{
int i, rc;
@@ -219,7 +223,7 @@ int bitvec_set_uint(struct bitvec *bv, unsigned int ui, int num_bits)
}
/*! \brief get multiple bits (based on numeric value) from current pos */
-int bitvec_get_uint(struct bitvec *bv, int num_bits)
+int bitvec_get_uint(struct bitvec *bv, unsigned num_bits)
{
int i;
unsigned int ui = 0;
@@ -261,4 +265,83 @@ int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n,
return -1;
}
+/*! \brief prints bit vector to stdout */
+void bitvec_print(struct bitvec *bv)
+{
+ unsigned i;
+ for (i = 0; i < bv->cur_bit; i++) {
+ if (0 == i % 8) printf(" ");
+ switch (bitvec_get_bit_pos(bv, i)) {
+ case ZERO: printf("0"); break;
+ case ONE: printf("1"); break;
+ case L: printf("L"); break;
+ case H: printf("H"); break;
+ }
+ }
+}
+
+/* we assume that x have at least 1 non-b bit */
+inline unsigned _leading_bits(uint8_t x, bool b)
+{
+ if (b) {
+ if (x < 0x80) return 0;
+ if (x < 0xC0) return 1;
+ if (x < 0xE0) return 2;
+ if (x < 0xF0) return 3;
+ if (x < 0xF8) return 4;
+ if (x < 0xFC) return 5;
+ if (x < 0xFE) return 6;
+ } else {
+ if (x > 0x7F) return 0;
+ if (x > 0x3F) return 1;
+ if (x > 0x1F) return 2;
+ if (x > 0xF) return 3;
+ if (x > 7) return 4;
+ if (x > 3) return 5;
+ if (x > 1) return 6;
+ }
+ return 7;
+}
+
+/*! \brief Return number (bits) of uninterrupted run of \b in \bv starting from the MSB */
+unsigned bitvec_rl(struct bitvec *bv, bool b)
+{
+ unsigned i;
+ for (i = 0; i < bv->data_len; i++) {
+ if ( (b ? 0xFF : 0) != bv->data[i]) return i * 8 + _leading_bits(bv->data[i], b);
+ }
+
+ return bv->cur_bit;
+}
+
+/*! \brief Shifts bitvec to the left, n MSB bits lost */
+void bitvec_shiftl(struct bitvec *bv, unsigned n)
+{
+ if (0 == n) return;
+ if (n >= bv->cur_bit) {
+ bitvec_zero(bv);
+ return;
+ }
+
+ memmove(bv->data, bv->data + n / 8, bv->data_len - n / 8);
+
+ uint8_t tmp[2];
+ unsigned i;
+ for (i = 0; i < bv->data_len - 2; i++) {
+ uint16_t t = osmo_load16be(bv->data + i);
+ osmo_store16be(t << (n % 8), &tmp);
+ bv->data[i] = tmp[0];
+ }
+
+ bv->data[bv->data_len - 1] <<= (n % 8);
+ bv->cur_bit -= n;
+}
+
+/*! \brief force bit vector to all 0 and current bit to the beginnig of the vector */
+void bitvec_zero(struct bitvec *bv)
+{
+ bv->cur_bit = 0;
+ memset(bv->data, 0, bv->data_len);
+}
+
/*! @} */
@@ -3,9 +3,9 @@ AM_CFLAGS = -Wall $(TALLOC_CFLAGS)
AM_LDFLAGS = $(TALLOC_LIBS)
check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \
- smscb/smscb_test bits/bitrev_test a5/a5_test \
+ smscb/smscb_test bits/bitrev_test bits/bitvec_test \
conv/conv_test auth/milenage_test lapd/lapd_test \
- gsm0808/gsm0808_test gsm0408/gsm0408_test \
+ gsm0808/gsm0808_test gsm0408/gsm0408_test a5/a5_test \
gb/bssgp_fc_test gb/gprs_bssgp_test gb/gprs_ns_test \
kasumi/kasumi_test logging/logging_test fr/fr_test \
loggingrb/loggingrb_test strrb/strrb_test \
@@ -37,6 +37,9 @@ auth_milenage_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/sr
bits_bitrev_test_SOURCES = bits/bitrev_test.c
bits_bitrev_test_LDADD = $(top_builddir)/src/libosmocore.la
+bits_bitvec_test_SOURCES = bits/bitvec_test.c
+bits_bitvec_test_LDADD = $(top_builddir)/src/libosmocore.la
+
conv_conv_test_SOURCES = conv/conv_test.c
conv_conv_test_LDADD = $(top_builddir)/src/libosmocore.la
@@ -112,7 +115,8 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \
timer/timer_test.ok sms/sms_test.ok ussd/ussd_test.ok \
- smscb/smscb_test.ok bits/bitrev_test.ok a5/a5_test.ok \
+ bits/bitrev_test.ok bits/bitvec_test.ok \
+ smscb/smscb_test.ok a5/a5_test.ok \
conv/conv_test.ok auth/milenage_test.ok \
lapd/lapd_test.ok gsm0408/gsm0408_test.ok \
gsm0808/gsm0808_test.ok gb/bssgp_fc_tests.err \
new file mode 100644
@@ -0,0 +1,43 @@
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+#include <stdbool.h>
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/bits.h>
+#include <osmocom/core/bitvec.h>
+
+int main(int argc, char **argv)
+{
+ srand(time(NULL));
+
+ struct bitvec bv;
+ uint8_t i = 8, test[i];
+
+ memset(test, 0, i);
+ bv.data_len = i;
+ bv.data = test;
+ bv.cur_bit = 0;
+
+ printf("checking RL functions...\n");
+
+ bitvec_zero(&bv); bitvec_print(&bv); printf(" RL0=%d, RL1=%d\n", bitvec_rl(&bv, false), bitvec_rl(&bv, true));
+ bitvec_set_uint(&bv, 0x000F, 32); bitvec_print(&bv); printf(" RL0=%d, RL1=%d\n", bitvec_rl(&bv, false), bitvec_rl(&bv, true));
+ bitvec_shiftl(&bv, 18); bitvec_print(&bv); printf(" RL0=%d, RL1=%d\n", bitvec_rl(&bv, false), bitvec_rl(&bv, true));
+ bitvec_set_uint(&bv, 0x0F, 8); bitvec_print(&bv); printf(" RL0=%d, RL1=%d\n", bitvec_rl(&bv, false), bitvec_rl(&bv, true));
+ bitvec_zero(&bv);
+ bitvec_set_uint(&bv, 0xFF, 8); bitvec_print(&bv); printf(" RL0=%d, RL1=%d\n", bitvec_rl(&bv, false), bitvec_rl(&bv, true));
+ bitvec_set_uint(&bv, 0xFE, 7); bitvec_print(&bv); printf(" RL0=%d, RL1=%d\n", bitvec_rl(&bv, false), bitvec_rl(&bv, true));
+
+ printf("test shifting...\n");
+
+ bitvec_set_uint(&bv, 0x0E, 7); bitvec_print(&bv); printf(" << 3:\n"); bitvec_shiftl(&bv, 3); bitvec_print(&bv); printf("\n");
+ bitvec_print(&bv); printf(" << 17:\n"); bitvec_shiftl(&bv, 17); bitvec_print(&bv); printf("\n");
+ bitvec_set_uint(&bv, 0, 32); bitvec_set_uint(&bv, 0x0A, 7);
+ bitvec_print(&bv); printf(" << 24:\n"); bitvec_shiftl(&bv, 24); bitvec_print(&bv); printf("\n");
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,14 @@
+checking RL functions...
+ RL0=0, RL1=0
+ 00000000 00000000 00000000 00001111 RL0=28, RL1=0
+ 00000000 001111 RL0=10, RL1=0
+ 00000000 00111100 001111 RL0=10, RL1=0
+ 11111111 RL0=0, RL1=8
+ 11111111 1111110 RL0=0, RL1=14
+test shifting...
+ 11111111 11111100 001110 << 3:
+ 11111111 11100001 110
+ 11111111 11100001 110 << 17:
+ 10
+ 10000000 00000000 00000000 00000000 00000101 0 << 24:
+ 00000000 00000101 0
@@ -21,6 +21,12 @@ cat $abs_srcdir/bits/bitrev_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/bits/bitrev_test], [0], [expout])
AT_CLEANUP
+AT_SETUP([bitvec])
+AT_KEYWORDS([bitvec])
+cat $abs_srcdir/bits/bitvec_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/bits/bitvec_test], [0], [expout])
+AT_CLEANUP
+
AT_SETUP([conv])
AT_KEYWORDS([conv])
cat $abs_srcdir/conv/conv_test.ok > expout