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