Listing 5 (cujhuff4.c)

      /****************************************************
      *
      *       file d:\lsu\cujhuff4.c
      *
      ***************************************************/

#include "d:\lsu\cujhuff.h"

/*
   decode_compressed_file(...

   This is the main function of the decompression
   portion of the program.

*/

decode_compressed_file (input_file_name, output_file_name,
                    item_array, file_header)
  char   input_file_name[], output_file_name[];
  struct item_struct item_array[];
  struct header_struct *file_header;
{
  char r[80];
  int  in_file_desc,
      out_file_desc;

  open_files_for_decode(input_file_name, output_file_name,
                    &in_file_desc, &out_file_desc};

  input_file_header(file_header, in_file_desc);
  convert_short_to_long(item_array, file_header);

  decode_file_and_write_output (item_array,
                           in_file_desc,
                           out_file_desc);

  close_decode_files(in_file_desc, out_file_desc);

}  /* ends decode_compressed_file */

/*
        open_files_for_decode(...

        Open the input end output file.
*/

open_files_for_decode(in_file_name, out_file_name,
                  in_file_desc, out_file_desc)
   char in_file_name[], out_file_name[],
   int  *in_file_desc, *out_file_desc;
{
   int a ,b;

   *out_file_desc = open(out_file_name, 0_RDWR | 0_CREAT | 0_BINARY,
                      S_IWRITE);
   *in_file_desc  = open(in_file_name, 0_RDWR | 0_CREAT | 0_BINARY,
                      S_IWRITE);

}  /* ends open_files_for_decode          */

/*
        input_file_header( file_header, in_file_desc)

        This function reads in the short header from the
        front of the input file.
*/


input_file_header( file_header, in_file_desc)
  int in_file_desc;
  struct header_struct *file_header;
{
      int     bytes_read,
             i;

      char    in_buffer[(sizeof(struct header_struct))],
             *charptr,
             name[80];

      long  position;


      position   = lseek(in_file_desc, 0L, 0);
      bytes_read = my_read(in_file_desc, in_buffer,
                        sizeof(struct header_struct));
/*printf("\n\n> Read %d bytes using file header", bytes_read);*/

      charptr = (char *)file_header;
      for(i=0; i<((sizeof(struct header_struct))); i++)
         *charptr++ = in_buffer[i];

}      /* ends input_item_array */

/*

       decode_file_and write_output(...

       This function takes in the packed bits, decodes them,
       and puts the decoded characters out to the output
       file.

/*

decode_file_and_write_output(item_array, in_file_desc, out_file_desc)
   int    in_file_desc, out_file_desc;
   struct item_struct item_array[];
{
   char  output_buffer[IB_LENGTH],
        r[80],
        stream_buffer[CODE_LENGTH],
        stream_of_bits[OB_LENGTH];

   int   bytes_read,
        counter
        i,
        in_disp,
        not_finished,
        output_pointer,
        stream_pointer;
   counter        = 0;
   output_pointer = 0;
   stream_pointer  = 0;
   bytes_read     = 0;
   not_finished   = 1;

   for(i=0; i<IB_LENGTH; i++)
      output_buffer[i] = OTHER;

   while(not_finished){

      read_in_buffer(in_file_desc, in_disp,
                   stream_of_bits, &bytes_read);

/*printf("\n> read %d bytes into stream of bits", bytes_read);*/
     stream_pointer = 0;

     if(bytes_read < OB_LENGTH)
        not_finished = 0;

        /* work through the stream_of_bits
           you're finished when the stream_pointer
           equals bytes_read * 8 bits per byte. */

     while(stream_pointer < bytes_read*8){
        convert_bits_to_char(stream_of_bits, stream_pointer,
                            stream_buffer);

        decode_bits(stream_buffer, item_array,
                  output_buffer, &output_pointer,
                  &stream_pointer);

/*printf("\n> stream pointer = %d", stream_pointer);*/
          /* if output_buffer fills up write it to disk */
        if(output_pointer >= IB_LENGHT-10){
           counter++;
           printf("\n> Writing to output file-%d", counter);
           write_out_buffer(out_file_desc,
                         output_buffer,
                         output_pointer);
           output_pointer = 0;
        }   /* ends if output pointer is too big */
      }     /* ends while stream_pointer < bytes_read*8 */

   }   /* ends while not_finished */

   if(output_pointer > 0) {
        printf ("\n> Writing to output file");
        write_out_buffer(out_file_desc, output_buffer, output_pointer);
   }

}   /* ends decode_file_and_write_output */


/*
         read_in_buffer(...

         This function reads the input file and puts the packed
         bits into the stream_of_bits.
*/

read_in_buffer(in_file_desc, in_disp, stream_of_bits,
             bytes_read)
   int  *bytes_read, in_file_desc, in_disp;
   char stream_of_bits[];
{
   int b;

   for(b=0; b<OB_LENGTH; b++)
      stream_of_bits[b] = 0x00;

   *bytes_read = read(in_file_desc, stream_of_bits, OB_LENGTH);

}   /* ends read_in_buffer */


