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