Files
sdrpp/core/libcorrect/src/convolutional/bit.c
2021-10-02 17:01:23 +02:00

233 lines
5.5 KiB
C

#include "correct/convolutional/bit.h"
bit_writer_t *bit_writer_create(uint8_t *bytes, size_t len) {
bit_writer_t *w = calloc(1, sizeof(bit_writer_t));
if (bytes) {
bit_writer_reconfigure(w, bytes, len);
}
return w;
}
void bit_writer_reconfigure(bit_writer_t *w, uint8_t *bytes, size_t len) {
w->bytes = bytes;
w->len = len;
w->current_byte = 0;
w->current_byte_len = 0;
w->byte_index = 0;
}
void bit_writer_destroy(bit_writer_t *w) {
free(w);
}
void bit_writer_write(bit_writer_t *w, uint8_t val, unsigned int n) {
for (size_t j = 0; j < n; j++) {
bit_writer_write_1(w, val);
val >>= 1;
}
}
void bit_writer_write_1(bit_writer_t *w, uint8_t val) {
w->current_byte |= val & 1;
w->current_byte_len++;
if (w->current_byte_len == 8) {
// 8 bits in a byte -- move to the next byte
w->bytes[w->byte_index] = w->current_byte;
w->byte_index++;
w->current_byte_len = 0;
w->current_byte = 0;
} else {
w->current_byte <<= 1;
}
}
void bit_writer_write_bitlist(bit_writer_t *w, uint8_t *l, size_t len) {
// first close the current byte
// we might have been given too few elements to do that. be careful.
size_t close_len = 8 - w->current_byte_len;
close_len = (close_len < len) ? close_len : len;
uint16_t b = w->current_byte;
for (ptrdiff_t i = 0; i < close_len; i++) {
b |= l[i];
b <<= 1;
}
l += close_len;
len -= close_len;
uint8_t *bytes = w->bytes;
size_t byte_index = w->byte_index;
if (w->current_byte_len + close_len == 8) {
b >>= 1;
bytes[byte_index] = b;
byte_index++;
} else {
w->current_byte = b;
w->current_byte_len += close_len;
return;
}
size_t full_bytes = len/8;
for (size_t i = 0; i < full_bytes; i++) {
bytes[byte_index] = l[0] << 7 | l[1] << 6 | l[2] << 5 |
l[3] << 4 | l[4] << 3 | l[5] << 2 |
l[6] << 1 | l[7];
byte_index += 1;
l += 8;
}
len -= 8*full_bytes;
b = 0;
for (ptrdiff_t i = 0; i < len; i++) {
b |= l[i];
b <<= 1;
}
w->current_byte = b;
w->byte_index = byte_index;
w->current_byte_len = len;
}
void bit_writer_write_bitlist_reversed(bit_writer_t *w, uint8_t *l, size_t len) {
l = l + len - 1;
uint8_t *bytes = w->bytes;
size_t byte_index = w->byte_index;
uint16_t b;
if (w->current_byte_len != 0) {
size_t close_len = 8 - w->current_byte_len;
close_len = (close_len < len) ? close_len : len;
b = w->current_byte;
for (ptrdiff_t i = 0; i < close_len; i++) {
b |= *l;
b <<= 1;
l--;
}
len -= close_len;
if (w->current_byte_len + close_len == 8) {
b >>= 1;
bytes[byte_index] = b;
byte_index++;
} else {
w->current_byte = b;
w->current_byte_len += close_len;
return;
}
}
size_t full_bytes = len/8;
for (size_t i = 0; i < full_bytes; i++) {
bytes[byte_index] = l[0] << 7 | l[-1] << 6 | l[-2] << 5 |
l[-3] << 4 | l[-4] << 3 | l[-5] << 2 |
l[-6] << 1 | l[-7];
byte_index += 1;
l -= 8;
}
len -= 8*full_bytes;
b = 0;
for (ptrdiff_t i = 0; i < len; i++) {
b |= *l;
b <<= 1;
l--;
}
w->current_byte = (uint8_t)b;
w->byte_index = byte_index;
w->current_byte_len = len;
}
void bit_writer_flush_byte(bit_writer_t *w) {
if (w->current_byte_len != 0) {
w->current_byte <<= (8 - w->current_byte_len);
w->bytes[w->byte_index] = w->current_byte;
w->byte_index++;
w->current_byte_len = 0;
}
}
size_t bit_writer_length(bit_writer_t *w) {
return w->byte_index;
}
uint8_t reverse_byte(uint8_t b) {
return (b & 0x80) >> 7 | (b & 0x40) >> 5 | (b & 0x20) >> 3 |
(b & 0x10) >> 1 | (b & 0x08) << 1 | (b & 0x04) << 3 |
(b & 0x02) << 5 | (b & 0x01) << 7;
}
static uint8_t reverse_table[256];
void create_reverse_table() {
for (uint16_t i = 0; i < 256; i++) {
reverse_table[i] = reverse_byte(i);
}
}
bit_reader_t *bit_reader_create(const uint8_t *bytes, size_t len) {
bit_reader_t *r = calloc(1, sizeof(bit_reader_t));
static bool reverse_table_created = false;
if (!reverse_table_created) {
create_reverse_table();
reverse_table_created = true;
}
if (bytes) {
bit_reader_reconfigure(r, bytes, len);
}
return r;
}
void bit_reader_reconfigure(bit_reader_t *r, const uint8_t *bytes, size_t len) {
r->bytes = bytes;
r->len = len;
r->current_byte_len = 8;
r->current_byte = bytes[0];
r->byte_index = 0;
}
void bit_reader_destroy(bit_reader_t *r) {
free(r);
}
uint8_t bit_reader_read(bit_reader_t *r, unsigned int n) {
unsigned int read = 0;
unsigned int n_copy = n;
if (r->current_byte_len < n) {
read = r->current_byte & ((1 << r->current_byte_len) - 1);
r->byte_index++;
r->current_byte = r->bytes[r->byte_index];
n -= r->current_byte_len;
r->current_byte_len = 8;
read <<= n;
}
uint8_t copy_mask = (1 << n) - 1;
copy_mask <<= (r->current_byte_len - n);
read |= (r->current_byte & copy_mask) >> (r->current_byte_len - n);
r->current_byte_len -= n;
return reverse_table[read] >> (8 - n_copy);
}