michael@0: /******************************************************************** michael@0: * * michael@0: * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * michael@0: * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * michael@0: * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * michael@0: * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * michael@0: * * michael@0: * THE OggTheora SOURCE CODE IS (C) COPYRIGHT 1994-2009 * michael@0: * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * michael@0: * * michael@0: ******************************************************************** michael@0: michael@0: function: packing variable sized words into an octet stream michael@0: last mod: $Id: bitpack.c 17410 2010-09-21 21:53:48Z tterribe $ michael@0: michael@0: ********************************************************************/ michael@0: #include michael@0: #include michael@0: #include "bitpack.h" michael@0: michael@0: /*We're 'MSb' endian; if we write a word but read individual bits, michael@0: then we'll read the MSb first.*/ michael@0: michael@0: void oc_pack_readinit(oc_pack_buf *_b,unsigned char *_buf,long _bytes){ michael@0: memset(_b,0,sizeof(*_b)); michael@0: _b->ptr=_buf; michael@0: _b->stop=_buf+_bytes; michael@0: } michael@0: michael@0: static oc_pb_window oc_pack_refill(oc_pack_buf *_b,int _bits){ michael@0: const unsigned char *ptr; michael@0: const unsigned char *stop; michael@0: oc_pb_window window; michael@0: int available; michael@0: unsigned shift; michael@0: stop=_b->stop; michael@0: ptr=_b->ptr; michael@0: window=_b->window; michael@0: available=_b->bits; michael@0: shift=OC_PB_WINDOW_SIZE-available; michael@0: while(7ptr=ptr; michael@0: available=OC_PB_WINDOW_SIZE-shift; michael@0: if(_bits>available){ michael@0: if(ptr>=stop){ michael@0: _b->eof=1; michael@0: available=OC_LOTS_OF_BITS; michael@0: } michael@0: else window|=*ptr>>(available&7); michael@0: } michael@0: _b->bits=available; michael@0: return window; michael@0: } michael@0: michael@0: int oc_pack_look1(oc_pack_buf *_b){ michael@0: oc_pb_window window; michael@0: int available; michael@0: window=_b->window; michael@0: available=_b->bits; michael@0: if(available<1)_b->window=window=oc_pack_refill(_b,1); michael@0: return window>>OC_PB_WINDOW_SIZE-1; michael@0: } michael@0: michael@0: void oc_pack_adv1(oc_pack_buf *_b){ michael@0: _b->window<<=1; michael@0: _b->bits--; michael@0: } michael@0: michael@0: /*Here we assume that 0<=_bits&&_bits<=32.*/ michael@0: long oc_pack_read_c(oc_pack_buf *_b,int _bits){ michael@0: oc_pb_window window; michael@0: int available; michael@0: long result; michael@0: window=_b->window; michael@0: available=_b->bits; michael@0: if(_bits==0)return 0; michael@0: if(available<_bits){ michael@0: window=oc_pack_refill(_b,_bits); michael@0: available=_b->bits; michael@0: } michael@0: result=window>>OC_PB_WINDOW_SIZE-_bits; michael@0: available-=_bits; michael@0: window<<=1; michael@0: window<<=_bits-1; michael@0: _b->window=window; michael@0: _b->bits=available; michael@0: return result; michael@0: } michael@0: michael@0: int oc_pack_read1_c(oc_pack_buf *_b){ michael@0: oc_pb_window window; michael@0: int available; michael@0: int result; michael@0: window=_b->window; michael@0: available=_b->bits; michael@0: if(available<1){ michael@0: window=oc_pack_refill(_b,1); michael@0: available=_b->bits; michael@0: } michael@0: result=window>>OC_PB_WINDOW_SIZE-1; michael@0: available--; michael@0: window<<=1; michael@0: _b->window=window; michael@0: _b->bits=available; michael@0: return result; michael@0: } michael@0: michael@0: long oc_pack_bytes_left(oc_pack_buf *_b){ michael@0: if(_b->eof)return -1; michael@0: return _b->stop-_b->ptr+(_b->bits>>3); michael@0: }