#include #include #define WSIZE 250 #define BSIZE 50 typedef struct { unsigned char pos; unsigned char n; char symb; } LZ77Token; int compress_1(const char* input_file, const char* output_file) { int compr_size = 0, sz = 0; FILE* input = fopen(input_file, "rb"); FILE* output = fopen(output_file, "wb"); if (!input || !output) { exit(-1); } char window[WSIZE] = { 0 }; char buffer[BSIZE] = { 0 }; int w_start = 0; int w_end = 0; while (!feof(input)) { int blen = fread(buffer, 1, BSIZE, input); for (int bpos = 0; bpos < blen; ++bpos) { int best_pos = 0; int best_n = 0; for (int spos = w_start; spos < w_end; ++spos) { int mlength = 0; while (mlength < blen - bpos && mlength < WSIZE && (spos + mlength) < w_end && window[(spos + mlength) % WSIZE] == buffer[bpos + mlength]) { ++mlength; } if (mlength > best_n) { best_pos = w_end - spos; best_n = mlength; } } LZ77Token token; token.pos = best_pos; token.n = best_n; if (bpos + best_n < blen) { token.symb = buffer[bpos + best_n]; } else { token.symb = '\0'; } sz=fwrite(&token, sizeof(LZ77Token), 1, output); compr_size += sizeof(LZ77Token) * sz; for (int j = 0; j <= best_n && bpos < blen; ++j) { if (bpos + j < blen) { window[w_end % WSIZE] = buffer[bpos + j]; w_end++; if (w_end - w_start > WSIZE) { w_start++; } } } bpos += best_n; } } fclose(input); fclose(output); return compr_size; } int decompress_1(const char* input_file, const char* output_file) { int compr_size = 0; FILE* input = fopen(input_file, "rb"); FILE* output = fopen(output_file, "wb"); if (!input || !output) { exit(-1); } char window[WSIZE] = { 0 }; int window_end = 0; LZ77Token token; while (fread(&token, sizeof(LZ77Token), 1, input)) { if (token.pos == 0 && token.n == 0 && token.symb == '\0') { continue; } int start_index = (window_end - token.pos + WSIZE) % WSIZE; for (int i = 0; i < token.n; ++i) { char ch = window[(start_index + i) % WSIZE]; compr_size += fwrite(&ch, 1, 1, output); window[window_end % WSIZE] = ch; window_end = (window_end + 1) % WSIZE; } if (token.symb != '\0') { compr_size += fwrite(&token.symb, 1, 1, output); window[window_end % WSIZE] = token.symb; window_end = (window_end + 1) % WSIZE; } } fclose(input); fclose(output); return compr_size; }