Files
c_progarm/lzw-ab/lzwfilter.ctt
2023-12-02 11:52:15 +08:00

192 lines
5.6 KiB
Plaintext

////////////////////////////////////////////////////////////////////////////
// **** LZW-AB **** //
// Adjusted Binary LZW Compressor/Decompressor //
// Copyright (c) 2016-2020 David Bryant //
// All Rights Reserved //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <fcntl.h>
#endif
#include "lzwlib.h"
/* This module provides a command-line filter for testing the lzw library.
* It can also optionally calculate and display the compression ratio and
* a simple checksum for informational purposes. Other command-line
* arguments select decoding mode or the maximum symbol size (9 to 16 bits)
* for encoding.
*/
static const char *usage =
" Usage: lzwfilter [-options] [< infile] [> outfile]\n\n"
" Operation: compression is default, use -d to decompress\n\n"
" Options: -d = decompress\n"
" -h = display this \"help\" message\n"
" -1 = maximum symbol size = 9 bits\n"
" -2 = maximum symbol size = 10 bits\n"
" -3 = maximum symbol size = 11 bits\n"
" -4 = maximum symbol size = 12 bits\n"
" -5 = maximum symbol size = 13 bits\n"
" -6 = maximum symbol size = 14 bits\n"
" -7 = maximum symbol size = 15 bits\n"
" -8 = maximum symbol size = 16 bits (default)\n"
" -v = verbose (display ratio and checksum)\n\n"
" Web: Visit www.github.com/dbry/lzw-ab for latest version and info\n\n";
typedef struct {
unsigned char buffer [65536];
int checksum, head, tail;
size_t byte_count;
} streamer;
static int read_buff (void *ctx)
{
streamer *stream = ctx;
int value;
if (stream->head == stream->tail)
stream->tail = (stream->head = 0) + fread (stream->buffer, 1, sizeof (stream->buffer), stdin);
if (stream->head < stream->tail) {
value = stream->buffer [stream->head++];
stream->checksum = stream->checksum * 3 + (unsigned char) value;
stream->byte_count++;
}
else
value = EOF;
return value;
}
static void write_buff (int value, void *ctx)
{
streamer *stream = ctx;
if (value == EOF) {
fwrite (stream->buffer, 1, stream->head, stdout);
return;
}
stream->buffer [stream->head++] = value;
if (stream->head == sizeof (stream->buffer)) {
fwrite (stream->buffer, 1, stream->head, stdout);
stream->head = 0;
}
stream->checksum = stream->checksum * 3 + (unsigned char) value;
stream->byte_count++;
}
int main (int argc, char **argv)
{
int decompress = 0, maxbits = 16, verbose = 0, error = 0;
streamer reader, writer;
memset (&reader, 0, sizeof (reader));
memset (&writer, 0, sizeof (writer));
reader.checksum = writer.checksum = -1;
while (--argc) {
if ((**++argv == '-') && (*argv)[1])
while (*++*argv)
switch (**argv) {
case '1':
maxbits = 9;
break;
case '2':
maxbits = 10;
break;
case '3':
maxbits = 11;
break;
case '4':
maxbits = 12;
break;
case '5':
maxbits = 13;
break;
case '6':
maxbits = 14;
break;
case '7':
maxbits = 15;
break;
case '8':
maxbits = 16;
break;
case 'D': case 'd':
decompress = 1;
break;
case 'H': case 'h':
fprintf (stderr, "%s", usage);
return 0;
break;
case 'V': case 'v':
verbose = 1;
break;
default:
fprintf (stderr, "illegal option: %c !\n", **argv);
error = 1;
break;
}
else {
fprintf (stderr, "unknown argument: %s\n", *argv);
error = 1;
}
}
if (error) {
fprintf (stderr, "%s", usage);
return 0;
}
#ifdef _WIN32
setmode (fileno (stdin), O_BINARY);
setmode (fileno (stdout), O_BINARY);
#endif
if (decompress) {
if (lzw_decompress (write_buff, &writer, read_buff, &reader)) {
fprintf (stderr, "lzw_decompress() returned non-zero!\n");
return 1;
}
write_buff (EOF, &writer);
if (verbose && writer.byte_count)
fprintf (stderr, "output checksum = %x, ratio = %.2f%%\n", writer.checksum, reader.byte_count * 100.0 / writer.byte_count);
}
else {
if (lzw_compress (write_buff, &writer, read_buff, &reader, maxbits)) {
fprintf (stderr, "lzw_compress() returned non-zero!\n");
return 1;
}
write_buff (EOF, &writer);
if (verbose && reader.byte_count)
fprintf (stderr, "source checksum = %x, ratio = %.2f%%\n", reader.checksum, writer.byte_count * 100.0 / reader.byte_count);
}
return 0;
}