| 1 | /******************************************************************** |
| 2 | * * |
| 3 | * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * |
| 4 | * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * |
| 5 | * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * |
| 6 | * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * |
| 7 | * * |
| 8 | * THE OggTheora SOURCE CODE IS (C) COPYRIGHT 1994-2009 * |
| 9 | * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * |
| 10 | * * |
| 11 | ******************************************************************** |
| 12 | |
| 13 | function: packing variable sized words into an octet stream |
| 14 | last mod: $Id$ |
| 15 | |
| 16 | ********************************************************************/ |
| 17 | #include <string.h> |
| 18 | #include <stdlib.h> |
| 19 | #include "bitpack.h" |
| 20 | |
| 21 | /*We're 'MSb' endian; if we write a word but read individual bits, |
| 22 | then we'll read the MSb first.*/ |
| 23 | |
| 24 | void oc_pack_readinit(oc_pack_buf *_b,unsigned char *_buf,long _bytes){ |
| 25 | memset(_b,0,sizeof(*_b)); |
| 26 | _b->ptr=_buf; |
| 27 | _b->stop=_buf+_bytes; |
| 28 | } |
| 29 | |
| 30 | static oc_pb_window oc_pack_refill(oc_pack_buf *_b,int _bits){ |
| 31 | const unsigned char *ptr; |
| 32 | const unsigned char *stop; |
| 33 | oc_pb_window window; |
| 34 | int available; |
| 35 | unsigned shift; |
| 36 | stop=_b->stop; |
| 37 | ptr=_b->ptr; |
| 38 | window=_b->window; |
| 39 | available=_b->bits; |
| 40 | shift=OC_PB_WINDOW_SIZE-available; |
| 41 | while(7<shift&&ptr<stop){ |
| 42 | shift-=8; |
| 43 | window|=(oc_pb_window)*ptr++<<shift; |
| 44 | } |
| 45 | _b->ptr=ptr; |
| 46 | available=OC_PB_WINDOW_SIZE-shift; |
| 47 | if(_bits>available){ |
| 48 | if(ptr>=stop){ |
| 49 | _b->eof=1; |
| 50 | available=OC_LOTS_OF_BITS; |
| 51 | } |
| 52 | else window|=*ptr>>(available&7); |
| 53 | } |
| 54 | _b->bits=available; |
| 55 | return window; |
| 56 | } |
| 57 | |
| 58 | int oc_pack_look1(oc_pack_buf *_b){ |
| 59 | oc_pb_window window; |
| 60 | int available; |
| 61 | window=_b->window; |
| 62 | available=_b->bits; |
| 63 | if(available<1)_b->window=window=oc_pack_refill(_b,1); |
| 64 | return window>>OC_PB_WINDOW_SIZE-1; |
| 65 | } |
| 66 | |
| 67 | void oc_pack_adv1(oc_pack_buf *_b){ |
| 68 | _b->window<<=1; |
| 69 | _b->bits--; |
| 70 | } |
| 71 | |
| 72 | /*Here we assume that 0<=_bits&&_bits<=32.*/ |
| 73 | long oc_pack_read_c(oc_pack_buf *_b,int _bits){ |
| 74 | oc_pb_window window; |
| 75 | int available; |
| 76 | long result; |
| 77 | window=_b->window; |
| 78 | available=_b->bits; |
| 79 | if(_bits==0)return 0; |
| 80 | if(available<_bits){ |
| 81 | window=oc_pack_refill(_b,_bits); |
| 82 | available=_b->bits; |
| 83 | } |
| 84 | result=window>>OC_PB_WINDOW_SIZE-_bits; |
| 85 | available-=_bits; |
| 86 | window<<=1; |
| 87 | window<<=_bits-1; |
| 88 | _b->window=window; |
| 89 | _b->bits=available; |
| 90 | return result; |
| 91 | } |
| 92 | |
| 93 | int oc_pack_read1_c(oc_pack_buf *_b){ |
| 94 | oc_pb_window window; |
| 95 | int available; |
| 96 | int result; |
| 97 | window=_b->window; |
| 98 | available=_b->bits; |
| 99 | if(available<1){ |
| 100 | window=oc_pack_refill(_b,1); |
| 101 | available=_b->bits; |
| 102 | } |
| 103 | result=window>>OC_PB_WINDOW_SIZE-1; |
| 104 | available--; |
| 105 | window<<=1; |
| 106 | _b->window=window; |
| 107 | _b->bits=available; |
| 108 | return result; |
| 109 | } |
| 110 | |
| 111 | long oc_pack_bytes_left(oc_pack_buf *_b){ |
| 112 | if(_b->eof)return -1; |
| 113 | return _b->stop-_b->ptr+(_b->bits>>3); |
| 114 | } |
| 115 | |