/*
   file bitstream.c
   (C) 2003 Yann GUIDON <whygee@f-cpu.org>
   Common code for the Range Reduction algorithms
   version Sat Dec 27 09:21:56 CET 2003

   "int"s are assumed 32-bit and the bitstream
   has a byte granularity (this should be endian-proof),
   so the largest values are 24 bits wide.
*/

#include <stdio.h>  /* for printf */

/* some global data */
unsigned int stream_length; /* number of bytes */
unsigned int shift_count;   /* number of bits in the reservoir */
unsigned int reservoir;     /* bit accumulator */
unsigned char * stream;

/* bit insertion routine */
void put_bits(unsigned int nb_bits,
              unsigned int data) {
  int i;

  if (nb_bits==0) {
    printf("[skipping 0]\n");
    return;
  }

  /* print the number in binary format */
  i=nb_bits-1;
  do {
    putchar(((data >> (i--)) & 1) | '0');
  } while (i >= 0);
  putchar('\n');

  /* merge the input data and the reservoir */
  reservoir |= (data << shift_count);
  shift_count += nb_bits;

  /* sends the bit accumulator, byte per byte */
  while (shift_count >= 8) {
    stream[stream_length++] = reservoir;
    reservoir >>= 8;
    shift_count -= 8;
  }

  /* remove some eventual garbage */
  reservoir &= (1U << shift_count) - 1;
}


/* bit extraction routine */
unsigned int get_bits(unsigned int nb_bits) {
  unsigned int result;
  int i;

  if (nb_bits==0) {
    printf("[skipping 0]\n");
    return 0; /* shortcut */
  }

  while (shift_count < nb_bits) {
    reservoir |= stream[stream_length++] << shift_count;
    shift_count += 8;
  }

  result = reservoir & ((1U << nb_bits) - 1);
  reservoir >>= nb_bits;
  shift_count -= nb_bits;

  /* print the number in binary format */
  i=nb_bits-1;
  do {
    putchar(((result >> (i--)) & 1) | '0');
  } while (i >= 0);

  return result;
}

