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: bitpack.c 16503 2009-08-22 18:14:02Z giles $
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
oc_pack_readinit(oc_pack_buf * _b,unsigned char * _buf,long _bytes)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
oc_pack_refill(oc_pack_buf * _b,int _bits)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 window=_b->window;
36 available=_b->bits;
37 ptr=_b->ptr;
38 stop=_b->stop;
39 while(available<=OC_PB_WINDOW_SIZE-8&&ptr<stop){
40 available+=8;
41 window|=(oc_pb_window)*ptr++<<OC_PB_WINDOW_SIZE-available;
42 }
43 _b->ptr=ptr;
44 if(_bits>available){
45 if(ptr>=stop){
46 _b->eof=1;
47 available=OC_LOTS_OF_BITS;
48 }
49 else window|=*ptr>>(available&7);
50 }
51 _b->bits=available;
52 return window;
53 }
54
oc_pack_look1(oc_pack_buf * _b)55 int oc_pack_look1(oc_pack_buf *_b){
56 oc_pb_window window;
57 int available;
58 window=_b->window;
59 available=_b->bits;
60 if(available<1)_b->window=window=oc_pack_refill(_b,1);
61 return window>>OC_PB_WINDOW_SIZE-1;
62 }
63
oc_pack_adv1(oc_pack_buf * _b)64 void oc_pack_adv1(oc_pack_buf *_b){
65 _b->window<<=1;
66 _b->bits--;
67 }
68
69 /*Here we assume that 0<=_bits&&_bits<=32.*/
oc_pack_read(oc_pack_buf * _b,int _bits)70 long oc_pack_read(oc_pack_buf *_b,int _bits){
71 oc_pb_window window;
72 int available;
73 long result;
74 window=_b->window;
75 available=_b->bits;
76 if(_bits==0)return 0;
77 if(available<_bits){
78 window=oc_pack_refill(_b,_bits);
79 available=_b->bits;
80 }
81 result=window>>OC_PB_WINDOW_SIZE-_bits;
82 available-=_bits;
83 window<<=1;
84 window<<=_bits-1;
85 _b->bits=available;
86 _b->window=window;
87 return result;
88 }
89
oc_pack_read1(oc_pack_buf * _b)90 int oc_pack_read1(oc_pack_buf *_b){
91 oc_pb_window window;
92 int available;
93 int result;
94 window=_b->window;
95 available=_b->bits;
96 if(available<1){
97 window=oc_pack_refill(_b,1);
98 available=_b->bits;
99 }
100 result=window>>OC_PB_WINDOW_SIZE-1;
101 available--;
102 window<<=1;
103 _b->bits=available;
104 _b->window=window;
105 return result;
106 }
107
oc_pack_bytes_left(oc_pack_buf * _b)108 long oc_pack_bytes_left(oc_pack_buf *_b){
109 if(_b->eof)return -1;
110 return _b->stop-_b->ptr+(_b->bits>>3);
111 }
112