diff --git a/sk1/compressor.c b/sk1/compressor.c index 65137b0..c48d9ab 100644 --- a/sk1/compressor.c +++ b/sk1/compressor.c @@ -1,21 +1,140 @@ #include -int copy_file(const char *a, const char *b) +#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) { - FILE *x = fopen(a, "rb"); if (!x) return -1; - FILE *y = fopen(b, "wb"); if (!y) { fclose(x); return -1; } - int c, n = 0; - while ((c = fgetc(x)) != EOF) - { - fputc(c, y); - n++; + size_t compr_size = 0, sz=0; + FILE* input = fopen(input_file, "rb"); + FILE* output = fopen(output_file, "wb"); + + if (!input || !output) + { + exit(-1); } - fclose(x); - fclose(y); - return n; + + char window[WSIZE] = { 0 }; + char buffer[BSIZE] = { 0 }; + + int w_start = 0; + int w_end = 0; + + while (!feof(input)) + { + size_t 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) +{ + size_t 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 }; + 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; } -int compress_1(const char *a, const char *b){return copy_file(a,b);} -int compress_2(const char *a, const char *b){return copy_file(a,b);} -int decompress_1(const char *a, const char *b){return copy_file(a,b);} -int decompress_2(const char *a, const char *b){return copy_file(a,b);}