mirror of https://gerrit.osmocom.org/libosmocore
380 lines
8.9 KiB
C
380 lines
8.9 KiB
C
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <stdbool.h>
|
|
#include <errno.h>
|
|
|
|
#include <osmocom/core/utils.h>
|
|
#include <osmocom/core/bitvec.h>
|
|
#include <osmocom/core/bits.h>
|
|
|
|
static char lol[1024]; // we pollute this with printed vectors
|
|
static inline void test_rl(const struct bitvec *bv)
|
|
{
|
|
bitvec_to_string_r(bv, lol);
|
|
printf("%s [%d] RL0=%d, RL1=%d\n", lol, bv->cur_bit, bitvec_rl(bv, false), bitvec_rl(bv, true));
|
|
}
|
|
|
|
static inline void test_shift(struct bitvec *bv, unsigned n)
|
|
{
|
|
bitvec_to_string_r(bv, lol);
|
|
printf("%s << %d:\n", lol, n);
|
|
bitvec_shiftl(bv, n);
|
|
bitvec_to_string_r(bv, lol);
|
|
printf("%s\n", lol);
|
|
}
|
|
|
|
static inline void test_get(struct bitvec *bv, unsigned n)
|
|
{
|
|
bitvec_to_string_r(bv, lol);
|
|
printf("%s [%d]", lol, bv->cur_bit);
|
|
int16_t x = bitvec_get_int16_msb(bv, n);
|
|
uint8_t tmp[2];
|
|
osmo_store16be(x, &tmp);
|
|
printf(" -> %d (%u bit) ["OSMO_BIN_SPEC" "OSMO_BIN_SPEC"]:\n", x, n, OSMO_BIN_PRINT(tmp[0]), OSMO_BIN_PRINT(tmp[1]));
|
|
bitvec_to_string_r(bv, lol);
|
|
printf("%s [%d]\n", lol, bv->cur_bit);
|
|
}
|
|
|
|
static inline void test_fill(struct bitvec *bv, unsigned n, enum bit_value val)
|
|
{
|
|
bitvec_to_string_r(bv, lol);
|
|
unsigned bvlen = bv->cur_bit;
|
|
int fi = bitvec_fill(bv, n, val);
|
|
printf("%c> FILL %s [%d] -%d-> [%d]:\n", bit_value_to_char(val), lol, bvlen, n, fi);
|
|
bitvec_to_string_r(bv, lol);
|
|
printf(" %s [%d]\n\n", lol, bv->cur_bit);
|
|
}
|
|
|
|
static inline void test_spare(struct bitvec *bv, unsigned n)
|
|
{
|
|
bitvec_to_string_r(bv, lol);
|
|
unsigned bvlen = bv->cur_bit;
|
|
int sp = bitvec_spare_padding(bv, n);
|
|
printf("%c> SPARE %s [%d] -%d-> [%d]:\n", bit_value_to_char(L), lol, bvlen, n, sp);
|
|
bitvec_to_string_r(bv, lol);
|
|
printf(" %s [%d]\n\n", lol, bv->cur_bit);
|
|
}
|
|
|
|
static inline void test_set(struct bitvec *bv, enum bit_value bit)
|
|
{
|
|
bitvec_to_string_r(bv, lol);
|
|
unsigned bvlen = bv->cur_bit;
|
|
int set = bitvec_set_bit(bv, bit);
|
|
printf("%c> SET %s [%d] ++> [%d]:\n", bit_value_to_char(bit), lol, bvlen, set);
|
|
bitvec_to_string_r(bv, lol);
|
|
printf(" %s [%d]\n\n", lol, bv->cur_bit);
|
|
}
|
|
|
|
static void test_byte_ops(void)
|
|
{
|
|
struct bitvec bv;
|
|
const uint8_t *in = (const uint8_t *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
uint8_t out[26 + 2];
|
|
uint8_t data[64];
|
|
int i;
|
|
int rc;
|
|
int in_size = strlen((const char *)in);
|
|
|
|
printf("=== start %s ===\n", __func__);
|
|
|
|
bv.data = data;
|
|
bv.data_len = sizeof(data);
|
|
|
|
for (i = 0; i < 32; i++) {
|
|
/* Write to bitvec */
|
|
memset(data, 0x00, sizeof(data));
|
|
bv.cur_bit = i;
|
|
rc = bitvec_set_uint(&bv, 0x7e, 8);
|
|
OSMO_ASSERT(rc >= 0);
|
|
rc = bitvec_set_bytes(&bv, in, in_size);
|
|
OSMO_ASSERT(rc >= 0);
|
|
rc = bitvec_set_uint(&bv, 0x7e, 8);
|
|
OSMO_ASSERT(rc >= 0);
|
|
|
|
printf("bitvec: %s\n", osmo_hexdump(bv.data, bv.data_len));
|
|
|
|
/* Read from bitvec */
|
|
memset(out, 0xff, sizeof(out));
|
|
bv.cur_bit = i;
|
|
rc = bitvec_get_uint(&bv, 8);
|
|
OSMO_ASSERT(rc == 0x7e);
|
|
rc = bitvec_get_bytes(&bv, out + 1, in_size);
|
|
OSMO_ASSERT(rc >= 0);
|
|
rc = bitvec_get_uint(&bv, 8);
|
|
OSMO_ASSERT(rc == 0x7e);
|
|
|
|
printf("out: %s\n", osmo_hexdump(out, sizeof(out)));
|
|
|
|
OSMO_ASSERT(out[0] == 0xff);
|
|
OSMO_ASSERT(out[in_size+1] == 0xff);
|
|
OSMO_ASSERT(memcmp(in, out + 1, in_size) == 0);
|
|
}
|
|
|
|
printf("=== end %s ===\n", __func__);
|
|
}
|
|
|
|
static void test_unhex(const char *hex)
|
|
{
|
|
int rc;
|
|
struct bitvec b;
|
|
uint8_t d[64] = {0};
|
|
b.data = d;
|
|
b.data_len = sizeof(d);
|
|
b.cur_bit = 0;
|
|
|
|
rc = bitvec_unhex(&b, hex);
|
|
printf("%d -=> cur_bit=%u\n", rc, b.cur_bit);
|
|
printf("%s\n", osmo_hexdump_nospc(d, 64));
|
|
printf("%s\n", hex);
|
|
}
|
|
|
|
static inline void test_array_item(unsigned t, struct bitvec *b, unsigned int n,
|
|
uint32_t *array, unsigned int p)
|
|
{
|
|
unsigned int i, x, y;
|
|
bitvec_zero(b);
|
|
x = b->cur_bit;
|
|
i = bitvec_add_array(b, array, n, true, t);
|
|
y = b->cur_bit;
|
|
bitvec_add_array(b, array, n, false, t);
|
|
printf("\nbits: %u, est: %u, real: %u, x: %u, y: %u\n",
|
|
t, i, b->cur_bit, x, y);
|
|
for (i = 0; i < p; i++) {
|
|
printf(OSMO_BIT_SPEC " ", OSMO_BIT_PRINT(b->data[i]));
|
|
if (0 == (i + 1) % 15)
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
static inline void test_bitvec_rl_curbit(struct bitvec *bv, bool b, int max_bits,
|
|
int result )
|
|
{
|
|
int num = 0;
|
|
int readIndex = bv->cur_bit;
|
|
OSMO_ASSERT(bv->cur_bit < max_bits);
|
|
num = bitvec_rl_curbit(bv, b, max_bits);
|
|
readIndex += num;
|
|
OSMO_ASSERT(bv->cur_bit == readIndex);
|
|
OSMO_ASSERT(num == result);
|
|
}
|
|
|
|
static void test_array(void)
|
|
{
|
|
struct bitvec b;
|
|
uint8_t d[4096];
|
|
b.data = d;
|
|
b.data_len = sizeof(d);
|
|
|
|
unsigned int i, n = 64;
|
|
uint32_t array[n];
|
|
for (i = 0; i < n; i++) {
|
|
array[i] = i * i * i + i;
|
|
printf("0x%x ", array[i]);
|
|
}
|
|
|
|
test_array_item(3, &b, n, array, n);
|
|
test_array_item(9, &b, n, array, n * 2);
|
|
test_array_item(17, &b, n, array, n * 3);
|
|
}
|
|
|
|
static void test_used_bytes(void)
|
|
{
|
|
struct bitvec b;
|
|
uint8_t d[32];
|
|
unsigned int i;
|
|
|
|
b.data = d;
|
|
b.data_len = sizeof(d);
|
|
bitvec_zero(&b);
|
|
|
|
OSMO_ASSERT(bitvec_used_bytes(&b) == 0);
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
bitvec_set_bit(&b, 1);
|
|
OSMO_ASSERT(bitvec_used_bytes(&b) == 1);
|
|
}
|
|
|
|
for (i = 8; i < 16; i++) {
|
|
bitvec_set_bit(&b, 1);
|
|
OSMO_ASSERT(bitvec_used_bytes(&b) == 2);
|
|
}
|
|
}
|
|
|
|
static void test_tailroom(void)
|
|
{
|
|
struct bitvec b;
|
|
uint8_t d[32];
|
|
unsigned int i;
|
|
|
|
b.data = d;
|
|
b.data_len = sizeof(d);
|
|
bitvec_zero(&b);
|
|
|
|
OSMO_ASSERT(bitvec_tailroom_bits(&b) == sizeof(d)*8);
|
|
|
|
for (i = 0; i < 8*sizeof(d); i++) {
|
|
bitvec_set_bit(&b, 1);
|
|
OSMO_ASSERT(bitvec_tailroom_bits(&b) == sizeof(d)*8-(i+1));
|
|
}
|
|
}
|
|
|
|
static void test_bitvec_read_field(void)
|
|
{
|
|
uint8_t data[8] = { 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xeb, 0xda, 0xed };
|
|
struct bitvec bv = {
|
|
.data_len = sizeof(data),
|
|
.data = data,
|
|
.cur_bit = 0,
|
|
};
|
|
|
|
unsigned int readIndex;
|
|
uint64_t field;
|
|
|
|
#define _bitvec_read_field(idx, len) \
|
|
readIndex = idx; \
|
|
field = bitvec_read_field(&bv, &readIndex, len); \
|
|
printf("bitvec_read_field(idx=%u, len=%u) => %" PRIx64 " (%s)\n", \
|
|
idx, len, field, errno == 0 ? "success" : "error");
|
|
|
|
_bitvec_read_field(0, 64);
|
|
_bitvec_read_field(0, 32);
|
|
_bitvec_read_field(0, 16);
|
|
_bitvec_read_field(0, 8);
|
|
_bitvec_read_field(0, 0);
|
|
|
|
_bitvec_read_field(8, 8);
|
|
_bitvec_read_field(8, 4);
|
|
_bitvec_read_field(8, 0);
|
|
|
|
_bitvec_read_field(10, 9);
|
|
_bitvec_read_field(10, 7);
|
|
_bitvec_read_field(10, 5);
|
|
_bitvec_read_field(10, 3);
|
|
_bitvec_read_field(10, 1);
|
|
|
|
/* Out of bounds (see OS#4388) */
|
|
_bitvec_read_field(8 * 8 * 8, 16); /* index too far */
|
|
_bitvec_read_field(0, 8 * 8 + 1); /* too many bits */
|
|
_bitvec_read_field(8 * 8, 16); /* 16 bits past */
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
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("test shifting...\n");
|
|
|
|
bitvec_set_uint(&bv, 0x0E, 7);
|
|
test_shift(&bv, 3);
|
|
test_shift(&bv, 17);
|
|
bitvec_set_uint(&bv, 0, 32);
|
|
bitvec_set_uint(&bv, 0x0A, 7);
|
|
test_shift(&bv, 24);
|
|
|
|
printf("checking RL functions...\n");
|
|
|
|
bitvec_zero(&bv);
|
|
test_rl(&bv);
|
|
bitvec_set_uint(&bv, 0x000F, 32);
|
|
test_rl(&bv);
|
|
bitvec_shiftl(&bv, 18);
|
|
test_rl(&bv);
|
|
bitvec_set_uint(&bv, 0x0F, 8);
|
|
test_rl(&bv);
|
|
bitvec_zero(&bv);
|
|
bitvec_set_uint(&bv, 0xFF, 8);
|
|
test_rl(&bv);
|
|
bitvec_set_uint(&bv, 0xFE, 7);
|
|
test_rl(&bv);
|
|
bitvec_set_uint(&bv, 0, 17);
|
|
test_rl(&bv);
|
|
bitvec_shiftl(&bv, 18);
|
|
test_rl(&bv);
|
|
|
|
printf("probing bit access...\n");
|
|
|
|
bitvec_zero(&bv);
|
|
bitvec_set_uint(&bv, 0x3747817, 32);
|
|
bitvec_shiftl(&bv, 10);
|
|
|
|
test_get(&bv, 2);
|
|
test_get(&bv, 7);
|
|
test_get(&bv, 9);
|
|
test_get(&bv, 13);
|
|
test_get(&bv, 16);
|
|
test_get(&bv, 42);
|
|
|
|
printf("feeling bit fills...\n");
|
|
|
|
test_set(&bv, ONE);
|
|
test_fill(&bv, 3, ZERO);
|
|
test_spare(&bv, 38);
|
|
test_spare(&bv, 43);
|
|
test_spare(&bv, 1);
|
|
test_spare(&bv, 7);
|
|
test_fill(&bv, 5, ONE);
|
|
test_fill(&bv, 3, L);
|
|
|
|
printf("byte me...\n");
|
|
|
|
test_byte_ops();
|
|
test_unhex("48282407a6a074227201000b2b2b2b2b2b2b2b2b2b2b2b");
|
|
test_unhex("47240c00400000000000000079eb2ac9402b2b2b2b2b2b");
|
|
test_unhex("47283c367513ba333004242b2b2b2b2b2b2b2b2b2b2b2b");
|
|
test_unhex("DEADFACE000000000000000000000000000000BEEFFEED");
|
|
test_unhex("FFFFFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
|
|
|
|
printf("arrr...\n");
|
|
|
|
test_array();
|
|
|
|
printf("\nbitvec_runlength....\n");
|
|
|
|
bitvec_zero(&bv);
|
|
bitvec_set_uint(&bv, 0xff, 8);
|
|
bv.cur_bit -= 8;
|
|
test_bitvec_rl_curbit(&bv, 1, 64, 8);
|
|
|
|
bitvec_zero(&bv);
|
|
bitvec_set_uint(&bv, 0xfc, 8);
|
|
bv.cur_bit -= 8;
|
|
test_bitvec_rl_curbit(&bv, 1, 64, 6);
|
|
|
|
bitvec_zero(&bv);
|
|
test_bitvec_rl_curbit(&bv, 0, 52, 52);
|
|
|
|
bitvec_zero(&bv);
|
|
bitvec_set_uint(&bv, 0xfc, 8);
|
|
bv.cur_bit -= 2;
|
|
test_bitvec_rl_curbit(&bv, 0, 64, 58);
|
|
|
|
bitvec_zero(&bv);
|
|
bitvec_set_uint(&bv, 0x07, 8);
|
|
bitvec_set_uint(&bv, 0xf8, 8);
|
|
bv.cur_bit -= 11;
|
|
test_bitvec_rl_curbit(&bv, 1, 64, 8);
|
|
|
|
bitvec_zero(&bv);
|
|
test_bitvec_rl_curbit(&bv, 1, 64, 0);
|
|
|
|
printf("\nbitvec bytes used.\n");
|
|
test_used_bytes();
|
|
test_tailroom();
|
|
|
|
printf("\ntest bitvec_read_field():\n");
|
|
test_bitvec_read_field();
|
|
|
|
printf("\nbitvec ok.\n");
|
|
return 0;
|
|
}
|