text: /**
  	libsmacker - A C library for decoding .smk Smacker Video files
  	Copyright (C) 2012-2017 Greg Kennedy
  
  	See smacker.h for more information.
  
  	smk_bitstream.c
  		Implements a bitstream structure, which can extract and
  		return a bit at a time from a raw block of bytes.
  */
  
  #include "smk_bitstream.h"
  
  /* malloc and friends */
  #include "smk_malloc.h"
  
  /*
  	Bitstream structure
  	Pointer to raw block of data and a size limit.
  	Maintains internal pointers to byte_num and bit_number.
  */
  struct smk_bit_t
  {
  	const unsigned char* buffer;
  	unsigned long size;
  
  	unsigned long byte_num;
  	char bit_num;
  };
  
  /* BITSTREAM Functions */
  struct smk_bit_t* smk_bs_init(const unsigned char* b, const unsigned long size)
  {
  	struct smk_bit_t* ret = NULL;
  
  	/* sanity check */
  	smk_assert(b);
  
  	/* allocate a bitstream struct */
  	smk_malloc(ret, sizeof(struct smk_bit_t));
  
  	/* set up the pointer to bitstream, and the size counter */
  	ret->buffer = b;
  	ret->size = size;
  
  	/* point to initial byte: note, smk_malloc already sets these to 0 */
  	/* ret->byte_num = 0;
  	ret->bit_num = 0; */
  
  	/* return ret or NULL if error : ) */
  error:
  	return ret;
  }
  
  /* Reads a bit
  	Returns -1 if error encountered */
  char _smk_bs_read_1(struct smk_bit_t* bs)
  {
  	unsigned char ret = -1;
  
  	/* sanity check */
  	smk_assert(bs);
  
  	/* don't die when running out of bits, but signal */
  	if (bs->byte_num >= bs->size)
  	{
  		fprintf(stderr, "libsmacker::_smk_bs_read_1(bs): ERROR: bitstream (length=%lu) exhausted.\n", bs->size);
  		goto error;
  	}
  
  	/* get next bit and return */
  	ret = (((bs->buffer[bs->byte_num]) & (1 << bs->bit_num)) != 0);
  
  	/* advance to next bit */
  	bs->bit_num ++;
  
  	/* Out of bits in this byte: next! */
  	if (bs->bit_num > 7)
  	{
  		bs->byte_num ++;
  		bs->bit_num = 0;
  	}
  
  	/* return ret, or (default) -1 if error */
  error:
  	return ret;
  }
  
  /* Reads a byte
  	Returns -1 if error. */
  short _smk_bs_read_8(struct smk_bit_t* bs)
  {
  	unsigned char ret = -1;
  
  	/* sanity check */
  	smk_assert(bs);
  
  	/* don't die when running out of bits, but signal */
  	if (bs->byte_num + (bs->bit_num > 0) >= bs->size)
  	{
  		fprintf(stderr, "libsmacker::_smk_bs_read_8(bs): ERROR: bitstream (length=%lu) exhausted.\n", bs->size);
  		goto error;
  	}
  
  	if (bs->bit_num)
  	{
  		/* unaligned read */
  		ret = bs->buffer[bs->byte_num] >> bs->bit_num;
  		bs->byte_num ++;
  		ret |= (bs->buffer[bs->byte_num] << (8 - bs->bit_num));
  	} else {
  		/* aligned read */
  		ret = bs->buffer[bs->byte_num ++];
  	}
  
  	/* return ret, or (default) -1 if error */
  error:
  	return ret;
  }
  