Line data Source code
1 : /********************************************************************
2 : * *
3 : * THIS FILE IS PART OF THE Ogg CONTAINER 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 OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2014 *
9 : * by the Xiph.Org Foundation http://www.xiph.org/ *
10 : * *
11 : ********************************************************************
12 :
13 : function: packing variable sized words into an octet stream
14 : last mod: $Id: bitwise.c 19149 2014-05-27 16:26:23Z giles $
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 <limits.h>
24 : #include <ogg/ogg.h>
25 :
26 : #define BUFFER_INCREMENT 256
27 :
28 : static const unsigned long mask[]=
29 : {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
30 : 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
31 : 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
32 : 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
33 : 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
34 : 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
35 : 0x3fffffff,0x7fffffff,0xffffffff };
36 :
37 : static const unsigned int mask8B[]=
38 : {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};
39 :
40 0 : void oggpack_writeinit(oggpack_buffer *b){
41 0 : memset(b,0,sizeof(*b));
42 0 : b->ptr=b->buffer=_ogg_malloc(BUFFER_INCREMENT);
43 0 : b->buffer[0]='\0';
44 0 : b->storage=BUFFER_INCREMENT;
45 0 : }
46 :
47 0 : void oggpackB_writeinit(oggpack_buffer *b){
48 0 : oggpack_writeinit(b);
49 0 : }
50 :
51 0 : int oggpack_writecheck(oggpack_buffer *b){
52 0 : if(!b->ptr || !b->storage)return -1;
53 0 : return 0;
54 : }
55 :
56 0 : int oggpackB_writecheck(oggpack_buffer *b){
57 0 : return oggpack_writecheck(b);
58 : }
59 :
60 0 : void oggpack_writetrunc(oggpack_buffer *b,long bits){
61 0 : long bytes=bits>>3;
62 0 : if(b->ptr){
63 0 : bits-=bytes*8;
64 0 : b->ptr=b->buffer+bytes;
65 0 : b->endbit=bits;
66 0 : b->endbyte=bytes;
67 0 : *b->ptr&=mask[bits];
68 : }
69 0 : }
70 :
71 0 : void oggpackB_writetrunc(oggpack_buffer *b,long bits){
72 0 : long bytes=bits>>3;
73 0 : if(b->ptr){
74 0 : bits-=bytes*8;
75 0 : b->ptr=b->buffer+bytes;
76 0 : b->endbit=bits;
77 0 : b->endbyte=bytes;
78 0 : *b->ptr&=mask8B[bits];
79 : }
80 0 : }
81 :
82 : /* Takes only up to 32 bits. */
83 0 : void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){
84 0 : if(bits<0 || bits>32) goto err;
85 0 : if(b->endbyte>=b->storage-4){
86 : void *ret;
87 0 : if(!b->ptr)return;
88 0 : if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err;
89 0 : ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
90 0 : if(!ret) goto err;
91 0 : b->buffer=ret;
92 0 : b->storage+=BUFFER_INCREMENT;
93 0 : b->ptr=b->buffer+b->endbyte;
94 : }
95 :
96 0 : value&=mask[bits];
97 0 : bits+=b->endbit;
98 :
99 0 : b->ptr[0]|=value<<b->endbit;
100 :
101 0 : if(bits>=8){
102 0 : b->ptr[1]=(unsigned char)(value>>(8-b->endbit));
103 0 : if(bits>=16){
104 0 : b->ptr[2]=(unsigned char)(value>>(16-b->endbit));
105 0 : if(bits>=24){
106 0 : b->ptr[3]=(unsigned char)(value>>(24-b->endbit));
107 0 : if(bits>=32){
108 0 : if(b->endbit)
109 0 : b->ptr[4]=(unsigned char)(value>>(32-b->endbit));
110 : else
111 0 : b->ptr[4]=0;
112 : }
113 : }
114 : }
115 : }
116 :
117 0 : b->endbyte+=bits/8;
118 0 : b->ptr+=bits/8;
119 0 : b->endbit=bits&7;
120 0 : return;
121 : err:
122 0 : oggpack_writeclear(b);
123 : }
124 :
125 : /* Takes only up to 32 bits. */
126 0 : void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){
127 0 : if(bits<0 || bits>32) goto err;
128 0 : if(b->endbyte>=b->storage-4){
129 : void *ret;
130 0 : if(!b->ptr)return;
131 0 : if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err;
132 0 : ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
133 0 : if(!ret) goto err;
134 0 : b->buffer=ret;
135 0 : b->storage+=BUFFER_INCREMENT;
136 0 : b->ptr=b->buffer+b->endbyte;
137 : }
138 :
139 0 : value=(value&mask[bits])<<(32-bits);
140 0 : bits+=b->endbit;
141 :
142 0 : b->ptr[0]|=value>>(24+b->endbit);
143 :
144 0 : if(bits>=8){
145 0 : b->ptr[1]=(unsigned char)(value>>(16+b->endbit));
146 0 : if(bits>=16){
147 0 : b->ptr[2]=(unsigned char)(value>>(8+b->endbit));
148 0 : if(bits>=24){
149 0 : b->ptr[3]=(unsigned char)(value>>(b->endbit));
150 0 : if(bits>=32){
151 0 : if(b->endbit)
152 0 : b->ptr[4]=(unsigned char)(value<<(8-b->endbit));
153 : else
154 0 : b->ptr[4]=0;
155 : }
156 : }
157 : }
158 : }
159 :
160 0 : b->endbyte+=bits/8;
161 0 : b->ptr+=bits/8;
162 0 : b->endbit=bits&7;
163 0 : return;
164 : err:
165 0 : oggpack_writeclear(b);
166 : }
167 :
168 0 : void oggpack_writealign(oggpack_buffer *b){
169 0 : int bits=8-b->endbit;
170 0 : if(bits<8)
171 0 : oggpack_write(b,0,bits);
172 0 : }
173 :
174 0 : void oggpackB_writealign(oggpack_buffer *b){
175 0 : int bits=8-b->endbit;
176 0 : if(bits<8)
177 0 : oggpackB_write(b,0,bits);
178 0 : }
179 :
180 0 : static void oggpack_writecopy_helper(oggpack_buffer *b,
181 : void *source,
182 : long bits,
183 : void (*w)(oggpack_buffer *,
184 : unsigned long,
185 : int),
186 : int msb){
187 0 : unsigned char *ptr=(unsigned char *)source;
188 :
189 0 : long bytes=bits/8;
190 0 : long pbytes=(b->endbit+bits)/8;
191 0 : bits-=bytes*8;
192 :
193 : /* expand storage up-front */
194 0 : if(b->endbyte+pbytes>=b->storage){
195 : void *ret;
196 0 : if(!b->ptr) goto err;
197 0 : if(b->storage>b->endbyte+pbytes+BUFFER_INCREMENT) goto err;
198 0 : b->storage=b->endbyte+pbytes+BUFFER_INCREMENT;
199 0 : ret=_ogg_realloc(b->buffer,b->storage);
200 0 : if(!ret) goto err;
201 0 : b->buffer=ret;
202 0 : b->ptr=b->buffer+b->endbyte;
203 : }
204 :
205 : /* copy whole octets */
206 0 : if(b->endbit){
207 : int i;
208 : /* unaligned copy. Do it the hard way. */
209 0 : for(i=0;i<bytes;i++)
210 0 : w(b,(unsigned long)(ptr[i]),8);
211 : }else{
212 : /* aligned block copy */
213 0 : memmove(b->ptr,source,bytes);
214 0 : b->ptr+=bytes;
215 0 : b->endbyte+=bytes;
216 0 : *b->ptr=0;
217 : }
218 :
219 : /* copy trailing bits */
220 0 : if(bits){
221 0 : if(msb)
222 0 : w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits);
223 : else
224 0 : w(b,(unsigned long)(ptr[bytes]),bits);
225 : }
226 0 : return;
227 : err:
228 0 : oggpack_writeclear(b);
229 : }
230 :
231 0 : void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){
232 0 : oggpack_writecopy_helper(b,source,bits,oggpack_write,0);
233 0 : }
234 :
235 0 : void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits){
236 0 : oggpack_writecopy_helper(b,source,bits,oggpackB_write,1);
237 0 : }
238 :
239 0 : void oggpack_reset(oggpack_buffer *b){
240 0 : if(!b->ptr)return;
241 0 : b->ptr=b->buffer;
242 0 : b->buffer[0]=0;
243 0 : b->endbit=b->endbyte=0;
244 : }
245 :
246 0 : void oggpackB_reset(oggpack_buffer *b){
247 0 : oggpack_reset(b);
248 0 : }
249 :
250 0 : void oggpack_writeclear(oggpack_buffer *b){
251 0 : if(b->buffer)_ogg_free(b->buffer);
252 0 : memset(b,0,sizeof(*b));
253 0 : }
254 :
255 0 : void oggpackB_writeclear(oggpack_buffer *b){
256 0 : oggpack_writeclear(b);
257 0 : }
258 :
259 0 : void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
260 0 : memset(b,0,sizeof(*b));
261 0 : b->buffer=b->ptr=buf;
262 0 : b->storage=bytes;
263 0 : }
264 :
265 0 : void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
266 0 : oggpack_readinit(b,buf,bytes);
267 0 : }
268 :
269 : /* Read in bits without advancing the bitptr; bits <= 32 */
270 0 : long oggpack_look(oggpack_buffer *b,int bits){
271 : unsigned long ret;
272 : unsigned long m;
273 :
274 0 : if(bits<0 || bits>32) return -1;
275 0 : m=mask[bits];
276 0 : bits+=b->endbit;
277 :
278 0 : if(b->endbyte >= b->storage-4){
279 : /* not the main path */
280 0 : if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
281 : /* special case to avoid reading b->ptr[0], which might be past the end of
282 : the buffer; also skips some useless accounting */
283 0 : else if(!bits)return(0L);
284 : }
285 :
286 0 : ret=b->ptr[0]>>b->endbit;
287 0 : if(bits>8){
288 0 : ret|=b->ptr[1]<<(8-b->endbit);
289 0 : if(bits>16){
290 0 : ret|=b->ptr[2]<<(16-b->endbit);
291 0 : if(bits>24){
292 0 : ret|=b->ptr[3]<<(24-b->endbit);
293 0 : if(bits>32 && b->endbit)
294 0 : ret|=b->ptr[4]<<(32-b->endbit);
295 : }
296 : }
297 : }
298 0 : return(m&ret);
299 : }
300 :
301 : /* Read in bits without advancing the bitptr; bits <= 32 */
302 0 : long oggpackB_look(oggpack_buffer *b,int bits){
303 : unsigned long ret;
304 0 : int m=32-bits;
305 :
306 0 : if(m<0 || m>32) return -1;
307 0 : bits+=b->endbit;
308 :
309 0 : if(b->endbyte >= b->storage-4){
310 : /* not the main path */
311 0 : if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
312 : /* special case to avoid reading b->ptr[0], which might be past the end of
313 : the buffer; also skips some useless accounting */
314 0 : else if(!bits)return(0L);
315 : }
316 :
317 0 : ret=b->ptr[0]<<(24+b->endbit);
318 0 : if(bits>8){
319 0 : ret|=b->ptr[1]<<(16+b->endbit);
320 0 : if(bits>16){
321 0 : ret|=b->ptr[2]<<(8+b->endbit);
322 0 : if(bits>24){
323 0 : ret|=b->ptr[3]<<(b->endbit);
324 0 : if(bits>32 && b->endbit)
325 0 : ret|=b->ptr[4]>>(8-b->endbit);
326 : }
327 : }
328 : }
329 0 : return ((ret&0xffffffff)>>(m>>1))>>((m+1)>>1);
330 : }
331 :
332 0 : long oggpack_look1(oggpack_buffer *b){
333 0 : if(b->endbyte>=b->storage)return(-1);
334 0 : return((b->ptr[0]>>b->endbit)&1);
335 : }
336 :
337 0 : long oggpackB_look1(oggpack_buffer *b){
338 0 : if(b->endbyte>=b->storage)return(-1);
339 0 : return((b->ptr[0]>>(7-b->endbit))&1);
340 : }
341 :
342 0 : void oggpack_adv(oggpack_buffer *b,int bits){
343 0 : bits+=b->endbit;
344 :
345 0 : if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
346 :
347 0 : b->ptr+=bits/8;
348 0 : b->endbyte+=bits/8;
349 0 : b->endbit=bits&7;
350 0 : return;
351 :
352 : overflow:
353 0 : b->ptr=NULL;
354 0 : b->endbyte=b->storage;
355 0 : b->endbit=1;
356 : }
357 :
358 0 : void oggpackB_adv(oggpack_buffer *b,int bits){
359 0 : oggpack_adv(b,bits);
360 0 : }
361 :
362 0 : void oggpack_adv1(oggpack_buffer *b){
363 0 : if(++(b->endbit)>7){
364 0 : b->endbit=0;
365 0 : b->ptr++;
366 0 : b->endbyte++;
367 : }
368 0 : }
369 :
370 0 : void oggpackB_adv1(oggpack_buffer *b){
371 0 : oggpack_adv1(b);
372 0 : }
373 :
374 : /* bits <= 32 */
375 0 : long oggpack_read(oggpack_buffer *b,int bits){
376 : long ret;
377 : unsigned long m;
378 :
379 0 : if(bits<0 || bits>32) goto err;
380 0 : m=mask[bits];
381 0 : bits+=b->endbit;
382 :
383 0 : if(b->endbyte >= b->storage-4){
384 : /* not the main path */
385 0 : if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
386 : /* special case to avoid reading b->ptr[0], which might be past the end of
387 : the buffer; also skips some useless accounting */
388 0 : else if(!bits)return(0L);
389 : }
390 :
391 0 : ret=b->ptr[0]>>b->endbit;
392 0 : if(bits>8){
393 0 : ret|=b->ptr[1]<<(8-b->endbit);
394 0 : if(bits>16){
395 0 : ret|=b->ptr[2]<<(16-b->endbit);
396 0 : if(bits>24){
397 0 : ret|=b->ptr[3]<<(24-b->endbit);
398 0 : if(bits>32 && b->endbit){
399 0 : ret|=b->ptr[4]<<(32-b->endbit);
400 : }
401 : }
402 : }
403 : }
404 0 : ret&=m;
405 0 : b->ptr+=bits/8;
406 0 : b->endbyte+=bits/8;
407 0 : b->endbit=bits&7;
408 0 : return ret;
409 :
410 : overflow:
411 : err:
412 0 : b->ptr=NULL;
413 0 : b->endbyte=b->storage;
414 0 : b->endbit=1;
415 0 : return -1L;
416 : }
417 :
418 : /* bits <= 32 */
419 0 : long oggpackB_read(oggpack_buffer *b,int bits){
420 : long ret;
421 0 : long m=32-bits;
422 :
423 0 : if(m<0 || m>32) goto err;
424 0 : bits+=b->endbit;
425 :
426 0 : if(b->endbyte+4>=b->storage){
427 : /* not the main path */
428 0 : if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
429 : /* special case to avoid reading b->ptr[0], which might be past the end of
430 : the buffer; also skips some useless accounting */
431 0 : else if(!bits)return(0L);
432 : }
433 :
434 0 : ret=b->ptr[0]<<(24+b->endbit);
435 0 : if(bits>8){
436 0 : ret|=b->ptr[1]<<(16+b->endbit);
437 0 : if(bits>16){
438 0 : ret|=b->ptr[2]<<(8+b->endbit);
439 0 : if(bits>24){
440 0 : ret|=b->ptr[3]<<(b->endbit);
441 0 : if(bits>32 && b->endbit)
442 0 : ret|=b->ptr[4]>>(8-b->endbit);
443 : }
444 : }
445 : }
446 0 : ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1);
447 :
448 0 : b->ptr+=bits/8;
449 0 : b->endbyte+=bits/8;
450 0 : b->endbit=bits&7;
451 0 : return ret;
452 :
453 : overflow:
454 : err:
455 0 : b->ptr=NULL;
456 0 : b->endbyte=b->storage;
457 0 : b->endbit=1;
458 0 : return -1L;
459 : }
460 :
461 0 : long oggpack_read1(oggpack_buffer *b){
462 : long ret;
463 :
464 0 : if(b->endbyte >= b->storage) goto overflow;
465 0 : ret=(b->ptr[0]>>b->endbit)&1;
466 :
467 0 : b->endbit++;
468 0 : if(b->endbit>7){
469 0 : b->endbit=0;
470 0 : b->ptr++;
471 0 : b->endbyte++;
472 : }
473 0 : return ret;
474 :
475 : overflow:
476 0 : b->ptr=NULL;
477 0 : b->endbyte=b->storage;
478 0 : b->endbit=1;
479 0 : return -1L;
480 : }
481 :
482 0 : long oggpackB_read1(oggpack_buffer *b){
483 : long ret;
484 :
485 0 : if(b->endbyte >= b->storage) goto overflow;
486 0 : ret=(b->ptr[0]>>(7-b->endbit))&1;
487 :
488 0 : b->endbit++;
489 0 : if(b->endbit>7){
490 0 : b->endbit=0;
491 0 : b->ptr++;
492 0 : b->endbyte++;
493 : }
494 0 : return ret;
495 :
496 : overflow:
497 0 : b->ptr=NULL;
498 0 : b->endbyte=b->storage;
499 0 : b->endbit=1;
500 0 : return -1L;
501 : }
502 :
503 0 : long oggpack_bytes(oggpack_buffer *b){
504 0 : return(b->endbyte+(b->endbit+7)/8);
505 : }
506 :
507 0 : long oggpack_bits(oggpack_buffer *b){
508 0 : return(b->endbyte*8+b->endbit);
509 : }
510 :
511 0 : long oggpackB_bytes(oggpack_buffer *b){
512 0 : return oggpack_bytes(b);
513 : }
514 :
515 0 : long oggpackB_bits(oggpack_buffer *b){
516 0 : return oggpack_bits(b);
517 : }
518 :
519 0 : unsigned char *oggpack_get_buffer(oggpack_buffer *b){
520 0 : return(b->buffer);
521 : }
522 :
523 0 : unsigned char *oggpackB_get_buffer(oggpack_buffer *b){
524 0 : return oggpack_get_buffer(b);
525 : }
526 :
527 : /* Self test of the bitwise routines; everything else is based on
528 : them, so they damned well better be solid. */
529 :
530 : #ifdef _V_SELFTEST
531 : #include <stdio.h>
532 :
533 : static int ilog(unsigned int v){
534 : int ret=0;
535 : while(v){
536 : ret++;
537 : v>>=1;
538 : }
539 : return(ret);
540 : }
541 :
542 : oggpack_buffer o;
543 : oggpack_buffer r;
544 :
545 : void report(char *in){
546 : fprintf(stderr,"%s",in);
547 : exit(1);
548 : }
549 :
550 : void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){
551 : long bytes,i;
552 : unsigned char *buffer;
553 :
554 : oggpack_reset(&o);
555 : for(i=0;i<vals;i++)
556 : oggpack_write(&o,b[i],bits?bits:ilog(b[i]));
557 : buffer=oggpack_get_buffer(&o);
558 : bytes=oggpack_bytes(&o);
559 : if(bytes!=compsize)report("wrong number of bytes!\n");
560 : for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){
561 : for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]);
562 : report("wrote incorrect value!\n");
563 : }
564 : oggpack_readinit(&r,buffer,bytes);
565 : for(i=0;i<vals;i++){
566 : int tbit=bits?bits:ilog(b[i]);
567 : if(oggpack_look(&r,tbit)==-1)
568 : report("out of data!\n");
569 : if(oggpack_look(&r,tbit)!=(b[i]&mask[tbit]))
570 : report("looked at incorrect value!\n");
571 : if(tbit==1)
572 : if(oggpack_look1(&r)!=(b[i]&mask[tbit]))
573 : report("looked at single bit incorrect value!\n");
574 : if(tbit==1){
575 : if(oggpack_read1(&r)!=(b[i]&mask[tbit]))
576 : report("read incorrect single bit value!\n");
577 : }else{
578 : if(oggpack_read(&r,tbit)!=(b[i]&mask[tbit]))
579 : report("read incorrect value!\n");
580 : }
581 : }
582 : if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
583 : }
584 :
585 : void cliptestB(unsigned long *b,int vals,int bits,int *comp,int compsize){
586 : long bytes,i;
587 : unsigned char *buffer;
588 :
589 : oggpackB_reset(&o);
590 : for(i=0;i<vals;i++)
591 : oggpackB_write(&o,b[i],bits?bits:ilog(b[i]));
592 : buffer=oggpackB_get_buffer(&o);
593 : bytes=oggpackB_bytes(&o);
594 : if(bytes!=compsize)report("wrong number of bytes!\n");
595 : for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){
596 : for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]);
597 : report("wrote incorrect value!\n");
598 : }
599 : oggpackB_readinit(&r,buffer,bytes);
600 : for(i=0;i<vals;i++){
601 : int tbit=bits?bits:ilog(b[i]);
602 : if(oggpackB_look(&r,tbit)==-1)
603 : report("out of data!\n");
604 : if(oggpackB_look(&r,tbit)!=(b[i]&mask[tbit]))
605 : report("looked at incorrect value!\n");
606 : if(tbit==1)
607 : if(oggpackB_look1(&r)!=(b[i]&mask[tbit]))
608 : report("looked at single bit incorrect value!\n");
609 : if(tbit==1){
610 : if(oggpackB_read1(&r)!=(b[i]&mask[tbit]))
611 : report("read incorrect single bit value!\n");
612 : }else{
613 : if(oggpackB_read(&r,tbit)!=(b[i]&mask[tbit]))
614 : report("read incorrect value!\n");
615 : }
616 : }
617 : if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n");
618 : }
619 :
620 : void copytest(int prefill, int copy){
621 : oggpack_buffer source_write;
622 : oggpack_buffer dest_write;
623 : oggpack_buffer source_read;
624 : oggpack_buffer dest_read;
625 : unsigned char *source;
626 : unsigned char *dest;
627 : long source_bytes,dest_bytes;
628 : int i;
629 :
630 : oggpack_writeinit(&source_write);
631 : oggpack_writeinit(&dest_write);
632 :
633 : for(i=0;i<(prefill+copy+7)/8;i++)
634 : oggpack_write(&source_write,(i^0x5a)&0xff,8);
635 : source=oggpack_get_buffer(&source_write);
636 : source_bytes=oggpack_bytes(&source_write);
637 :
638 : /* prefill */
639 : oggpack_writecopy(&dest_write,source,prefill);
640 :
641 : /* check buffers; verify end byte masking */
642 : dest=oggpack_get_buffer(&dest_write);
643 : dest_bytes=oggpack_bytes(&dest_write);
644 : if(dest_bytes!=(prefill+7)/8){
645 : fprintf(stderr,"wrong number of bytes after prefill! %ld!=%d\n",dest_bytes,(prefill+7)/8);
646 : exit(1);
647 : }
648 : oggpack_readinit(&source_read,source,source_bytes);
649 : oggpack_readinit(&dest_read,dest,dest_bytes);
650 :
651 : for(i=0;i<prefill;i+=8){
652 : int s=oggpack_read(&source_read,prefill-i<8?prefill-i:8);
653 : int d=oggpack_read(&dest_read,prefill-i<8?prefill-i:8);
654 : if(s!=d){
655 : fprintf(stderr,"prefill=%d mismatch! byte %d, %x!=%x\n",prefill,i/8,s,d);
656 : exit(1);
657 : }
658 : }
659 : if(prefill<dest_bytes){
660 : if(oggpack_read(&dest_read,dest_bytes-prefill)!=0){
661 : fprintf(stderr,"prefill=%d mismatch! trailing bits not zero\n",prefill);
662 : exit(1);
663 : }
664 : }
665 :
666 : /* second copy */
667 : oggpack_writecopy(&dest_write,source,copy);
668 :
669 : /* check buffers; verify end byte masking */
670 : dest=oggpack_get_buffer(&dest_write);
671 : dest_bytes=oggpack_bytes(&dest_write);
672 : if(dest_bytes!=(copy+prefill+7)/8){
673 : fprintf(stderr,"wrong number of bytes after prefill+copy! %ld!=%d\n",dest_bytes,(copy+prefill+7)/8);
674 : exit(1);
675 : }
676 : oggpack_readinit(&source_read,source,source_bytes);
677 : oggpack_readinit(&dest_read,dest,dest_bytes);
678 :
679 : for(i=0;i<prefill;i+=8){
680 : int s=oggpack_read(&source_read,prefill-i<8?prefill-i:8);
681 : int d=oggpack_read(&dest_read,prefill-i<8?prefill-i:8);
682 : if(s!=d){
683 : fprintf(stderr,"prefill=%d mismatch! byte %d, %x!=%x\n",prefill,i/8,s,d);
684 : exit(1);
685 : }
686 : }
687 :
688 : oggpack_readinit(&source_read,source,source_bytes);
689 : for(i=0;i<copy;i+=8){
690 : int s=oggpack_read(&source_read,copy-i<8?copy-i:8);
691 : int d=oggpack_read(&dest_read,copy-i<8?copy-i:8);
692 : if(s!=d){
693 : fprintf(stderr,"prefill=%d copy=%d mismatch! byte %d, %x!=%x\n",prefill,copy,i/8,s,d);
694 : exit(1);
695 : }
696 : }
697 :
698 : if(copy+prefill<dest_bytes){
699 : if(oggpack_read(&dest_read,dest_bytes-copy-prefill)!=0){
700 : fprintf(stderr,"prefill=%d copy=%d mismatch! trailing bits not zero\n",prefill,copy);
701 : exit(1);
702 : }
703 : }
704 :
705 : oggpack_writeclear(&source_write);
706 : oggpack_writeclear(&dest_write);
707 :
708 :
709 : }
710 :
711 : void copytestB(int prefill, int copy){
712 : oggpack_buffer source_write;
713 : oggpack_buffer dest_write;
714 : oggpack_buffer source_read;
715 : oggpack_buffer dest_read;
716 : unsigned char *source;
717 : unsigned char *dest;
718 : long source_bytes,dest_bytes;
719 : int i;
720 :
721 : oggpackB_writeinit(&source_write);
722 : oggpackB_writeinit(&dest_write);
723 :
724 : for(i=0;i<(prefill+copy+7)/8;i++)
725 : oggpackB_write(&source_write,(i^0x5a)&0xff,8);
726 : source=oggpackB_get_buffer(&source_write);
727 : source_bytes=oggpackB_bytes(&source_write);
728 :
729 : /* prefill */
730 : oggpackB_writecopy(&dest_write,source,prefill);
731 :
732 : /* check buffers; verify end byte masking */
733 : dest=oggpackB_get_buffer(&dest_write);
734 : dest_bytes=oggpackB_bytes(&dest_write);
735 : if(dest_bytes!=(prefill+7)/8){
736 : fprintf(stderr,"wrong number of bytes after prefill! %ld!=%d\n",dest_bytes,(prefill+7)/8);
737 : exit(1);
738 : }
739 : oggpackB_readinit(&source_read,source,source_bytes);
740 : oggpackB_readinit(&dest_read,dest,dest_bytes);
741 :
742 : for(i=0;i<prefill;i+=8){
743 : int s=oggpackB_read(&source_read,prefill-i<8?prefill-i:8);
744 : int d=oggpackB_read(&dest_read,prefill-i<8?prefill-i:8);
745 : if(s!=d){
746 : fprintf(stderr,"prefill=%d mismatch! byte %d, %x!=%x\n",prefill,i/8,s,d);
747 : exit(1);
748 : }
749 : }
750 : if(prefill<dest_bytes){
751 : if(oggpackB_read(&dest_read,dest_bytes-prefill)!=0){
752 : fprintf(stderr,"prefill=%d mismatch! trailing bits not zero\n",prefill);
753 : exit(1);
754 : }
755 : }
756 :
757 : /* second copy */
758 : oggpackB_writecopy(&dest_write,source,copy);
759 :
760 : /* check buffers; verify end byte masking */
761 : dest=oggpackB_get_buffer(&dest_write);
762 : dest_bytes=oggpackB_bytes(&dest_write);
763 : if(dest_bytes!=(copy+prefill+7)/8){
764 : fprintf(stderr,"wrong number of bytes after prefill+copy! %ld!=%d\n",dest_bytes,(copy+prefill+7)/8);
765 : exit(1);
766 : }
767 : oggpackB_readinit(&source_read,source,source_bytes);
768 : oggpackB_readinit(&dest_read,dest,dest_bytes);
769 :
770 : for(i=0;i<prefill;i+=8){
771 : int s=oggpackB_read(&source_read,prefill-i<8?prefill-i:8);
772 : int d=oggpackB_read(&dest_read,prefill-i<8?prefill-i:8);
773 : if(s!=d){
774 : fprintf(stderr,"prefill=%d mismatch! byte %d, %x!=%x\n",prefill,i/8,s,d);
775 : exit(1);
776 : }
777 : }
778 :
779 : oggpackB_readinit(&source_read,source,source_bytes);
780 : for(i=0;i<copy;i+=8){
781 : int s=oggpackB_read(&source_read,copy-i<8?copy-i:8);
782 : int d=oggpackB_read(&dest_read,copy-i<8?copy-i:8);
783 : if(s!=d){
784 : fprintf(stderr,"prefill=%d copy=%d mismatch! byte %d, %x!=%x\n",prefill,copy,i/8,s,d);
785 : exit(1);
786 : }
787 : }
788 :
789 : if(copy+prefill<dest_bytes){
790 : if(oggpackB_read(&dest_read,dest_bytes-copy-prefill)!=0){
791 : fprintf(stderr,"prefill=%d copy=%d mismatch! trailing bits not zero\n",prefill,copy);
792 : exit(1);
793 : }
794 : }
795 :
796 : oggpackB_writeclear(&source_write);
797 : oggpackB_writeclear(&dest_write);
798 :
799 : }
800 :
801 : int main(void){
802 : unsigned char *buffer;
803 : long bytes,i,j;
804 : static unsigned long testbuffer1[]=
805 : {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7,
806 : 567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4};
807 : int test1size=43;
808 :
809 : static unsigned long testbuffer2[]=
810 : {216531625L,1237861823,56732452,131,3212421,12325343,34547562,12313212,
811 : 1233432,534,5,346435231,14436467,7869299,76326614,167548585,
812 : 85525151,0,12321,1,349528352};
813 : int test2size=21;
814 :
815 : static unsigned long testbuffer3[]=
816 : {1,0,14,0,1,0,12,0,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1,
817 : 0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1};
818 : int test3size=56;
819 :
820 : static unsigned long large[]=
821 : {2136531625L,2137861823,56732452,131,3212421,12325343,34547562,12313212,
822 : 1233432,534,5,2146435231,14436467,7869299,76326614,167548585,
823 : 85525151,0,12321,1,2146528352};
824 :
825 : int onesize=33;
826 : static int one[33]={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40,
827 : 34,242,223,136,35,222,211,86,171,50,225,135,214,75,172,
828 : 223,4};
829 : static int oneB[33]={150,101,131,33,203,15,204,216,105,193,156,65,84,85,222,
830 : 8,139,145,227,126,34,55,244,171,85,100,39,195,173,18,
831 : 245,251,128};
832 :
833 : int twosize=6;
834 : static int two[6]={61,255,255,251,231,29};
835 : static int twoB[6]={247,63,255,253,249,120};
836 :
837 : int threesize=54;
838 : static int three[54]={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254,
839 : 142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83,
840 : 58,135,196,61,55,129,183,54,101,100,170,37,127,126,10,
841 : 100,52,4,14,18,86,77,1};
842 : static int threeB[54]={206,128,42,153,57,8,183,251,13,89,36,30,32,144,183,
843 : 130,59,240,121,59,85,223,19,228,180,134,33,107,74,98,
844 : 233,253,196,135,63,2,110,114,50,155,90,127,37,170,104,
845 : 200,20,254,4,58,106,176,144,0};
846 :
847 : int foursize=38;
848 : static int four[38]={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72,
849 : 132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169,
850 : 28,2,133,0,1};
851 : static int fourB[38]={36,48,102,83,243,24,52,7,4,35,132,10,145,21,2,93,2,41,
852 : 1,219,184,16,33,184,54,149,170,132,18,30,29,98,229,67,
853 : 129,10,4,32};
854 :
855 : int fivesize=45;
856 : static int five[45]={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62,
857 : 241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169,
858 : 84,75,159,2,1,0,132,192,8,0,0,18,22};
859 : static int fiveB[45]={1,84,145,111,245,100,128,8,56,36,40,71,126,78,213,226,
860 : 124,105,12,0,133,128,0,162,233,242,67,152,77,205,77,
861 : 172,150,169,129,79,128,0,6,4,32,0,27,9,0};
862 :
863 : int sixsize=7;
864 : static int six[7]={17,177,170,242,169,19,148};
865 : static int sixB[7]={136,141,85,79,149,200,41};
866 :
867 : /* Test read/write together */
868 : /* Later we test against pregenerated bitstreams */
869 : oggpack_writeinit(&o);
870 :
871 : fprintf(stderr,"\nSmall preclipped packing (LSb): ");
872 : cliptest(testbuffer1,test1size,0,one,onesize);
873 : fprintf(stderr,"ok.");
874 :
875 : fprintf(stderr,"\nNull bit call (LSb): ");
876 : cliptest(testbuffer3,test3size,0,two,twosize);
877 : fprintf(stderr,"ok.");
878 :
879 : fprintf(stderr,"\nLarge preclipped packing (LSb): ");
880 : cliptest(testbuffer2,test2size,0,three,threesize);
881 : fprintf(stderr,"ok.");
882 :
883 : fprintf(stderr,"\n32 bit preclipped packing (LSb): ");
884 : oggpack_reset(&o);
885 : for(i=0;i<test2size;i++)
886 : oggpack_write(&o,large[i],32);
887 : buffer=oggpack_get_buffer(&o);
888 : bytes=oggpack_bytes(&o);
889 : oggpack_readinit(&r,buffer,bytes);
890 : for(i=0;i<test2size;i++){
891 : if(oggpack_look(&r,32)==-1)report("out of data. failed!");
892 : if(oggpack_look(&r,32)!=large[i]){
893 : fprintf(stderr,"%ld != %ld (%lx!=%lx):",oggpack_look(&r,32),large[i],
894 : oggpack_look(&r,32),large[i]);
895 : report("read incorrect value!\n");
896 : }
897 : oggpack_adv(&r,32);
898 : }
899 : if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
900 : fprintf(stderr,"ok.");
901 :
902 : fprintf(stderr,"\nSmall unclipped packing (LSb): ");
903 : cliptest(testbuffer1,test1size,7,four,foursize);
904 : fprintf(stderr,"ok.");
905 :
906 : fprintf(stderr,"\nLarge unclipped packing (LSb): ");
907 : cliptest(testbuffer2,test2size,17,five,fivesize);
908 : fprintf(stderr,"ok.");
909 :
910 : fprintf(stderr,"\nSingle bit unclipped packing (LSb): ");
911 : cliptest(testbuffer3,test3size,1,six,sixsize);
912 : fprintf(stderr,"ok.");
913 :
914 : fprintf(stderr,"\nTesting read past end (LSb): ");
915 : oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
916 : for(i=0;i<64;i++){
917 : if(oggpack_read(&r,1)!=0){
918 : fprintf(stderr,"failed; got -1 prematurely.\n");
919 : exit(1);
920 : }
921 : }
922 : if(oggpack_look(&r,1)!=-1 ||
923 : oggpack_read(&r,1)!=-1){
924 : fprintf(stderr,"failed; read past end without -1.\n");
925 : exit(1);
926 : }
927 : oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
928 : if(oggpack_read(&r,30)!=0 || oggpack_read(&r,16)!=0){
929 : fprintf(stderr,"failed 2; got -1 prematurely.\n");
930 : exit(1);
931 : }
932 :
933 : if(oggpack_look(&r,18)!=0 ||
934 : oggpack_look(&r,18)!=0){
935 : fprintf(stderr,"failed 3; got -1 prematurely.\n");
936 : exit(1);
937 : }
938 : if(oggpack_look(&r,19)!=-1 ||
939 : oggpack_look(&r,19)!=-1){
940 : fprintf(stderr,"failed; read past end without -1.\n");
941 : exit(1);
942 : }
943 : if(oggpack_look(&r,32)!=-1 ||
944 : oggpack_look(&r,32)!=-1){
945 : fprintf(stderr,"failed; read past end without -1.\n");
946 : exit(1);
947 : }
948 : oggpack_writeclear(&o);
949 : fprintf(stderr,"ok.");
950 :
951 : /* this is partly glassbox; we're mostly concerned about the allocation boundaries */
952 :
953 : fprintf(stderr,"\nTesting aligned writecopies (LSb): ");
954 : for(i=0;i<71;i++)
955 : for(j=0;j<5;j++)
956 : copytest(j*8,i);
957 : for(i=BUFFER_INCREMENT*8-71;i<BUFFER_INCREMENT*8+71;i++)
958 : for(j=0;j<5;j++)
959 : copytest(j*8,i);
960 : fprintf(stderr,"ok. ");
961 :
962 : fprintf(stderr,"\nTesting unaligned writecopies (LSb): ");
963 : for(i=0;i<71;i++)
964 : for(j=1;j<40;j++)
965 : if(j&0x7)
966 : copytest(j,i);
967 : for(i=BUFFER_INCREMENT*8-71;i<BUFFER_INCREMENT*8+71;i++)
968 : for(j=1;j<40;j++)
969 : if(j&0x7)
970 : copytest(j,i);
971 :
972 : fprintf(stderr,"ok. \n");
973 :
974 :
975 : /********** lazy, cut-n-paste retest with MSb packing ***********/
976 :
977 : /* Test read/write together */
978 : /* Later we test against pregenerated bitstreams */
979 : oggpackB_writeinit(&o);
980 :
981 : fprintf(stderr,"\nSmall preclipped packing (MSb): ");
982 : cliptestB(testbuffer1,test1size,0,oneB,onesize);
983 : fprintf(stderr,"ok.");
984 :
985 : fprintf(stderr,"\nNull bit call (MSb): ");
986 : cliptestB(testbuffer3,test3size,0,twoB,twosize);
987 : fprintf(stderr,"ok.");
988 :
989 : fprintf(stderr,"\nLarge preclipped packing (MSb): ");
990 : cliptestB(testbuffer2,test2size,0,threeB,threesize);
991 : fprintf(stderr,"ok.");
992 :
993 : fprintf(stderr,"\n32 bit preclipped packing (MSb): ");
994 : oggpackB_reset(&o);
995 : for(i=0;i<test2size;i++)
996 : oggpackB_write(&o,large[i],32);
997 : buffer=oggpackB_get_buffer(&o);
998 : bytes=oggpackB_bytes(&o);
999 : oggpackB_readinit(&r,buffer,bytes);
1000 : for(i=0;i<test2size;i++){
1001 : if(oggpackB_look(&r,32)==-1)report("out of data. failed!");
1002 : if(oggpackB_look(&r,32)!=large[i]){
1003 : fprintf(stderr,"%ld != %ld (%lx!=%lx):",oggpackB_look(&r,32),large[i],
1004 : oggpackB_look(&r,32),large[i]);
1005 : report("read incorrect value!\n");
1006 : }
1007 : oggpackB_adv(&r,32);
1008 : }
1009 : if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n");
1010 : fprintf(stderr,"ok.");
1011 :
1012 : fprintf(stderr,"\nSmall unclipped packing (MSb): ");
1013 : cliptestB(testbuffer1,test1size,7,fourB,foursize);
1014 : fprintf(stderr,"ok.");
1015 :
1016 : fprintf(stderr,"\nLarge unclipped packing (MSb): ");
1017 : cliptestB(testbuffer2,test2size,17,fiveB,fivesize);
1018 : fprintf(stderr,"ok.");
1019 :
1020 : fprintf(stderr,"\nSingle bit unclipped packing (MSb): ");
1021 : cliptestB(testbuffer3,test3size,1,sixB,sixsize);
1022 : fprintf(stderr,"ok.");
1023 :
1024 : fprintf(stderr,"\nTesting read past end (MSb): ");
1025 : oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
1026 : for(i=0;i<64;i++){
1027 : if(oggpackB_read(&r,1)!=0){
1028 : fprintf(stderr,"failed; got -1 prematurely.\n");
1029 : exit(1);
1030 : }
1031 : }
1032 : if(oggpackB_look(&r,1)!=-1 ||
1033 : oggpackB_read(&r,1)!=-1){
1034 : fprintf(stderr,"failed; read past end without -1.\n");
1035 : exit(1);
1036 : }
1037 : oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
1038 : if(oggpackB_read(&r,30)!=0 || oggpackB_read(&r,16)!=0){
1039 : fprintf(stderr,"failed 2; got -1 prematurely.\n");
1040 : exit(1);
1041 : }
1042 :
1043 : if(oggpackB_look(&r,18)!=0 ||
1044 : oggpackB_look(&r,18)!=0){
1045 : fprintf(stderr,"failed 3; got -1 prematurely.\n");
1046 : exit(1);
1047 : }
1048 : if(oggpackB_look(&r,19)!=-1 ||
1049 : oggpackB_look(&r,19)!=-1){
1050 : fprintf(stderr,"failed; read past end without -1.\n");
1051 : exit(1);
1052 : }
1053 : if(oggpackB_look(&r,32)!=-1 ||
1054 : oggpackB_look(&r,32)!=-1){
1055 : fprintf(stderr,"failed; read past end without -1.\n");
1056 : exit(1);
1057 : }
1058 : fprintf(stderr,"ok.");
1059 : oggpackB_writeclear(&o);
1060 :
1061 : /* this is partly glassbox; we're mostly concerned about the allocation boundaries */
1062 :
1063 : fprintf(stderr,"\nTesting aligned writecopies (MSb): ");
1064 : for(i=0;i<71;i++)
1065 : for(j=0;j<5;j++)
1066 : copytestB(j*8,i);
1067 : for(i=BUFFER_INCREMENT*8-71;i<BUFFER_INCREMENT*8+71;i++)
1068 : for(j=0;j<5;j++)
1069 : copytestB(j*8,i);
1070 : fprintf(stderr,"ok. ");
1071 :
1072 : fprintf(stderr,"\nTesting unaligned writecopies (MSb): ");
1073 : for(i=0;i<71;i++)
1074 : for(j=1;j<40;j++)
1075 : if(j&0x7)
1076 : copytestB(j,i);
1077 : for(i=BUFFER_INCREMENT*8-71;i<BUFFER_INCREMENT*8+71;i++)
1078 : for(j=1;j<40;j++)
1079 : if(j&0x7)
1080 : copytestB(j,i);
1081 :
1082 : fprintf(stderr,"ok. \n\n");
1083 :
1084 : return(0);
1085 : }
1086 : #endif /* _V_SELFTEST */
1087 :
1088 : #undef BUFFER_INCREMENT
|