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$
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
oggpack_writeinit(oggpack_buffer * b)40 void oggpack_writeinit(oggpack_buffer *b){
41 memset(b,0,sizeof(*b));
42 b->ptr=b->buffer=_ogg_malloc(BUFFER_INCREMENT);
43 b->buffer[0]='\0';
44 b->storage=BUFFER_INCREMENT;
45 }
46
oggpackB_writeinit(oggpack_buffer * b)47 void oggpackB_writeinit(oggpack_buffer *b){
48 oggpack_writeinit(b);
49 }
50
oggpack_writecheck(oggpack_buffer * b)51 int oggpack_writecheck(oggpack_buffer *b){
52 if(!b->ptr || !b->storage)return -1;
53 return 0;
54 }
55
oggpackB_writecheck(oggpack_buffer * b)56 int oggpackB_writecheck(oggpack_buffer *b){
57 return oggpack_writecheck(b);
58 }
59
oggpack_writetrunc(oggpack_buffer * b,long bits)60 void oggpack_writetrunc(oggpack_buffer *b,long bits){
61 long bytes=bits>>3;
62 if(b->ptr){
63 bits-=bytes*8;
64 b->ptr=b->buffer+bytes;
65 b->endbit=bits;
66 b->endbyte=bytes;
67 *b->ptr&=mask[bits];
68 }
69 }
70
oggpackB_writetrunc(oggpack_buffer * b,long bits)71 void oggpackB_writetrunc(oggpack_buffer *b,long bits){
72 long bytes=bits>>3;
73 if(b->ptr){
74 bits-=bytes*8;
75 b->ptr=b->buffer+bytes;
76 b->endbit=bits;
77 b->endbyte=bytes;
78 *b->ptr&=mask8B[bits];
79 }
80 }
81
82 /* Takes only up to 32 bits. */
oggpack_write(oggpack_buffer * b,unsigned long value,int bits)83 void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){
84 if(bits<0 || bits>32) goto err;
85 if(b->endbyte>=b->storage-4){
86 void *ret;
87 if(!b->ptr)return;
88 if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err;
89 ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
90 if(!ret) goto err;
91 b->buffer=ret;
92 b->storage+=BUFFER_INCREMENT;
93 b->ptr=b->buffer+b->endbyte;
94 }
95
96 value&=mask[bits];
97 bits+=b->endbit;
98
99 b->ptr[0]|=value<<b->endbit;
100
101 if(bits>=8){
102 b->ptr[1]=(unsigned char)(value>>(8-b->endbit));
103 if(bits>=16){
104 b->ptr[2]=(unsigned char)(value>>(16-b->endbit));
105 if(bits>=24){
106 b->ptr[3]=(unsigned char)(value>>(24-b->endbit));
107 if(bits>=32){
108 if(b->endbit)
109 b->ptr[4]=(unsigned char)(value>>(32-b->endbit));
110 else
111 b->ptr[4]=0;
112 }
113 }
114 }
115 }
116
117 b->endbyte+=bits/8;
118 b->ptr+=bits/8;
119 b->endbit=bits&7;
120 return;
121 err:
122 oggpack_writeclear(b);
123 }
124
125 /* Takes only up to 32 bits. */
oggpackB_write(oggpack_buffer * b,unsigned long value,int bits)126 void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){
127 if(bits<0 || bits>32) goto err;
128 if(b->endbyte>=b->storage-4){
129 void *ret;
130 if(!b->ptr)return;
131 if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err;
132 ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
133 if(!ret) goto err;
134 b->buffer=ret;
135 b->storage+=BUFFER_INCREMENT;
136 b->ptr=b->buffer+b->endbyte;
137 }
138
139 value=(value&mask[bits])<<(32-bits);
140 bits+=b->endbit;
141
142 b->ptr[0]|=value>>(24+b->endbit);
143
144 if(bits>=8){
145 b->ptr[1]=(unsigned char)(value>>(16+b->endbit));
146 if(bits>=16){
147 b->ptr[2]=(unsigned char)(value>>(8+b->endbit));
148 if(bits>=24){
149 b->ptr[3]=(unsigned char)(value>>(b->endbit));
150 if(bits>=32){
151 if(b->endbit)
152 b->ptr[4]=(unsigned char)(value<<(8-b->endbit));
153 else
154 b->ptr[4]=0;
155 }
156 }
157 }
158 }
159
160 b->endbyte+=bits/8;
161 b->ptr+=bits/8;
162 b->endbit=bits&7;
163 return;
164 err:
165 oggpack_writeclear(b);
166 }
167
oggpack_writealign(oggpack_buffer * b)168 void oggpack_writealign(oggpack_buffer *b){
169 int bits=8-b->endbit;
170 if(bits<8)
171 oggpack_write(b,0,bits);
172 }
173
oggpackB_writealign(oggpack_buffer * b)174 void oggpackB_writealign(oggpack_buffer *b){
175 int bits=8-b->endbit;
176 if(bits<8)
177 oggpackB_write(b,0,bits);
178 }
179
oggpack_writecopy_helper(oggpack_buffer * b,void * source,long bits,void (* w)(oggpack_buffer *,unsigned long,int),int msb)180 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 unsigned char *ptr=(unsigned char *)source;
188
189 long bytes=bits/8;
190 long pbytes=(b->endbit+bits)/8;
191 bits-=bytes*8;
192
193 /* expand storage up-front */
194 if(b->endbyte+pbytes>=b->storage){
195 void *ret;
196 if(!b->ptr) goto err;
197 if(b->storage>b->endbyte+pbytes+BUFFER_INCREMENT) goto err;
198 b->storage=b->endbyte+pbytes+BUFFER_INCREMENT;
199 ret=_ogg_realloc(b->buffer,b->storage);
200 if(!ret) goto err;
201 b->buffer=ret;
202 b->ptr=b->buffer+b->endbyte;
203 }
204
205 /* copy whole octets */
206 if(b->endbit){
207 int i;
208 /* unaligned copy. Do it the hard way. */
209 for(i=0;i<bytes;i++)
210 w(b,(unsigned long)(ptr[i]),8);
211 }else{
212 /* aligned block copy */
213 memmove(b->ptr,source,bytes);
214 b->ptr+=bytes;
215 b->endbyte+=bytes;
216 *b->ptr=0;
217 }
218
219 /* copy trailing bits */
220 if(bits){
221 if(msb)
222 w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits);
223 else
224 w(b,(unsigned long)(ptr[bytes]),bits);
225 }
226 return;
227 err:
228 oggpack_writeclear(b);
229 }
230
oggpack_writecopy(oggpack_buffer * b,void * source,long bits)231 void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){
232 oggpack_writecopy_helper(b,source,bits,oggpack_write,0);
233 }
234
oggpackB_writecopy(oggpack_buffer * b,void * source,long bits)235 void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits){
236 oggpack_writecopy_helper(b,source,bits,oggpackB_write,1);
237 }
238
oggpack_reset(oggpack_buffer * b)239 void oggpack_reset(oggpack_buffer *b){
240 if(!b->ptr)return;
241 b->ptr=b->buffer;
242 b->buffer[0]=0;
243 b->endbit=b->endbyte=0;
244 }
245
oggpackB_reset(oggpack_buffer * b)246 void oggpackB_reset(oggpack_buffer *b){
247 oggpack_reset(b);
248 }
249
oggpack_writeclear(oggpack_buffer * b)250 void oggpack_writeclear(oggpack_buffer *b){
251 if(b->buffer)_ogg_free(b->buffer);
252 memset(b,0,sizeof(*b));
253 }
254
oggpackB_writeclear(oggpack_buffer * b)255 void oggpackB_writeclear(oggpack_buffer *b){
256 oggpack_writeclear(b);
257 }
258
oggpack_readinit(oggpack_buffer * b,unsigned char * buf,int bytes)259 void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
260 memset(b,0,sizeof(*b));
261 b->buffer=b->ptr=buf;
262 b->storage=bytes;
263 }
264
oggpackB_readinit(oggpack_buffer * b,unsigned char * buf,int bytes)265 void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
266 oggpack_readinit(b,buf,bytes);
267 }
268
269 /* Read in bits without advancing the bitptr; bits <= 32 */
oggpack_look(oggpack_buffer * b,int bits)270 long oggpack_look(oggpack_buffer *b,int bits){
271 unsigned long ret;
272 unsigned long m;
273
274 if(bits<0 || bits>32) return -1;
275 m=mask[bits];
276 bits+=b->endbit;
277
278 if(b->endbyte >= b->storage-4){
279 /* not the main path */
280 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 else if(!bits)return(0L);
284 }
285
286 ret=b->ptr[0]>>b->endbit;
287 if(bits>8){
288 ret|=b->ptr[1]<<(8-b->endbit);
289 if(bits>16){
290 ret|=b->ptr[2]<<(16-b->endbit);
291 if(bits>24){
292 ret|=b->ptr[3]<<(24-b->endbit);
293 if(bits>32 && b->endbit)
294 ret|=b->ptr[4]<<(32-b->endbit);
295 }
296 }
297 }
298 return(m&ret);
299 }
300
301 /* Read in bits without advancing the bitptr; bits <= 32 */
oggpackB_look(oggpack_buffer * b,int bits)302 long oggpackB_look(oggpack_buffer *b,int bits){
303 unsigned long ret;
304 int m=32-bits;
305
306 if(m<0 || m>32) return -1;
307 bits+=b->endbit;
308
309 if(b->endbyte >= b->storage-4){
310 /* not the main path */
311 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 else if(!bits)return(0L);
315 }
316
317 ret=b->ptr[0]<<(24+b->endbit);
318 if(bits>8){
319 ret|=b->ptr[1]<<(16+b->endbit);
320 if(bits>16){
321 ret|=b->ptr[2]<<(8+b->endbit);
322 if(bits>24){
323 ret|=b->ptr[3]<<(b->endbit);
324 if(bits>32 && b->endbit)
325 ret|=b->ptr[4]>>(8-b->endbit);
326 }
327 }
328 }
329 return ((ret&0xffffffff)>>(m>>1))>>((m+1)>>1);
330 }
331
oggpack_look1(oggpack_buffer * b)332 long oggpack_look1(oggpack_buffer *b){
333 if(b->endbyte>=b->storage)return(-1);
334 return((b->ptr[0]>>b->endbit)&1);
335 }
336
oggpackB_look1(oggpack_buffer * b)337 long oggpackB_look1(oggpack_buffer *b){
338 if(b->endbyte>=b->storage)return(-1);
339 return((b->ptr[0]>>(7-b->endbit))&1);
340 }
341
oggpack_adv(oggpack_buffer * b,int bits)342 void oggpack_adv(oggpack_buffer *b,int bits){
343 bits+=b->endbit;
344
345 if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
346
347 b->ptr+=bits/8;
348 b->endbyte+=bits/8;
349 b->endbit=bits&7;
350 return;
351
352 overflow:
353 b->ptr=NULL;
354 b->endbyte=b->storage;
355 b->endbit=1;
356 }
357
oggpackB_adv(oggpack_buffer * b,int bits)358 void oggpackB_adv(oggpack_buffer *b,int bits){
359 oggpack_adv(b,bits);
360 }
361
oggpack_adv1(oggpack_buffer * b)362 void oggpack_adv1(oggpack_buffer *b){
363 if(++(b->endbit)>7){
364 b->endbit=0;
365 b->ptr++;
366 b->endbyte++;
367 }
368 }
369
oggpackB_adv1(oggpack_buffer * b)370 void oggpackB_adv1(oggpack_buffer *b){
371 oggpack_adv1(b);
372 }
373
374 /* bits <= 32 */
oggpack_read(oggpack_buffer * b,int bits)375 long oggpack_read(oggpack_buffer *b,int bits){
376 long ret;
377 unsigned long m;
378
379 if(bits<0 || bits>32) goto err;
380 m=mask[bits];
381 bits+=b->endbit;
382
383 if(b->endbyte >= b->storage-4){
384 /* not the main path */
385 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 else if(!bits)return(0L);
389 }
390
391 ret=b->ptr[0]>>b->endbit;
392 if(bits>8){
393 ret|=b->ptr[1]<<(8-b->endbit);
394 if(bits>16){
395 ret|=b->ptr[2]<<(16-b->endbit);
396 if(bits>24){
397 ret|=b->ptr[3]<<(24-b->endbit);
398 if(bits>32 && b->endbit){
399 ret|=b->ptr[4]<<(32-b->endbit);
400 }
401 }
402 }
403 }
404 ret&=m;
405 b->ptr+=bits/8;
406 b->endbyte+=bits/8;
407 b->endbit=bits&7;
408 return ret;
409
410 overflow:
411 err:
412 b->ptr=NULL;
413 b->endbyte=b->storage;
414 b->endbit=1;
415 return -1L;
416 }
417
418 /* bits <= 32 */
oggpackB_read(oggpack_buffer * b,int bits)419 long oggpackB_read(oggpack_buffer *b,int bits){
420 long ret;
421 long m=32-bits;
422
423 if(m<0 || m>32) goto err;
424 bits+=b->endbit;
425
426 if(b->endbyte+4>=b->storage){
427 /* not the main path */
428 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 else if(!bits)return(0L);
432 }
433
434 ret=b->ptr[0]<<(24+b->endbit);
435 if(bits>8){
436 ret|=b->ptr[1]<<(16+b->endbit);
437 if(bits>16){
438 ret|=b->ptr[2]<<(8+b->endbit);
439 if(bits>24){
440 ret|=b->ptr[3]<<(b->endbit);
441 if(bits>32 && b->endbit)
442 ret|=b->ptr[4]>>(8-b->endbit);
443 }
444 }
445 }
446 ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1);
447
448 b->ptr+=bits/8;
449 b->endbyte+=bits/8;
450 b->endbit=bits&7;
451 return ret;
452
453 overflow:
454 err:
455 b->ptr=NULL;
456 b->endbyte=b->storage;
457 b->endbit=1;
458 return -1L;
459 }
460
oggpack_read1(oggpack_buffer * b)461 long oggpack_read1(oggpack_buffer *b){
462 long ret;
463
464 if(b->endbyte >= b->storage) goto overflow;
465 ret=(b->ptr[0]>>b->endbit)&1;
466
467 b->endbit++;
468 if(b->endbit>7){
469 b->endbit=0;
470 b->ptr++;
471 b->endbyte++;
472 }
473 return ret;
474
475 overflow:
476 b->ptr=NULL;
477 b->endbyte=b->storage;
478 b->endbit=1;
479 return -1L;
480 }
481
oggpackB_read1(oggpack_buffer * b)482 long oggpackB_read1(oggpack_buffer *b){
483 long ret;
484
485 if(b->endbyte >= b->storage) goto overflow;
486 ret=(b->ptr[0]>>(7-b->endbit))&1;
487
488 b->endbit++;
489 if(b->endbit>7){
490 b->endbit=0;
491 b->ptr++;
492 b->endbyte++;
493 }
494 return ret;
495
496 overflow:
497 b->ptr=NULL;
498 b->endbyte=b->storage;
499 b->endbit=1;
500 return -1L;
501 }
502
oggpack_bytes(oggpack_buffer * b)503 long oggpack_bytes(oggpack_buffer *b){
504 return(b->endbyte+(b->endbit+7)/8);
505 }
506
oggpack_bits(oggpack_buffer * b)507 long oggpack_bits(oggpack_buffer *b){
508 return(b->endbyte*8+b->endbit);
509 }
510
oggpackB_bytes(oggpack_buffer * b)511 long oggpackB_bytes(oggpack_buffer *b){
512 return oggpack_bytes(b);
513 }
514
oggpackB_bits(oggpack_buffer * b)515 long oggpackB_bits(oggpack_buffer *b){
516 return oggpack_bits(b);
517 }
518
oggpack_get_buffer(oggpack_buffer * b)519 unsigned char *oggpack_get_buffer(oggpack_buffer *b){
520 return(b->buffer);
521 }
522
oggpackB_get_buffer(oggpack_buffer * b)523 unsigned char *oggpackB_get_buffer(oggpack_buffer *b){
524 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
ilog(unsigned int v)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
report(char * in)545 void report(char *in){
546 fprintf(stderr,"%s",in);
547 exit(1);
548 }
549
cliptest(unsigned long * b,int vals,int bits,int * comp,int compsize)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
cliptestB(unsigned long * b,int vals,int bits,int * comp,int compsize)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
copytest(int prefill,int copy)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
copytestB(int prefill,int copy)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
main(void)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
1089