|
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 17410 2010-09-21 21:53:48Z tterribe $ |
|
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 } |