/*$Source: /usr/home/dhesi/zoo/RCS/io.c,v $*/
/*$Id: io.c,v 1.14 91/07/09 01:39:54 dhesi Exp $*/
/***********************************************************
   io.c -- input/output

Adapted from "ar" archiver written by Haruhiko Okumura.
***********************************************************/

/*

Adapted from "zoo" written by Rahul Dhesi

-- Matthias Meixner

*/

#include "ar.h"
#include "lzh.h"

#include <stdlib.h>
#include <string.h>

#include "zooarc.h"

#define JUST_LZH      /* for stand-alone compression */

extern FILE * arcfile;

t_uint16 bitbuf;
int unpackable;

#ifndef JUST_LZH
ulong origsize;
#endif
ulong compsize;

/*static*/ uint  subbitbuf;
/*static*/ int   bitcount;


void fillbuf(int n)  /* Shift bitbuf n bits left, read n bits */
{
   bitbuf <<= n;
   while (n > bitcount) {
      bitbuf |= subbitbuf << (n -= bitcount);
#ifdef JUST_LZH
      if (feof(arcfile))
      subbitbuf = 0;
      else
      subbitbuf = (uchar) getc(arcfile);
#else
      if (compsize != 0) {
         compsize--;  subbitbuf = (uchar) getc(arcfile);
      } else subbitbuf = 0;
#endif /* JUST_LZH */
      bitcount = CHAR_BIT;
   }
   bitbuf |= subbitbuf >> (bitcount -= n);
}

uint getbits(int n)
{
   uint x;

   x = bitbuf >> (BITBUFSIZ - n);  fillbuf(n);
   return x;
}



void putbits(int n, uint x)  /* Write rightmost n bits of x */
{
   if (n < bitcount) {
      subbitbuf |= x << (bitcount -= n);
   } else {
#ifdef JUST_LZH
      (void) putc((int) (subbitbuf | (x >> (n -= bitcount))), arcfile);
      compsize++;
#else
      if (compsize < origsize) {
         (void) zputc((int) (subbitbuf | (x >> (n -= bitcount))), arcfile);
         compsize++;
      } else unpackable = 1;
#endif /* JUST_LZH */

      if (n < CHAR_BIT) {
         subbitbuf = x << (bitcount = CHAR_BIT - n);
      } else {
#ifdef JUST_LZH
         (void) putc((int) (x >> (n - CHAR_BIT)), arcfile);
         compsize++;
#else
         if (compsize < origsize) {
            (void) zputc((int) (x >> (n - CHAR_BIT)), arcfile);
            compsize++;
         } else unpackable = 1;
#endif /* JUST_LZH */
         subbitbuf = x << (bitcount = 2 * CHAR_BIT - n);
      }
   }
}

/*extern void addbfcrc(); OIS*/

#if 0

int fread_crc(uchar *p,int n,FILE *f)
{
   int i;

   i = n = fread((char *) p, 1, n, f);  origsize += n;
   addbfcrc((char *)p, i);
   return n;
}

void fwrite_crc(uchar *p, int n, FILE *f)
{
   if (f != NULLFILE) {
      if (fwrite((char *) p, 1, n, f) < n)
      prterror('f', disk_full);
   }
   addbfcrc((char *)p, n);
}

#endif

void init_getbits()
{
   bitbuf = 0;  subbitbuf = 0;  bitcount = 0;
   fillbuf(BITBUFSIZ);
}


void init_putbits()
{
   bitcount = CHAR_BIT;  subbitbuf = 0;
}
