1/********************************************************************
2 *                                                                  *
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC 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-2009             *
9 * by the Xiph.Org Foundation http://www.xiph.org/                  *
10 *                                                                  *
11 ********************************************************************
12
13  function: packing variable sized words into an octet stream
14  last mod: $Id: bitwise.c 16051 2009-05-27 05:00:06Z xiphmont $
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 <ogg/ogg.h>
24
25#define BUFFER_INCREMENT 256
26
27static 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
36static const unsigned int mask8B[]=
37{0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};
38
39void 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
46void oggpackB_writeinit(oggpack_buffer *b){
47  oggpack_writeinit(b);
48}
49
50int oggpack_writecheck(oggpack_buffer *b){
51  if(!b->ptr || !b->storage)return -1;
52  return 0;
53}
54
55int oggpackB_writecheck(oggpack_buffer *b){
56  return oggpack_writecheck(b);
57}
58
59void 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
70void 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. */
82void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){
83  if(b->endbyte+4>=b->storage){
84    void *ret;
85    if(!b->ptr)return;
86    ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
87    if(!ret){
88      oggpack_writeclear(b);
89      return;
90    }
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}
121
122/* Takes only up to 32 bits. */
123void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){
124  if(b->endbyte+4>=b->storage){
125    void *ret;
126    if(!b->ptr)return;
127    ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
128    if(!ret){
129      oggpack_writeclear(b);
130      return;
131    }
132    b->buffer=ret;
133    b->storage+=BUFFER_INCREMENT;
134    b->ptr=b->buffer+b->endbyte;
135  }
136
137  value=(value&mask[bits])<<(32-bits);
138  bits+=b->endbit;
139
140  b->ptr[0]|=value>>(24+b->endbit);
141
142  if(bits>=8){
143    b->ptr[1]=(unsigned char)(value>>(16+b->endbit));
144    if(bits>=16){
145      b->ptr[2]=(unsigned char)(value>>(8+b->endbit));
146      if(bits>=24){
147        b->ptr[3]=(unsigned char)(value>>(b->endbit));
148        if(bits>=32){
149          if(b->endbit)
150            b->ptr[4]=(unsigned char)(value<<(8-b->endbit));
151          else
152            b->ptr[4]=0;
153        }
154      }
155    }
156  }
157
158  b->endbyte+=bits/8;
159  b->ptr+=bits/8;
160  b->endbit=bits&7;
161}
162
163void oggpack_writealign(oggpack_buffer *b){
164  int bits=8-b->endbit;
165  if(bits<8)
166    oggpack_write(b,0,bits);
167}
168
169void oggpackB_writealign(oggpack_buffer *b){
170  int bits=8-b->endbit;
171  if(bits<8)
172    oggpackB_write(b,0,bits);
173}
174
175static void oggpack_writecopy_helper(oggpack_buffer *b,
176                                     void *source,
177                                     long bits,
178                                     void (*w)(oggpack_buffer *,
179                                               unsigned long,
180                                               int),
181                                     int msb){
182  unsigned char *ptr=(unsigned char *)source;
183
184  long bytes=bits/8;
185  bits-=bytes*8;
186
187  if(b->endbit){
188    int i;
189    /* unaligned copy.  Do it the hard way. */
190    for(i=0;i<bytes;i++)
191      w(b,(unsigned long)(ptr[i]),8);
192  }else{
193    /* aligned block copy */
194    if(b->endbyte+bytes+1>=b->storage){
195      void *ret;
196      if(!b->ptr)return;
197      b->storage=b->endbyte+bytes+BUFFER_INCREMENT;
198      ret=_ogg_realloc(b->buffer,b->storage);
199      if(!ret){
200        oggpack_writeclear(b);
201        return;
202      }
203      b->buffer=ret;
204      b->ptr=b->buffer+b->endbyte;
205    }
206
207    memmove(b->ptr,source,bytes);
208    b->ptr+=bytes;
209    b->endbyte+=bytes;
210    *b->ptr=0;
211
212  }
213  if(bits){
214    if(msb)
215      w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits);
216    else
217      w(b,(unsigned long)(ptr[bytes]),bits);
218  }
219}
220
221void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){
222  oggpack_writecopy_helper(b,source,bits,oggpack_write,0);
223}
224
225void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits){
226  oggpack_writecopy_helper(b,source,bits,oggpackB_write,1);
227}
228
229void oggpack_reset(oggpack_buffer *b){
230  if(!b->ptr)return;
231  b->ptr=b->buffer;
232  b->buffer[0]=0;
233  b->endbit=b->endbyte=0;
234}
235
236void oggpackB_reset(oggpack_buffer *b){
237  oggpack_reset(b);
238}
239
240void oggpack_writeclear(oggpack_buffer *b){
241  if(b->buffer)_ogg_free(b->buffer);
242  memset(b,0,sizeof(*b));
243}
244
245void oggpackB_writeclear(oggpack_buffer *b){
246  oggpack_writeclear(b);
247}
248
249void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
250  memset(b,0,sizeof(*b));
251  b->buffer=b->ptr=buf;
252  b->storage=bytes;
253}
254
255void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
256  oggpack_readinit(b,buf,bytes);
257}
258
259/* Read in bits without advancing the bitptr; bits <= 32 */
260long oggpack_look(oggpack_buffer *b,int bits){
261  unsigned long ret;
262  unsigned long m=mask[bits];
263
264  bits+=b->endbit;
265
266  if(b->endbyte+4>=b->storage){
267    /* not the main path */
268    if(b->endbyte*8+bits>b->storage*8)return(-1);
269  }
270
271  ret=b->ptr[0]>>b->endbit;
272  if(bits>8){
273    ret|=b->ptr[1]<<(8-b->endbit);
274    if(bits>16){
275      ret|=b->ptr[2]<<(16-b->endbit);
276      if(bits>24){
277        ret|=b->ptr[3]<<(24-b->endbit);
278        if(bits>32 && b->endbit)
279          ret|=b->ptr[4]<<(32-b->endbit);
280      }
281    }
282  }
283  return(m&ret);
284}
285
286/* Read in bits without advancing the bitptr; bits <= 32 */
287long oggpackB_look(oggpack_buffer *b,int bits){
288  unsigned long ret;
289  int m=32-bits;
290
291  bits+=b->endbit;
292
293  if(b->endbyte+4>=b->storage){
294    /* not the main path */
295    if(b->endbyte*8+bits>b->storage*8)return(-1);
296  }
297
298  ret=b->ptr[0]<<(24+b->endbit);
299  if(bits>8){
300    ret|=b->ptr[1]<<(16+b->endbit);
301    if(bits>16){
302      ret|=b->ptr[2]<<(8+b->endbit);
303      if(bits>24){
304        ret|=b->ptr[3]<<(b->endbit);
305        if(bits>32 && b->endbit)
306          ret|=b->ptr[4]>>(8-b->endbit);
307      }
308    }
309  }
310  return ((ret&0xffffffff)>>(m>>1))>>((m+1)>>1);
311}
312
313long oggpack_look1(oggpack_buffer *b){
314  if(b->endbyte>=b->storage)return(-1);
315  return((b->ptr[0]>>b->endbit)&1);
316}
317
318long oggpackB_look1(oggpack_buffer *b){
319  if(b->endbyte>=b->storage)return(-1);
320  return((b->ptr[0]>>(7-b->endbit))&1);
321}
322
323void oggpack_adv(oggpack_buffer *b,int bits){
324  bits+=b->endbit;
325  b->ptr+=bits/8;
326  b->endbyte+=bits/8;
327  b->endbit=bits&7;
328}
329
330void oggpackB_adv(oggpack_buffer *b,int bits){
331  oggpack_adv(b,bits);
332}
333
334void oggpack_adv1(oggpack_buffer *b){
335  if(++(b->endbit)>7){
336    b->endbit=0;
337    b->ptr++;
338    b->endbyte++;
339  }
340}
341
342void oggpackB_adv1(oggpack_buffer *b){
343  oggpack_adv1(b);
344}
345
346/* bits <= 32 */
347long oggpack_read(oggpack_buffer *b,int bits){
348  long ret;
349  unsigned long m=mask[bits];
350
351  bits+=b->endbit;
352
353  if(b->endbyte+4>=b->storage){
354    /* not the main path */
355    ret=-1L;
356    if(b->endbyte*8+bits>b->storage*8)goto overflow;
357  }
358
359  ret=b->ptr[0]>>b->endbit;
360  if(bits>8){
361    ret|=b->ptr[1]<<(8-b->endbit);
362    if(bits>16){
363      ret|=b->ptr[2]<<(16-b->endbit);
364      if(bits>24){
365        ret|=b->ptr[3]<<(24-b->endbit);
366        if(bits>32 && b->endbit){
367          ret|=b->ptr[4]<<(32-b->endbit);
368        }
369      }
370    }
371  }
372  ret&=m;
373
374 overflow:
375
376  b->ptr+=bits/8;
377  b->endbyte+=bits/8;
378  b->endbit=bits&7;
379  return(ret);
380}
381
382/* bits <= 32 */
383long oggpackB_read(oggpack_buffer *b,int bits){
384  long ret;
385  long m=32-bits;
386
387  bits+=b->endbit;
388
389  if(b->endbyte+4>=b->storage){
390    /* not the main path */
391    ret=-1L;
392    if(b->endbyte*8+bits>b->storage*8)goto overflow;
393    /* special case to avoid reading b->ptr[0], which might be past the end of
394        the buffer; also skips some useless accounting */
395    else if(!bits)return(0L);
396  }
397
398  ret=b->ptr[0]<<(24+b->endbit);
399  if(bits>8){
400    ret|=b->ptr[1]<<(16+b->endbit);
401    if(bits>16){
402      ret|=b->ptr[2]<<(8+b->endbit);
403      if(bits>24){
404        ret|=b->ptr[3]<<(b->endbit);
405        if(bits>32 && b->endbit)
406          ret|=b->ptr[4]>>(8-b->endbit);
407      }
408    }
409  }
410  ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1);
411
412 overflow:
413
414  b->ptr+=bits/8;
415  b->endbyte+=bits/8;
416  b->endbit=bits&7;
417  return(ret);
418}
419
420long oggpack_read1(oggpack_buffer *b){
421  long ret;
422
423  if(b->endbyte>=b->storage){
424    /* not the main path */
425    ret=-1L;
426    goto overflow;
427  }
428
429  ret=(b->ptr[0]>>b->endbit)&1;
430
431 overflow:
432
433  b->endbit++;
434  if(b->endbit>7){
435    b->endbit=0;
436    b->ptr++;
437    b->endbyte++;
438  }
439  return(ret);
440}
441
442long oggpackB_read1(oggpack_buffer *b){
443  long ret;
444
445  if(b->endbyte>=b->storage){
446    /* not the main path */
447    ret=-1L;
448    goto overflow;
449  }
450
451  ret=(b->ptr[0]>>(7-b->endbit))&1;
452
453 overflow:
454
455  b->endbit++;
456  if(b->endbit>7){
457    b->endbit=0;
458    b->ptr++;
459    b->endbyte++;
460  }
461  return(ret);
462}
463
464long oggpack_bytes(oggpack_buffer *b){
465  return(b->endbyte+(b->endbit+7)/8);
466}
467
468long oggpack_bits(oggpack_buffer *b){
469  return(b->endbyte*8+b->endbit);
470}
471
472long oggpackB_bytes(oggpack_buffer *b){
473  return oggpack_bytes(b);
474}
475
476long oggpackB_bits(oggpack_buffer *b){
477  return oggpack_bits(b);
478}
479
480unsigned char *oggpack_get_buffer(oggpack_buffer *b){
481  return(b->buffer);
482}
483
484unsigned char *oggpackB_get_buffer(oggpack_buffer *b){
485  return oggpack_get_buffer(b);
486}
487
488/* Self test of the bitwise routines; everything else is based on
489   them, so they damned well better be solid. */
490
491#ifdef _V_SELFTEST
492#include <stdio.h>
493
494static int ilog(unsigned int v){
495  int ret=0;
496  while(v){
497    ret++;
498    v>>=1;
499  }
500  return(ret);
501}
502
503oggpack_buffer o;
504oggpack_buffer r;
505
506void report(char *in){
507  fprintf(stderr,"%s",in);
508  exit(1);
509}
510
511void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){
512  long bytes,i;
513  unsigned char *buffer;
514
515  oggpack_reset(&o);
516  for(i=0;i<vals;i++)
517    oggpack_write(&o,b[i],bits?bits:ilog(b[i]));
518  buffer=oggpack_get_buffer(&o);
519  bytes=oggpack_bytes(&o);
520  if(bytes!=compsize)report("wrong number of bytes!\n");
521  for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){
522    for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]);
523    report("wrote incorrect value!\n");
524  }
525  oggpack_readinit(&r,buffer,bytes);
526  for(i=0;i<vals;i++){
527    int tbit=bits?bits:ilog(b[i]);
528    if(oggpack_look(&r,tbit)==-1)
529      report("out of data!\n");
530    if(oggpack_look(&r,tbit)!=(b[i]&mask[tbit]))
531      report("looked at incorrect value!\n");
532    if(tbit==1)
533      if(oggpack_look1(&r)!=(b[i]&mask[tbit]))
534        report("looked at single bit incorrect value!\n");
535    if(tbit==1){
536      if(oggpack_read1(&r)!=(b[i]&mask[tbit]))
537        report("read incorrect single bit value!\n");
538    }else{
539    if(oggpack_read(&r,tbit)!=(b[i]&mask[tbit]))
540      report("read incorrect value!\n");
541    }
542  }
543  if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
544}
545
546void cliptestB(unsigned long *b,int vals,int bits,int *comp,int compsize){
547  long bytes,i;
548  unsigned char *buffer;
549
550  oggpackB_reset(&o);
551  for(i=0;i<vals;i++)
552    oggpackB_write(&o,b[i],bits?bits:ilog(b[i]));
553  buffer=oggpackB_get_buffer(&o);
554  bytes=oggpackB_bytes(&o);
555  if(bytes!=compsize)report("wrong number of bytes!\n");
556  for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){
557    for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]);
558    report("wrote incorrect value!\n");
559  }
560  oggpackB_readinit(&r,buffer,bytes);
561  for(i=0;i<vals;i++){
562    int tbit=bits?bits:ilog(b[i]);
563    if(oggpackB_look(&r,tbit)==-1)
564      report("out of data!\n");
565    if(oggpackB_look(&r,tbit)!=(b[i]&mask[tbit]))
566      report("looked at incorrect value!\n");
567    if(tbit==1)
568      if(oggpackB_look1(&r)!=(b[i]&mask[tbit]))
569        report("looked at single bit incorrect value!\n");
570    if(tbit==1){
571      if(oggpackB_read1(&r)!=(b[i]&mask[tbit]))
572        report("read incorrect single bit value!\n");
573    }else{
574    if(oggpackB_read(&r,tbit)!=(b[i]&mask[tbit]))
575      report("read incorrect value!\n");
576    }
577  }
578  if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n");
579}
580
581int main(void){
582  unsigned char *buffer;
583  long bytes,i;
584  static unsigned long testbuffer1[]=
585    {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7,
586       567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4};
587  int test1size=43;
588
589  static unsigned long testbuffer2[]=
590    {216531625L,1237861823,56732452,131,3212421,12325343,34547562,12313212,
591       1233432,534,5,346435231,14436467,7869299,76326614,167548585,
592       85525151,0,12321,1,349528352};
593  int test2size=21;
594
595  static unsigned long testbuffer3[]=
596    {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,
597       0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1};
598  int test3size=56;
599
600  static unsigned long large[]=
601    {2136531625L,2137861823,56732452,131,3212421,12325343,34547562,12313212,
602       1233432,534,5,2146435231,14436467,7869299,76326614,167548585,
603       85525151,0,12321,1,2146528352};
604
605  int onesize=33;
606  static int one[33]={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40,
607                    34,242,223,136,35,222,211,86,171,50,225,135,214,75,172,
608                    223,4};
609  static int oneB[33]={150,101,131,33,203,15,204,216,105,193,156,65,84,85,222,
610                       8,139,145,227,126,34,55,244,171,85,100,39,195,173,18,
611                       245,251,128};
612
613  int twosize=6;
614  static int two[6]={61,255,255,251,231,29};
615  static int twoB[6]={247,63,255,253,249,120};
616
617  int threesize=54;
618  static int three[54]={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254,
619                      142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83,
620                      58,135,196,61,55,129,183,54,101,100,170,37,127,126,10,
621                      100,52,4,14,18,86,77,1};
622  static int threeB[54]={206,128,42,153,57,8,183,251,13,89,36,30,32,144,183,
623                         130,59,240,121,59,85,223,19,228,180,134,33,107,74,98,
624                         233,253,196,135,63,2,110,114,50,155,90,127,37,170,104,
625                         200,20,254,4,58,106,176,144,0};
626
627  int foursize=38;
628  static int four[38]={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72,
629                     132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169,
630                     28,2,133,0,1};
631  static int fourB[38]={36,48,102,83,243,24,52,7,4,35,132,10,145,21,2,93,2,41,
632                        1,219,184,16,33,184,54,149,170,132,18,30,29,98,229,67,
633                        129,10,4,32};
634
635  int fivesize=45;
636  static int five[45]={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62,
637                     241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169,
638                     84,75,159,2,1,0,132,192,8,0,0,18,22};
639  static int fiveB[45]={1,84,145,111,245,100,128,8,56,36,40,71,126,78,213,226,
640                        124,105,12,0,133,128,0,162,233,242,67,152,77,205,77,
641                        172,150,169,129,79,128,0,6,4,32,0,27,9,0};
642
643  int sixsize=7;
644  static int six[7]={17,177,170,242,169,19,148};
645  static int sixB[7]={136,141,85,79,149,200,41};
646
647  /* Test read/write together */
648  /* Later we test against pregenerated bitstreams */
649  oggpack_writeinit(&o);
650
651  fprintf(stderr,"\nSmall preclipped packing (LSb): ");
652  cliptest(testbuffer1,test1size,0,one,onesize);
653  fprintf(stderr,"ok.");
654
655  fprintf(stderr,"\nNull bit call (LSb): ");
656  cliptest(testbuffer3,test3size,0,two,twosize);
657  fprintf(stderr,"ok.");
658
659  fprintf(stderr,"\nLarge preclipped packing (LSb): ");
660  cliptest(testbuffer2,test2size,0,three,threesize);
661  fprintf(stderr,"ok.");
662
663  fprintf(stderr,"\n32 bit preclipped packing (LSb): ");
664  oggpack_reset(&o);
665  for(i=0;i<test2size;i++)
666    oggpack_write(&o,large[i],32);
667  buffer=oggpack_get_buffer(&o);
668  bytes=oggpack_bytes(&o);
669  oggpack_readinit(&r,buffer,bytes);
670  for(i=0;i<test2size;i++){
671    if(oggpack_look(&r,32)==-1)report("out of data. failed!");
672    if(oggpack_look(&r,32)!=large[i]){
673      fprintf(stderr,"%ld != %ld (%lx!=%lx):",oggpack_look(&r,32),large[i],
674              oggpack_look(&r,32),large[i]);
675      report("read incorrect value!\n");
676    }
677    oggpack_adv(&r,32);
678  }
679  if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
680  fprintf(stderr,"ok.");
681
682  fprintf(stderr,"\nSmall unclipped packing (LSb): ");
683  cliptest(testbuffer1,test1size,7,four,foursize);
684  fprintf(stderr,"ok.");
685
686  fprintf(stderr,"\nLarge unclipped packing (LSb): ");
687  cliptest(testbuffer2,test2size,17,five,fivesize);
688  fprintf(stderr,"ok.");
689
690  fprintf(stderr,"\nSingle bit unclipped packing (LSb): ");
691  cliptest(testbuffer3,test3size,1,six,sixsize);
692  fprintf(stderr,"ok.");
693
694  fprintf(stderr,"\nTesting read past end (LSb): ");
695  oggpack_readinit(&r,"\0\0\0\0\0\0\0\0",8);
696  for(i=0;i<64;i++){
697    if(oggpack_read(&r,1)!=0){
698      fprintf(stderr,"failed; got -1 prematurely.\n");
699      exit(1);
700    }
701  }
702  if(oggpack_look(&r,1)!=-1 ||
703     oggpack_read(&r,1)!=-1){
704      fprintf(stderr,"failed; read past end without -1.\n");
705      exit(1);
706  }
707  oggpack_readinit(&r,"\0\0\0\0\0\0\0\0",8);
708  if(oggpack_read(&r,30)!=0 || oggpack_read(&r,16)!=0){
709      fprintf(stderr,"failed 2; got -1 prematurely.\n");
710      exit(1);
711  }
712
713  if(oggpack_look(&r,18)!=0 ||
714     oggpack_look(&r,18)!=0){
715    fprintf(stderr,"failed 3; got -1 prematurely.\n");
716      exit(1);
717  }
718  if(oggpack_look(&r,19)!=-1 ||
719     oggpack_look(&r,19)!=-1){
720    fprintf(stderr,"failed; read past end without -1.\n");
721      exit(1);
722  }
723  if(oggpack_look(&r,32)!=-1 ||
724     oggpack_look(&r,32)!=-1){
725    fprintf(stderr,"failed; read past end without -1.\n");
726      exit(1);
727  }
728  oggpack_writeclear(&o);
729  fprintf(stderr,"ok.\n");
730
731  /********** lazy, cut-n-paste retest with MSb packing ***********/
732
733  /* Test read/write together */
734  /* Later we test against pregenerated bitstreams */
735  oggpackB_writeinit(&o);
736
737  fprintf(stderr,"\nSmall preclipped packing (MSb): ");
738  cliptestB(testbuffer1,test1size,0,oneB,onesize);
739  fprintf(stderr,"ok.");
740
741  fprintf(stderr,"\nNull bit call (MSb): ");
742  cliptestB(testbuffer3,test3size,0,twoB,twosize);
743  fprintf(stderr,"ok.");
744
745  fprintf(stderr,"\nLarge preclipped packing (MSb): ");
746  cliptestB(testbuffer2,test2size,0,threeB,threesize);
747  fprintf(stderr,"ok.");
748
749  fprintf(stderr,"\n32 bit preclipped packing (MSb): ");
750  oggpackB_reset(&o);
751  for(i=0;i<test2size;i++)
752    oggpackB_write(&o,large[i],32);
753  buffer=oggpackB_get_buffer(&o);
754  bytes=oggpackB_bytes(&o);
755  oggpackB_readinit(&r,buffer,bytes);
756  for(i=0;i<test2size;i++){
757    if(oggpackB_look(&r,32)==-1)report("out of data. failed!");
758    if(oggpackB_look(&r,32)!=large[i]){
759      fprintf(stderr,"%ld != %ld (%lx!=%lx):",oggpackB_look(&r,32),large[i],
760              oggpackB_look(&r,32),large[i]);
761      report("read incorrect value!\n");
762    }
763    oggpackB_adv(&r,32);
764  }
765  if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n");
766  fprintf(stderr,"ok.");
767
768  fprintf(stderr,"\nSmall unclipped packing (MSb): ");
769  cliptestB(testbuffer1,test1size,7,fourB,foursize);
770  fprintf(stderr,"ok.");
771
772  fprintf(stderr,"\nLarge unclipped packing (MSb): ");
773  cliptestB(testbuffer2,test2size,17,fiveB,fivesize);
774  fprintf(stderr,"ok.");
775
776  fprintf(stderr,"\nSingle bit unclipped packing (MSb): ");
777  cliptestB(testbuffer3,test3size,1,sixB,sixsize);
778  fprintf(stderr,"ok.");
779
780  fprintf(stderr,"\nTesting read past end (MSb): ");
781  oggpackB_readinit(&r,"\0\0\0\0\0\0\0\0",8);
782  for(i=0;i<64;i++){
783    if(oggpackB_read(&r,1)!=0){
784      fprintf(stderr,"failed; got -1 prematurely.\n");
785      exit(1);
786    }
787  }
788  if(oggpackB_look(&r,1)!=-1 ||
789     oggpackB_read(&r,1)!=-1){
790      fprintf(stderr,"failed; read past end without -1.\n");
791      exit(1);
792  }
793  oggpackB_readinit(&r,"\0\0\0\0\0\0\0\0",8);
794  if(oggpackB_read(&r,30)!=0 || oggpackB_read(&r,16)!=0){
795      fprintf(stderr,"failed 2; got -1 prematurely.\n");
796      exit(1);
797  }
798
799  if(oggpackB_look(&r,18)!=0 ||
800     oggpackB_look(&r,18)!=0){
801    fprintf(stderr,"failed 3; got -1 prematurely.\n");
802      exit(1);
803  }
804  if(oggpackB_look(&r,19)!=-1 ||
805     oggpackB_look(&r,19)!=-1){
806    fprintf(stderr,"failed; read past end without -1.\n");
807      exit(1);
808  }
809  if(oggpackB_look(&r,32)!=-1 ||
810     oggpackB_look(&r,32)!=-1){
811    fprintf(stderr,"failed; read past end without -1.\n");
812      exit(1);
813  }
814  oggpackB_writeclear(&o);
815  fprintf(stderr,"ok.\n\n");
816
817
818  return(0);
819}
820#endif  /* _V_SELFTEST */
821
822#undef BUFFER_INCREMENT
823