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