#include <stdio.h>
#include <stdlib.h>
//
#include "proto.h"
#include "bucket.h"


static U8 *buf;
static U32 bufsize, bucket, bits, ptr;


void init_bucket(U8 *buffer, U32 size) {

  buf = buffer;
  bufsize = size;
  bits = 0;
  ptr = 0;
}


int align_bucket() {

  bits = 0;
  return 0;
}

int read_position() {
  return ptr;
}


int read_ushort(U16 *output) {

  if (ptr+2 > bufsize)  return 1;
  *output = buf[ptr+0] | (buf[ptr+1]<<8);
  ptr += 2;
  bits = 0;
  return 0;
}


int read_short(S16 *output) {

  return read_ushort((U16 *)output);
}


int read_uint(U32 *output) {

  if (ptr+4 > bufsize)  return 1;
  *output = buf[ptr+0] | (buf[ptr+1]<<8) | (buf[ptr+2]<<16) | (buf[ptr+3]<<24);
  ptr += 4;
  bits = 0;
  return 0;
}


int read_int(S32 *output) {

  return read_uint((U32 *)output);
}


int read_ubyte(U8 *output) {

  if (ptr+1 > bufsize)  return 1;
  *output = buf[ptr+0];
  ptr += 1;
  bits = 0;
  return 0;
}


int read_byte(S8 *output) {

  if (ptr+1 > bufsize)  return 1;
  *output = (S8)buf[ptr+0];
  ptr += 1;
  bits = 0;
  return 0;
}



int read_bits(int n, S32 *output) {

  if (read_ubits(n, (U32 *)output))  return 1;
  if (n == 32)  return 0;
  n = 32-n;
  *output = (*output<<n)>>n;
  return 0;
}


int read_ubits(int n, U32 *output) {

  U32 v;

  if (n == 0) {
    *output = 0;
    return 0;
  }

  if (ptr+(n>>3) > bufsize)  return 1;

 // if (bits == 0)  bucket = buf[ptr++], bits = 8;
  v = 0;
  while (1) {
    if (n > bits) {
      v |= bucket<<(n-bits);
      n -= bits;
      bucket = buf[ptr++];
      bits = 8;

    } else {
      v |= bucket>>(bits-n);
      bits -= n;
      bucket &= 0xff>>(8-bits);
      *output = v;
      return 0;
    }
  }

  return 1;
}
