#include <stdlib.h>
#include <stdio.h>

#include "bitio_m_stdio.h"

stdio_bitio_buffer::stdio_bitio_buffer(FILE *f) {
  attachFile (f);
}

void stdio_bitio_buffer::attachFile (FILE *f) {
  file = f;
  buffer = 0;
  btg = 0;
  bytesWritten = 0;
}

void stdio_bitio_buffer::encodeStart() {
  btg = sizeof(buffer) * 8;
}

void stdio_bitio_buffer::error() {
  fprintf(stderr, "Unexpected EOF in \"%s\" on line %d", __FILE__, __LINE__);
  exit(1);
}

void stdio_bitio_buffer::seek (mg_u_long byte, unsigned char bit) {
  if (fseek (file, byte, SEEK_SET) != 0) return;
  buffer = getc(file);
  btg = bit;
  bytesWritten = 0;
}

void stdio_bitio_buffer::seek(mg_u_long topos) {
  if (fseek(file, topos >> 3, SEEK_SET) != 0) return;
  buffer = getc(file);
  btg = 8 - (topos & 0x07);
  bytesWritten = 0;
}

mg_s_long stdio_bitio_buffer::addff(mg_s_long b)
{
  if (!btg)
    {
      register int val;
      val = getc(file);
      if (val == EOF)
	{
	  buffer = 0x0ff;
	}
      else
	{
	  buffer = val;
	}
      btg = sizeof(buffer) * 8;
    }
  b = b + b + ((buffer >> --btg) & 0x01);

  return b;
}

mg_s_long stdio_bitio_buffer::add00(mg_s_long b)
{
  if (!btg)
    {
      register int val;
      val = getc(file);
      if (val == EOF)
	{
	  buffer = 0xff;
	}
      else
	{
	  buffer = val;
	}
      btg = sizeof(buffer) * 8;
    }
  b = b + b + ((buffer >> --btg) & 0x01);
  
  return b;
}

void stdio_bitio_buffer::encodeBit(int b)
{
  --btg;
  if (b != 0)
    buffer |= (1 << btg);

  if (btg == 0)
    {
      putc(buffer, file);
      bytesWritten += sizeof (buffer);
      buffer = 0;
      btg = sizeof(buffer)*8;
    }
}

int stdio_bitio_buffer::bit()
{
  if (btg == 0)
    {
      buffer = getc(file);
      if (feof(file))
	{
	  error();
	  return 0;
	}
      else
	{
	  btg = sizeof(buffer) * 8;
	}
    }
  return ((buffer >> --btg) & 0x01);
}

void stdio_bitio_buffer::done() {
  // no tidying required
}

void stdio_bitio_buffer::encodeDone() {
  if (btg != sizeof(buffer) * 8) {
    putc(buffer, file);
    bytesWritten += sizeof (buffer);
  }
}