/*
         convert_bits_to_char(...

         This function takes the next CODE_LENGTH # of bits
         from the stream_of_bits and converts them to bytes
         having the value ONE or ZERO. These bytes are placed
         into the stream_buffer. This makes it easier for
         the decode bits function to compare coded with the
         packed bits.
*/


convert_bits_to_char(stream_of_bits, stream_pointer, stream_buffer)
   char  stream_of_bits[], stream_buffer[];
   int   stream_pointer;
{
   char  temp;

   int  bit_in_byte,
       byte_in_buffer,
       i,
       j;

   for(i=0; i<CODE_LENGTH; i++)
      stream_buffer[i] = OTHER;

   j = -1:

   for(i=stream_pointer; i<stream_pointer+CODE_LENGTH; i++){

      j++;
      bit_in_byte    = i % 8;
      byte_in_buffer = i/8;

         /* Test the bit by shifting it to the left
            by the number bit_in_byte and then ANDing
            it with 1000 0000 (128).
            For this routine bit zero is the left most
            or most significant bit of temp */

      temp = stream_of_bits[byte_in buffer];
      temp = temp << bit_in_byte;
      if((temp & SET_BIT_ZERO) != 0)
         stream_buffer[j] = ONE;
      else
         stream_buffer[j] = ZERO;

   }   /* ends loop over i */

}   /* ends convert_bits_to_char */

/*
         decode_bits(...

         Look at the converted bits from the packed file
         compare them to the item_array.coded (start looking
         at the top of the item_array since those occur most
         frequently) and put the original character in the
         output buffer
*/

decode_bits(stream_buffer, item_array,
          output_buffer, output_pointer,
          stream_pointer)
   char output_buffer[], stream_buffer[];
   int *output_pointer, *stream_pointer;
   struct item_struct item_array[];
{
   int   found,
        j,
        i,
        length_of_code,
        not_finished;

   char  compare_string[CODE_LENGTH], r[80];

   found        = 0;
   not_finished = 1;
   j            = 0;

      /* search through the item_array looking for a coded array that
         matches the characters in the stream_buffer
         If you find it, increase the stream_pointer by
         adding length_of_code to it. */

   while(not_finished){

      extract_code(item_array[j].coded, compare_string, &length_of_code);

      if(strncmp (compare_string,
                stream_buffer,
                length_of_code) == 0){
         found          = 1;
         not_finished   = 0;
         *stream_pointer = *stream_pointer + length_of_code;
      }   /* ends if strncmp */

     else{ /* did not find the code so keep looking */
        j++;
        if(j > LENGTH){
          not_finished = 0;
          printf("\n\n\t> FAILURE - did not find code\n\n");
        }
      }  /* ends else */

   }   /* ends while not_finished */

      /* now put the decoded character in to the output_buffer */

   if(found == 1){
      output_buffer[*output_pointer] = item_array[j].character;
      *output_pointer = *output_pointer + 1;
   }   /* ends if found == 1 */

}   /* ends decode_bits */

/*
           extract_code(...

           Pull the code out of item_array[x].coded,
           put it into compare_string, and put the
           length of the code into length.
*/

extract_code(coded, compare_string, length_of_code}
   char coded[], compare_string[];
   int *length_of_code;
{
   int i, j, k, m, not_finished;

      /* clear the compare string */
   for(k=0; k<CODE LENGTH; k++)
      compare_string[k] = OTHER;

   not_finished    = 1;
   *length_of_code = 0;
   i               = CODE_LENGTH-1;
   j               = 0;

      /* Start at the end of coded and search back until you
         run out of code i.e. you hit a OTHER. */

   while(not_finished){
      if(coded[i] != OTHER){
         i-;
         j++;
      }
      else
         not_finished = 0;
   }   /* ends while not_finished */

      /* adjust value of i */
   i++;

      /* Copy the coded to the compare_string */
   *length_of_code = j;
   m       = 0;
   for(k=i; k<CODE_LENGTH; k++){
      compare_string[m] = coded[k];
      m++;
   }

}   /* ends extract_code */

/*
         write_out_buffer(...

         Write the output_buffer to file.
*/

write_out_buffer(out_file_desc, output_buffer, output_pointer)
   char output_buffer[];
   int out_file_desc, output_pointer;
{
   int bytes_written;

   bytes_written =
    my_write(out_file_desc, output_buffer, output_pointer);
}   /* ends write_out_buffer */


/*
         close_decode_files(...

         Close the files.
*/

close_decode_files(in_file_desc, out_file_desc)
   int in_file_desc, out_file_desc;
{

   close(in_file_desc);
   close (out_file_desc);

}  /* ends close_decode_files */

/* End of File */