1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
4  *                                                                  *
5  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
6  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
8  *                                                                  *
9  * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
10  * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
11  *                                                                  *
12  ********************************************************************
13 
14   function: packing variable sized words into an octet stream
15 
16  ********************************************************************/
17 
18 /* We're 'LSb' endian; if we write a word but read individual bits,
19    then we'll read the lsb first */
20 
21 #include <string.h>
22 #include <stdlib.h>
23 #include "ogg.h"
24 
25 static unsigned long mask[]=
26 {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
27  0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
28  0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
29  0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
30  0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
31  0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
32  0x3fffffff,0x7fffffff,0xffffffff };
33 
34 /* mark read process as having run off the end */
_adv_halt(oggpack_buffer * b)35 static void _adv_halt(oggpack_buffer *b){
36   b->headptr=b->head->buffer->data+b->head->begin+b->head->length;
37   b->headend=-1;
38   b->headbit=0;
39 }
40 
41 /* spans forward, skipping as many bytes as headend is negative; if
42    headend is zero, simply finds next byte.  If we're up to the end
43    of the buffer, leaves headend at zero.  If we've read past the end,
44    halt the decode process. */
_span(oggpack_buffer * b)45 static void _span(oggpack_buffer *b){
46   while(b->headend<1){
47     if(b->head->next){
48       b->count+=b->head->length;
49       b->head=b->head->next;
50       b->headptr=b->head->buffer->data+b->head->begin-b->headend;
51       b->headend+=b->head->length;
52     }else{
53       /* we've either met the end of decode, or gone past it. halt
54          only if we're past */
55       if(b->headend<0 || b->headbit)
56         /* read has fallen off the end */
57         _adv_halt(b);
58 
59       break;
60     }
61   }
62 }
63 
oggpack_readinit(oggpack_buffer * b,ogg_reference * r)64 void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){
65   memset(b,0,sizeof(*b));
66 
67   b->tail=b->head=r;
68   b->count=0;
69   b->headptr=b->head->buffer->data+b->head->begin;
70   b->headend=b->head->length;
71   _span(b);
72 }
73 
74 #define _lookspan()   while(!end){\
75                         head=head->next;\
76                         if(!head) return -1;\
77                         ptr=head->buffer->data + head->begin;\
78                         end=head->length;\
79                       }
80 
81 /* Read in bits without advancing the bitptr; bits <= 32 */
oggpack_look(oggpack_buffer * b,int bits)82 long oggpack_look(oggpack_buffer *b,int bits){
83   unsigned long m=mask[bits];
84   unsigned long ret=-1;
85 
86   bits+=b->headbit;
87 
88   if(bits >= b->headend<<3){
89     int            end=b->headend;
90     unsigned char *ptr=b->headptr;
91     ogg_reference *head=b->head;
92 
93     if(end<0)return -1;
94 
95     if(bits){
96       _lookspan();
97       ret=*ptr++>>b->headbit;
98       if(bits>8){
99         --end;
100         _lookspan();
101         ret|=*ptr++<<(8-b->headbit);
102         if(bits>16){
103           --end;
104           _lookspan();
105           ret|=*ptr++<<(16-b->headbit);
106           if(bits>24){
107             --end;
108             _lookspan();
109             ret|=*ptr++<<(24-b->headbit);
110             if(bits>32 && b->headbit){
111               --end;
112               _lookspan();
113               ret|=*ptr<<(32-b->headbit);
114             }
115           }
116         }
117       }
118     }
119 
120   }else{
121 
122     /* make this a switch jump-table */
123     ret=b->headptr[0]>>b->headbit;
124     if(bits>8){
125       ret|=b->headptr[1]<<(8-b->headbit);
126       if(bits>16){
127         ret|=b->headptr[2]<<(16-b->headbit);
128         if(bits>24){
129           ret|=b->headptr[3]<<(24-b->headbit);
130           if(bits>32 && b->headbit)
131             ret|=b->headptr[4]<<(32-b->headbit);
132         }
133       }
134     }
135   }
136 
137   ret&=m;
138   return ret;
139 }
140 
141 /* limited to 32 at a time */
oggpack_adv(oggpack_buffer * b,int bits)142 void oggpack_adv(oggpack_buffer *b,int bits){
143   bits+=b->headbit;
144   b->headbit=bits&7;
145   b->headptr+=bits/8;
146   if((b->headend-=bits/8)<1)_span(b);
147 }
148 
149 /* spans forward and finds next byte.  Never halts */
_span_one(oggpack_buffer * b)150 static void _span_one(oggpack_buffer *b){
151   while(b->headend<1){
152     if(b->head->next){
153       b->count+=b->head->length;
154       b->head=b->head->next;
155       b->headptr=b->head->buffer->data+b->head->begin;
156       b->headend=b->head->length;
157     }else
158       break;
159   }
160 }
161 
_halt_one(oggpack_buffer * b)162 static int _halt_one(oggpack_buffer *b){
163   if(b->headend<1){
164     _adv_halt(b);
165     return -1;
166   }
167   return 0;
168 }
169 
oggpack_eop(oggpack_buffer * b)170 int oggpack_eop(oggpack_buffer *b){
171   if(b->headend<0)return -1;
172   return 0;
173 }
174 
175 /* bits <= 32 */
oggpack_read(oggpack_buffer * b,int bits)176 long oggpack_read(oggpack_buffer *b,int bits){
177   unsigned long m=mask[bits];
178   ogg_uint32_t ret=-1;
179 
180   bits+=b->headbit;
181 
182   if(bits >= b->headend<<3){
183 
184     if(b->headend<0)return -1;
185 
186     if(bits){
187       if (_halt_one(b)) return -1;
188       ret=*b->headptr>>b->headbit;
189 
190       if(bits>=8){
191         ++b->headptr;
192         --b->headend;
193         _span_one(b);
194         if(bits>8){
195           if (_halt_one(b)) return -1;
196           ret|=*b->headptr<<(8-b->headbit);
197 
198           if(bits>=16){
199             ++b->headptr;
200             --b->headend;
201             _span_one(b);
202             if(bits>16){
203               if (_halt_one(b)) return -1;
204               ret|=*b->headptr<<(16-b->headbit);
205 
206               if(bits>=24){
207                 ++b->headptr;
208                 --b->headend;
209                 _span_one(b);
210                 if(bits>24){
211                   if (_halt_one(b)) return -1;
212                   ret|=*b->headptr<<(24-b->headbit);
213 
214                   if(bits>=32){
215                     ++b->headptr;
216                     --b->headend;
217                     _span_one(b);
218                     if(bits>32){
219                       if (_halt_one(b)) return -1;
220                       if(b->headbit)ret|=*b->headptr<<(32-b->headbit);
221 
222                     }
223                   }
224                 }
225               }
226             }
227           }
228         }
229       }
230     }
231   }else{
232 
233     ret=b->headptr[0]>>b->headbit;
234     if(bits>8){
235       ret|=b->headptr[1]<<(8-b->headbit);
236       if(bits>16){
237         ret|=b->headptr[2]<<(16-b->headbit);
238         if(bits>24){
239           ret|=b->headptr[3]<<(24-b->headbit);
240           if(bits>32 && b->headbit){
241             ret|=b->headptr[4]<<(32-b->headbit);
242           }
243         }
244       }
245     }
246 
247     b->headptr+=bits/8;
248     b->headend-=bits/8;
249   }
250 
251   ret&=m;
252   b->headbit=bits&7;
253   return ret;
254 }
255 
oggpack_bytes(oggpack_buffer * b)256 long oggpack_bytes(oggpack_buffer *b){
257   return(b->count+b->headptr-b->head->buffer->data-b->head->begin+
258          (b->headbit+7)/8);
259 }
260 
oggpack_bits(oggpack_buffer * b)261 long oggpack_bits(oggpack_buffer *b){
262   return((b->count+b->headptr-b->head->buffer->data-b->head->begin)*8+
263          b->headbit);
264 }
265 
266