witam, mam prośbę do kogoś kto choć odrobinę ogarnia C (ja niestety wcale) o wytłumaczenie działania małego fragmentu kodu, gdyż zamierzam jego funkcjonalność zaimplementować w pythonie, który znam.
oto kod:
/*
* unlzs.c
*
* Created on: 10/10/2013
* Author: alguien
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
char get_bit(char *data, int *offset, int *index) {
char abyte;
abyte = (data[*index] & (1 << (7 - *offset))) >> (7 - *offset);
(*offset)++;
if (*offset == 8) {
(*index)++;
*offset = 0;
}
return abyte;
}
char *get_nbits(int nbits, char *data, int *offset, int *index) {
char *bytes;
int nbytes = (nbits % 8) ? nbits / 8 + 1 : nbits / 8;
int boffset = (nbits % 8) ? 8 - nbits % 8 : 0;
int bindex = 0;
bytes = malloc(sizeof(char) * nbytes);
bzero(bytes, sizeof(char) * nbytes);
int i;
char bit;
for (i = 0; i < nbits; i++) {
bit = get_bit(data, offset, index);
bytes[bindex] = bytes[bindex] | ((bit << 7) >> boffset);
boffset++;
if (boffset == 8) {
bindex++;
boffset = 0;
}
}
return bytes;
}
int is_endmarker(char *data, int *offset, int *index) {
int end = 0;
int offset_tmp = *offset, index_tmp = *index;
char *bytes = get_nbits(2, data, offset, index);
if (bytes[0] == (char) 3) {
bytes = get_nbits(7, data, offset, index);
if (bytes[0] == (char) 0) {
end = 1;
}
}
*offset = offset_tmp;
*index = index_tmp;
return end;
}
char *uncompress_lzs(char *data) {
int data_offset = 0, data_index = 0;
char abyte, *bytes;
char *history = malloc(sizeof(char) * 2048);
int hindex = 0;
bzero(history, sizeof(char) * 2048);
while (1) {
abyte = get_bit(data, &data_offset, &data_index);
if (abyte == (char) 0) {
// raw pattern
bytes = get_nbits(8, data, &data_offset, &data_index);
history[hindex] = bytes[0];
hindex++;
} else {
// string pattern
int sp_offset = 0;
abyte = get_bit(data, &data_offset, &data_index);
if (abyte == (char) 0) {
// offset > 127
bytes = get_nbits(11, data, &data_offset, &data_index);
char aux = bytes[0];
bytes[0] = bytes[1];
bytes[1] = aux;
sp_offset = *((short *) bytes);
} else {
// offset <= 127
bytes = get_nbits(7, data, &data_offset, &data_index);
sp_offset = *((char *) bytes);
}
int sp_length = 0;
bytes = get_nbits(2, data, &data_offset, &data_index);
if (bytes[0] != 3) {
// length <= 4
sp_length = ((int) bytes[0]) + 2;
} else {
bytes = get_nbits(2, data, &data_offset, &data_index);
if (bytes[0] != 3) {
// length <= 7
sp_length = ((int) bytes[0]) + 5;
} else {
// length > 7
int n = 0;
while (1) {
bytes = get_nbits(4, data, &data_offset, &data_index);
if (bytes[0] == (char) 15) {
n++;
} else {
break;
}
}
sp_length = (n * 15) + ((int) bytes[0]) + 8;
}
}
// copiar patron
int count = 0;
for (count = 0; count < sp_length; count++) {
history[hindex] = history[hindex - sp_offset];
//printf("%c\n", history[hindex]);
hindex++;
}
}
if (is_endmarker(data, &data_offset, &data_index) == 1) {
// end marker
break;
}
}
return history;
}
int main(int argc, char **argv) {
if( argc == 0) {
printf("Modo de uso: %s <data.lzs>\n", argv[0]);
return -1;
}
FILE *file = NULL;
file = fopen(argv[1], "rb");
if (!file) {
printf("Error. No se puede abrir el archivo.\n");
return -1;
}
char *data = malloc(sizeof(char) * 2048);
fread(data, sizeof(char), 2048, file);
fclose(file);
char *uncompress = uncompress_lzs(data);
int count;
for (count = 0; count < 2048; count++) {
printf("%c", uncompress[count]);
}
return 0;
}