Listing 3 TESTRDC.C
/* TESTRDC.C - Ross Data Compression (RDC) * test driver program * * Written by Ed Ross, 1/92 * * This program will compress or decompress a file * using RDC data compression. */ #include <stdlib.h> #include <stdio.h> #include <stdarg.h> #include <string.h> #define HASH_LEN 4096 /* # hash table entries */ #define BUFF_LEN 16384 /* size of disk io buffer */ typedef unsigned char uchar; /* 8 bits, unsigned */ typedef unsigned int uint; /* 16 bits, unsigned */ uchar *hash_tbl[HASH_LEN]; /* hash table */ uchar inbuff[BUFF_LEN]; /* io buffers */ uchar outbuff[BUFF_LEN]; FILE *infile, *outfile; /* FILE access */ char usage[] = "\nUsage: TESTRDC <c | d> <infile> <outfile>\n" " c = compress infile to outfile\n" " d = decompress infile to outfile\n"; /* compression function prototypes */ int rdc_compress(uchar *inbuff, uint inbuff_len, uchar *outbuff, uchar *hash_tbl[], uint hash_len); int rdc_decompress(uchar *inbuff, uint inbuff_len, uchar *outbuff); /*--- post error message and exit ---*/ void err_exit(char *fmt, ...) { va_list v; va_start(v, fmt); vfprintf(stderr, fmt, v); va_end(v); exit(1); } /*--- compress infile to outfile ---*/ void do_compress(void) { int bytes_read; int compress_len; /* read infile BUFF_LEN bytes at a time */ while ((bytes_read = fread(inbuff, 1, BUFF_LEN, infile)) > 0) { /* compress this load of bytes */ compress_len = rdc_compress(inbuff, bytes_read, outbuff, hash_tbl, HASH_LEN); /* write length of compressed buffer */ if (fwrite(&compress_len, sizeof(int), 1, outfile) != 1) err_exit("Error writing block length.\n"); /*check for negative length indicating the buffer could not be compressed */ if (compress_len < 0) compress_len = 0 - compress_len; /* write the buffer */ if (fwrite(outbuff, compress_len, 1, outfile) != 1) err_exit("Error writing compressed data.\n"); /* we're done if less than full buffer was read */ if (bytes_read != BUFF_LEN) break; } /* add trailer to indicate end of file */ compress_len = 0; if (fwrite(&compress_len, sizeof(int), 1, outfile) != 1) err_exit("Error writing trailer.\n"); } /*--- decompress infile to outfile ---*/ void do_decompress(void) { int block_len; int decomp_len; /* read infile BUFF_LEN bytes at a time */ for (;;) { if (fread(&block_len, sizeof(int), 1, infile) != 1) err_exit("Can't read block length.\n"); /* check for end-of-file flag */ if (block_len == 0) return; if (block_len < 0) /* copy uncompressed chars */ { decomp_len = 0 - block_len; if (fread(outbuff, decomp_len, 1, infile) != 1) err_exit("Can't read uncompressed block.\n"); } else /* decompress this buffer */ { if (fread(inbuff, block_len, 1, infile) != 1) err_exit("Can't read compressed block.\n"); decomp_len = rdc_decompress(inbuff, block_len, outbuff); } /* and write this buffer outfile */ if (fwrite(outbuff, decomp_len, 1, outfile) != 1) err_exit("Error writing uncompressed data.\n"); } } /*--- main ---*/ void main(int argc, char *argv[]) { /* check command line */ if (argc != 4) err_exit(usage); /* open the files */ if ((infile = fopen(argv[2], "rb")) == NULL) err_exit("Can't open %s for input.\n", argv[2]); if ((outfile : fopen(argv[3], "wb")) == NULL) err_exit("Can't open %s for output.\n", argv[3]); /* dispatch to requested function */ switch (argv[1] [0]) { case 'c': case 'C': do_compress(); break; case 'd': case 'D': do_decompress(); break; default: err_exit(usage); } /* and close the files */ if (fclose(infile)) err_exit("Error closing input file.\n"); if (fclose(outfile)) err_exit("Error closing output file.\n"); } /* End of File */