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

#include "bitio_m_abstract.h"
#include "bitio_m_mem.h"

mem_bitio_buffer::mem_bitio_buffer() {
}

mem_bitio_buffer::mem_bitio_buffer(unsigned char *readbuffer, int size) { 
  pos       = readbuffer;
  base      = readbuffer;
  remaining = size;
  buffer    = 0;
  btg       = 0;
}


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

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


void mem_bitio_buffer::seek(mg_u_long toPos) { 
  register mg_s_long _newPos;
  do {
    _newPos = toPos;
    
    pos    = base + (_newPos >> 3);
    buffer = *pos++;
    btg    = 8 - (_newPos & 0x07);
  } while (0);
}

mg_s_long mem_bitio_buffer::addff(mg_s_long b) {
  do {
    if (btg == 0) {
      if (remaining != 0) {
	buffer = *pos++;
	--remaining;
      } else {
	buffer = 0xff;
      }
      btg = sizeof(buffer) * 8;
    }
    b = b + b + ((buffer >> --btg) & 1);
  } while(0);

  return b;
}

mg_s_long mem_bitio_buffer::add00(mg_s_long b) {
  do {
    if (btg == 0) {
      if (remaining != 0) {
	buffer = *pos++;
	--remaining;
      } else {
	buffer = 0x00;
      }
      btg = sizeof(buffer) * 8;
    }
    b = b + b + ((buffer >> --btg) & 1);
  } while(0);
  
  return b;
}

int mem_bitio_buffer::bit() {
  if (btg == 0) {

    if (remaining == 0) { 
      this->error();
      return 0;

    } else {
      buffer = *pos++;
      --remaining;
      btg = sizeof(buffer) * 8;
    }
    
  }
  return ((buffer >> --btg) & 0x01);
}

void mem_bitio_buffer::encodeBit(int b) {
  --btg;
  if (b) buffer |= (1 << btg);
  
  if (btg == 0) {
    if (remaining) {
      *pos++ = buffer;
      --remaining;
    }
    buffer = 0;
    btg = sizeof(buffer)*8;
  }
}

void mem_bitio_buffer::flush() {
  if (btg != sizeof(buffer)*8) {
    if (remaining) {
      *pos++ = buffer;
      --remaining;
    }
  }
  btg = sizeof(buffer)*8;
}

void mem_bitio_buffer::done() {
  // do nothing
}

int mem_bitio_buffer::encodeLength() {
  return pos - base;
}

int mem_bitio_buffer::encodeVerify() {
  return (remaining != 0);
}



