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 */