osmo-pcu/src/egprs_rlc_compression.cpp

314 lines
6.3 KiB
C++

/* egprs_rlc_compression.h
* Routines for EGPRS RLC bitmap compression handling
*/
#include <egprs_rlc_compression.h>
#include <errno.h>
#include <decoding.h>
egprs_compress *egprs_compress::s_instance = 0;
Node *egprs_compress::ones_list = NULL;
Node *egprs_compress::zeros_list = NULL;
void egprs_compress::build_codeword(Node *root, const char *cdwd[])
{
Node *iter; /* iterate the node on the tree */
int len; /* length of the code word */
int i; /* iterater */
uint16_t idx; /* interate index of the code word table */
root->left = NULL;
root->right = NULL;
root->run_length = NULL;
for (idx = 0; idx < MAX_CDWDTBL_LEN; idx++) {
len = strlen((const char *)cdwd[idx]);
iter = root;
for (i = 0; i < len; i++) {
if (cdwd[idx][i] == '0') {
if (iter->left == NULL) {
iter->left = (Node *)malloc(sizeof(Node));
/* create a clean node */
iter->left->left = NULL;
iter->left->right = NULL;
iter->left->run_length = NULL;
}
iter = iter->left;
} else if (cdwd[idx][i] == '1') {
if (iter->right == NULL) {
iter->right = (Node *)malloc(sizeof(Node));
/* create a clean node */
iter->right->left = NULL;
iter->right->right = NULL;
iter->right->run_length = NULL;
}
iter = iter->right;
}
}
if (iter != NULL) {
iter->run_length = (uint16_t *)malloc(sizeof(uint16_t));
*(iter->run_length) = (uint16_t)NULL;
if (idx < 64)
*(iter->run_length) = idx;
else
*(iter->run_length) = (idx - 63) * 64;
}
}
}
const char *one_run_len_code_list[MAX_CDWDTBL_LEN] = {
"00110101",
"000111",
"0111",
"1000",
"1011",
"1100",
"1110",
"1111",
"10011",
"10100",
"00111",
"01000",
"001000",
"000011",
"110100",
"110101",
"101010",
"101011",
"0100111",
"0001100",
"0001000",
"0010111",
"0000011",
"0000100",
"0101000",
"0101011",
"0010011",
"0100100",
"0011000",
"00000010",
"00000011",
"00011010",
"00011011",
"00010010",
"00010011",
"00010100",
"00010101",
"00010110",
"00010111",
"00101000",
"00101001",
"00101010",
"00101011",
"00101100",
"00101101",
"00000100",
"00000101",
"00001010",
"00001011",
"01010010",
"01010011",
"01010100",
"01010101",
"00100100",
"00100101",
"01011000",
"01011001",
"01011010",
"01011011",
"01001010",
"01001011",
"00110010",
"00110011",
"00110100",
"11011",
"10010",
"010111",
"0110111",
"00110110",
"00110111",
"01100100",
"01100101",
"01101000",
"01100111",
"011001100",
"011001101",
"011010010",
"011010011",
"011010100"
};
const char *zero_run_len_code_list[MAX_CDWDTBL_LEN] = {
"0000110111",
"10",
"11",
"010",
"011",
"0011",
"0010",
"00011",
"000101",
"000100",
"0000100",
"0000101",
"0000111",
"00000100",
"00000111",
"000011000",
"0000010111",
"0000011000",
"0000001000",
"00001100111",
"00001101000",
"00001101100",
"00000110111",
"00000101000",
"00000010111",
"00000011000",
"000011001010",
"000011001011",
"000011001100",
"000011001101",
"000001101000",
"000001101001",
"000001101010",
"000001101011",
"000011010010",
"000011010011",
"000011010100",
"000011010101",
"000011010110",
"000011010111",
"000001101100",
"000001101101",
"000011011010",
"000011011011",
"000001010100",
"000001010101",
"000001010110",
"000001010111",
"000001100100",
"000001100101",
"000001010010",
"000001010011",
"000000100100",
"000000110111",
"000000111000",
"000000100111",
"000000101000",
"000001011000",
"000001011001",
"000000101011",
"000000101100",
"000001011010",
"000001100110",
"000001100111",
"0000001111",
"000011001000",
"000011001001",
"000001011011",
"000000110011",
"000000110100",
"000000110101",
"0000001101100",
"0000001101101",
"0000001001010",
"0000001001011",
"0000001001100",
"0000001001101",
"0000001110010",
"0000001110011"
};
int search_runlen(
Node *root, /* root of Ones or Zeros tree */
const uint8_t *bmbuf, /* Received compressed bitmap buf */
uint8_t bit_pos, /* the start bit pos to read codeword */
uint8_t *len_codewd, /* length of code word */
uint16_t *rlen)
{
Node *iter;
uint8_t dir;
iter = root;
*len_codewd = 0;
while (iter->run_length == 0) {
if ((iter->left == NULL) && (iter->right == NULL))
return -1;
/* get the bit value at the bitpos and put it in right most of dir */
dir = ((bmbuf[BITS_TO_BYTES(bit_pos)-1]
>>(7-(MOD8(bit_pos)))) & 0x01);
(bit_pos)++;
(*len_codewd)++;
if (((dir&0x01) == 0) && (iter->left != NULL))
iter = iter->left;
else if (((dir&0x01) == 1) && (iter->right != NULL))
iter = iter->right;
else
return -1;
}
(*rlen) = *(iter->run_length);
return 1;
} /* search_runlen */
void Decoding::decompress_crbb(
int8_t compress_bmap_len, /* compressed bitmap length */
uint8_t clr_code_bit, /* run length of Ones or Zeros */
const uint8_t *orig_crbb_buf, /* received block crbb bitmap */
bitvec * dest)
{
uint8_t bit_pos = 0;
uint8_t nbits = 0; /* number of bits of codeword */
uint16_t run_length = 0;
uint16_t cbmaplen = 0; /* compressed bitmap part after decompression */
unsigned wp = dest->cur_bit;
egprs_compress *compress = egprs_compress::instance();
while (compress_bmap_len > 0) {
if (clr_code_bit == 1) {
search_runlen(compress->ones_list, orig_crbb_buf,
bit_pos, &nbits, &run_length);
/*If run length > 64, need makeup and terminating code*/
if (run_length < 64)
clr_code_bit = 0;
cbmaplen = cbmaplen + run_length;
/* put run length of Ones in uncompressed bitmap */
while (run_length != 0) {
if (run_length > 8) {
bitvec_write_field(dest, wp, 0xff, 8);
run_length = run_length - 8;
} else {
bitvec_write_field(dest, wp, 0xff,
run_length);
run_length = 0;
}
}
} else {
search_runlen(compress->zeros_list, orig_crbb_buf,
bit_pos, &nbits, &run_length);
/*If run length > 64, need makeup and terminating code*/
if (run_length < 64)
clr_code_bit = 1;
cbmaplen = cbmaplen + run_length;
/* put run length of Zeros in uncompressed bitmap */
while (run_length != 0) {
if (run_length > 8) {
bitvec_write_field(dest, wp, 0x00, 8);
run_length = run_length - 8;
} else {
bitvec_write_field(dest, wp, 0x00,
run_length);
run_length = 0;
}
}
}
bit_pos = bit_pos + nbits;
compress_bmap_len = compress_bmap_len - nbits;
}
} /* Decompress_CRBB */