/*----------------------------------------------------------------------*/
/*              File I/O module for LHarc UNIX                          */
/*                                                                      */
/*              Copyright(C) MCMLXXXIX  Yooichi.Tagawa                  */
/*                                                                      */
/*  V0.00  Original                             1989.06.25  Y.Tagawa    */
/*  V1.02  Fixed memory problems with copy()    1990.06.24  FvKempen    */
/*----------------------------------------------------------------------*/

#include <stdio.h>

#include "lhio.h"

#       define BUFFER_SIZE      16384

FILE            *crc_infile, *crc_outfile;      /* in lzhuf.c */

/* These functions are NO-RETURN */
extern void read_error ();
extern long count;
extern int  ForceReturn;
extern long WinSiz;
extern long TotSiz;
extern long cursize;
extern char *BfrPtr;
extern int  NotInterruptedCall;


int             crc_getc_cashe;
unsigned int    crc_value;
unsigned int    crc_table[0x100];
long            crc_size;
long            BufrCnt = 0;


static void
crcsub (ptr, length)
     char *ptr;
     register int length;
{
  register unsigned char *p;
  register unsigned int ctmp;

  if (length != 0)
    {
      ctmp = crc_value;
      p = (unsigned char*)ptr;
      for (; length; length --)
        {
          ctmp ^= (unsigned int)*p++;
          ctmp = (ctmp >> 8) ^ crc_table [ ctmp & 0xff ];
        }
      crc_value = ctmp;
    }
}

void
putc_crc (c)
     int c;
{
  CRC_CHAR (c);
  *(BfrPtr + BufrCnt) = c;
  TotSiz = BufrCnt + 1;
  if(( TotSiz % WinSiz) == 0 ) { ForceReturn = 1; BufrCnt = 0; }
  else                         { BufrCnt++; }
}

int
getc_crc ()
{
  int c;

  if (crc_getc_cashe != EOF)
    {
      c = crc_getc_cashe;
      crc_getc_cashe = EOF;
      CRC_CHAR (c);
      crc_size++;
    }
  else if ((c = getc (crc_infile)) != EOF)
    {
      CRC_CHAR (c);
      crc_size++;
    }
  return c;
}

void
init_crc ()
{
  static int inited = 0;
  register unsigned int *p = crc_table;
  register int i, j;
  register unsigned int x;

  if (!inited) {
    for (j = 0; j < 256; j ++) {
      x = j;
      for (i = 0; i < 8; i ++) {
        if ((x & 1) != 0) {
          x = (x >> 1) ^ 0xa001;
        } else {
          x = (x >> 1);
        }
      }
      *p ++ = x;
    }
    inited = 1;
  }
  crc_value = 0;
  crc_getc_cashe = EOF;
  crc_size = 0;
}

/*----------------------------------------------------------------------*/
/*                                                                      */
/*----------------------------------------------------------------------*/

/* if return value is -1, see errno */
static void
copy_binary_file (ifp, size, crc_flag)
     FILE *ifp;
     long size;
     int crc_flag;      /* as boolean value */
{
  static int read_size;
  static int n;

  if( !NotInterruptedCall ) NotInterruptedCall = 1;

  read_size = ((cursize < WinSiz) ? (int)cursize : WinSiz);

  n = fread (BfrPtr, sizeof (char), read_size, ifp);
  if (n < 0)
     read_error ();

  TotSiz = n;

  if (crc_flag)
     crcsub (BfrPtr, n);

  cursize -= (long)n;

  if( cursize > 0 ) ForceReturn = 1;
}

/*----------------------------------------------------------------------*/
/*                                                                      */
/*----------------------------------------------------------------------*/


int
decode_stored_crc (ifp, original_size, name)
     FILE *ifp;
     long original_size;
     char *name;
{
  if( NotInterruptedCall ) init_crc ();

  copy_binary_file (ifp, original_size, 1);
  return crc_value;
}

int
decode_stored_nocrc (ifp, original_size, name)
     FILE *ifp;
     long original_size;
     char *name;
{
  copy_binary_file (ifp, original_size, 0);
  return 0;                     /* DUMMY */
}
