main.c
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <zlib.h>
#define MAX_BUF_SIZE (32 * 1024 * 1024)
char lz[MAX_BUF_SIZE] = {0};
char file[MAX_BUF_SIZE] = {0};
char unlz[MAX_BUF_SIZE] = {0};
uint32_t lz77_compress(uint8_t *src, uint32_t slen, uint8_t *dst)
{
uint8_t plen = 0, tlen = 0;
uint16_t ppos = 0, tpos = 0, optr = 0;
uint32_t cptr = 0, osize = 0, cpos = 0, oref = 0, lkb = 0, lka = 0;
*((uint32_t*)dst) = slen;
cptr = osize = 4;
for (cpos = 0; cpos < slen; cpos++) {
ppos = 0;
plen = 0;
for (tpos = 1; (tpos < 4096) && (tpos <= cpos); tpos++) {
lkb = cpos - tpos;
lka = cpos;
for (tlen = 0; src[lka++] == src[lkb++]; tlen++) {
if (tlen == 15) {
break;
}
}
if (tlen > plen) {
ppos = tpos;
plen = tlen;
if (plen == 15) {
break;
}
}
}
cpos += plen;
if (plen && (cpos == slen)) {
optr = (ppos << 4) | (plen - 1);
oref = cpos - 1;
}
else {
optr = (ppos << 4) | plen;
oref = cpos;
}
*((uint32_t*)(dst + cptr)) = optr;
cptr += 2;
*(dst + cptr++) = *(src + oref);
osize += 3;
}
return osize;
}
uint32_t lz77_decompress(uint8_t *src, uint8_t *dst)
{
uint8_t plen = 0;
uint16_t iptr = 0, ppos = 0;
uint32_t cptr = 0, cpos = 0, poff = 0, usize = 0;
usize = *((uint32_t*)src);
cptr = 4;
for (cpos = 0; cpos < usize; cpos++) {
iptr = *((uint32_t*)(src + cptr));
cptr += 2;
ppos = iptr >> 4;
plen = iptr & 15;
if (ppos) {
for (poff = cpos - ppos; plen > 0; plen--) {
dst[cpos++] = dst[poff++];
}
}
*(dst + cpos) = *(src + cptr++);
}
return cpos;
}
int main(int argc, char **argv)
{
int r = 0;
int fd = -1;
fd = open("test.bin", O_RDONLY);
r = read(fd, file, sizeof(file));
close(fd);
printf("file length: %d\n", r);
r = lz77_compress(file, r, lz);
fd = open("test.lz77", O_CREAT | O_WRONLY, 0644);
write(fd, lz, r);
close(fd);
printf("compress length: %d\n", r);
r = lz77_decompress(lz, unlz);
fd = open("test.unlz77", O_CREAT | O_WRONLY, 0644);
write(fd, unlz, r);
close(fd);
printf("decompress length: %d\n", r);
return 0;
}
編譯、執行
$ gcc main.c -o main
$ echo "123" > test.bin
$ ./main
file length: 4
compress length: 16
decompress length: 4
$ cat test.unlz77
123