18 /* We're 'LSb' endian; if we write a word but read individual bits, |
18 /* We're 'LSb' endian; if we write a word but read individual bits, |
19 then we'll read the lsb first */ |
19 then we'll read the lsb first */ |
20 |
20 |
21 #include <string.h> |
21 #include <string.h> |
22 #include <stdlib.h> |
22 #include <stdlib.h> |
23 #include "misc.h" |
|
24 #include "ogg.h" |
23 #include "ogg.h" |
25 |
24 |
26 static unsigned long mask[]= |
25 static unsigned long mask[]= |
27 {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, |
26 {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, |
28 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, |
27 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, |
46 static void _span(oggpack_buffer *b){ |
45 static void _span(oggpack_buffer *b){ |
47 while(b->headend<1){ |
46 while(b->headend<1){ |
48 if(b->head->next){ |
47 if(b->head->next){ |
49 b->count+=b->head->length; |
48 b->count+=b->head->length; |
50 b->head=b->head->next; |
49 b->head=b->head->next; |
51 b->headptr=b->head->buffer->data+b->head->begin-b->headend; |
50 b->headptr=b->head->buffer->data+b->head->begin-b->headend; |
52 b->headend+=b->head->length; |
51 b->headend+=b->head->length; |
53 }else{ |
52 }else{ |
54 /* we've either met the end of decode, or gone past it. halt |
53 /* we've either met the end of decode, or gone past it. halt |
55 only if we're past */ |
54 only if we're past */ |
56 if(b->headend<0 || b->headbit) |
55 if(b->headend<0 || b->headbit) |
57 /* read has fallen off the end */ |
56 /* read has fallen off the end */ |
80 } |
79 } |
81 |
80 |
82 /* Read in bits without advancing the bitptr; bits <= 32 */ |
81 /* Read in bits without advancing the bitptr; bits <= 32 */ |
83 long oggpack_look(oggpack_buffer *b,int bits){ |
82 long oggpack_look(oggpack_buffer *b,int bits){ |
84 unsigned long m=mask[bits]; |
83 unsigned long m=mask[bits]; |
85 unsigned long ret; |
84 unsigned long ret=-1; |
86 |
85 |
87 bits+=b->headbit; |
86 bits+=b->headbit; |
88 |
87 |
89 if(bits >= b->headend<<3){ |
88 if(bits >= b->headend<<3){ |
90 int end=b->headend; |
89 int end=b->headend; |
91 unsigned char *ptr=b->headptr; |
90 unsigned char *ptr=b->headptr; |
92 ogg_reference *head=b->head; |
91 ogg_reference *head=b->head; |
93 |
92 |
94 if(end<0)return -1; |
93 if(end<0)return -1; |
95 |
94 |
96 if(bits){ |
95 if(bits){ |
97 _lookspan(); |
96 _lookspan(); |
98 ret=*ptr++>>b->headbit; |
97 ret=*ptr++>>b->headbit; |
99 if(bits>8){ |
98 if(bits>8){ |
100 --end; |
99 --end; |
101 _lookspan(); |
100 _lookspan(); |
102 ret|=*ptr++<<(8-b->headbit); |
101 ret|=*ptr++<<(8-b->headbit); |
103 if(bits>16){ |
102 if(bits>16){ |
104 --end; |
103 --end; |
105 _lookspan(); |
104 _lookspan(); |
106 ret|=*ptr++<<(16-b->headbit); |
105 ret|=*ptr++<<(16-b->headbit); |
107 if(bits>24){ |
106 if(bits>24){ |
108 --end; |
107 --end; |
109 _lookspan(); |
108 _lookspan(); |
110 ret|=*ptr++<<(24-b->headbit); |
109 ret|=*ptr++<<(24-b->headbit); |
111 if(bits>32 && b->headbit){ |
110 if(bits>32 && b->headbit){ |
112 --end; |
111 --end; |
113 _lookspan(); |
112 _lookspan(); |
114 ret|=*ptr<<(32-b->headbit); |
113 ret|=*ptr<<(32-b->headbit); |
115 } |
114 } |
145 b->headbit=bits&7; |
144 b->headbit=bits&7; |
146 b->headptr+=bits/8; |
145 b->headptr+=bits/8; |
147 if((b->headend-=bits/8)<1)_span(b); |
146 if((b->headend-=bits/8)<1)_span(b); |
148 } |
147 } |
149 |
148 |
|
149 /* spans forward and finds next byte. Never halts */ |
|
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 |
|
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 |
150 int oggpack_eop(oggpack_buffer *b){ |
170 int oggpack_eop(oggpack_buffer *b){ |
151 if(b->headend<0)return -1; |
171 if(b->headend<0)return -1; |
152 return 0; |
172 return 0; |
153 } |
173 } |
154 |
174 |
155 /* bits <= 32 */ |
175 /* bits <= 32 */ |
156 long oggpack_read(oggpack_buffer *b,int bits){ |
176 long oggpack_read(oggpack_buffer *b,int bits){ |
157 long ret=oggpack_look(b,bits); |
177 unsigned long m=mask[bits]; |
158 oggpack_adv(b,bits); |
178 ogg_uint32_t ret=-1; |
159 return(ret); |
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; |
160 } |
254 } |
161 |
255 |
162 long oggpack_bytes(oggpack_buffer *b){ |
256 long oggpack_bytes(oggpack_buffer *b){ |
163 return(b->count+b->headptr-b->head->buffer->data-b->head->begin+ |
257 return(b->count+b->headptr-b->head->buffer->data-b->head->begin+ |
164 (b->headbit+7)/8); |
258 (b->headbit+7)/8); |