Home | History | Annotate | Download | only in Tremolo
      1 /************************************************************************
      2  * Copyright (C) 2002-2009, Xiph.org Foundation
      3  * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  *
     10  *     * Redistributions of source code must retain the above copyright
     11  * notice, this list of conditions and the following disclaimer.
     12  *     * Redistributions in binary form must reproduce the above
     13  * copyright notice, this list of conditions and the following disclaimer
     14  * in the documentation and/or other materials provided with the
     15  * distribution.
     16  *     * Neither the names of the Xiph.org Foundation nor Pinknoise
     17  * Productions Ltd nor the names of its contributors may be used to
     18  * endorse or promote products derived from this software without
     19  * specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  ************************************************************************
     33 
     34   function: packing variable sized words into an octet stream
     35 
     36  ************************************************************************/
     37 
     38 /* We're 'LSb' endian; if we write a word but read individual bits,
     39    then we'll read the lsb first */
     40 
     41 #include <string.h>
     42 #include <stdlib.h>
     43 #include "misc.h"
     44 #include "ogg.h"
     45 
     46 #include <stdio.h>
     47 
     48 
     49 #if !defined(ARM_LITTLE_ENDIAN) || defined(_V_BIT_TEST)
     50 static unsigned long mask[]=
     51 {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
     52  0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
     53  0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
     54  0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
     55  0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
     56  0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
     57  0x3fffffff,0x7fffffff,0xffffffff };
     58 #endif
     59 
     60 #ifdef ARM_LITTLE_ENDIAN
     61 
     62 #ifdef DEBUGGING_BITWISE
     63 extern void oggpack_readinitARM(oggpack_buffer *b,ogg_reference *r);
     64 
     65 void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){
     66     oggpack_readinitARM(b,r);
     67     //fprintf(stderr, "Init: buffer=(%d,%x,%d,%d) %08x%08x\n",
     68     //        b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count,
     69     //        b->ptr[1], b->ptr[0]);
     70     //fflush(stderr);
     71 }
     72 
     73 extern long oggpack_lookARM(oggpack_buffer *b,int bits);
     74 
     75 long oggpack_look(oggpack_buffer *b,int bits){
     76     long l;
     77 
     78     //fprintf(stderr, "PreLook: buffer=(%x,%x,%x) %08x%08x (%d bits)\n",
     79     //        b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord,
     80     //        b->ptr[1], b->ptr[0], bits);
     81     //fflush(stderr);
     82     l = oggpack_lookARM(b,bits);
     83     //fprintf(stderr, "Look: buffer=(%d,%x,%d,%d) %08x%08x (%d bits) (result=%x)\n",
     84     //        b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count,
     85     //        b->ptr[1], b->ptr[0], bits, l);
     86     //fflush(stderr);
     87 
     88     return l;
     89 }
     90 
     91 extern void oggpack_advARM(oggpack_buffer *b,int bits);
     92 
     93 void oggpack_adv(oggpack_buffer *b,int bits){
     94     //fprintf(stderr, "Adv before: buffer=(%x,%x,%x) %08x%08x (%d bits)\n",
     95     //        b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord,
     96     //        b->ptr[1], b->ptr[0],bits);
     97     //fflush(stderr);
     98     oggpack_advARM(b,bits);
     99     //fprintf(stderr, "Adv: buffer=(%d,%x,%d,%d) %08x%08x\n",
    100     //        b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count,
    101     //        b->ptr[1], b->ptr[0]);
    102     //fflush(stderr);
    103 }
    104 
    105 extern long oggpack_readARM(oggpack_buffer *b,int bits);
    106 
    107 /* bits <= 32 */
    108 long oggpack_read(oggpack_buffer *b,int bits){
    109     long l;
    110 
    111     //fprintf(stderr, "PreRead: buffer=(%d,%x,%d,%d) %08x%08x (%d bits)\n",
    112     //        b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count,
    113     //        b->ptr[1], b->ptr[0], bits);
    114     //fflush(stderr);
    115     l = oggpack_readARM(b,bits);
    116     //fprintf(stderr, "Read: buffer=(%d,%x,%d,%d) %08x%08x (%d bits) (result=%x)\n",
    117     //       b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count,
    118     //       b->ptr[1], b->ptr[0], bits, l);
    119     //fflush(stderr);
    120 
    121     return l;
    122 }
    123 #endif
    124 
    125 int oggpack_eop(oggpack_buffer *b){
    126   int ret;
    127   if(b->bitsLeftInSegment<0)ret= -1;
    128   else ret = 0;
    129   //fprintf(stderr, "EOP %d\n", ret);
    130   //fflush(stderr);
    131   return ret;
    132 }
    133 
    134 long oggpack_bytes(oggpack_buffer *b){
    135   long ret;
    136   if(b->bitsLeftInSegment<0) ret = b->count+b->head->length;
    137   else ret = b->count + b->head->length - (b->bitsLeftInSegment)/8;
    138   //fprintf(stderr, "count=%d length=%d bitsLeftInSegment=%d\n",
    139   //        b->count, b->head->length, b->bitsLeftInSegment);
    140   //fflush(stderr);
    141   return ret;
    142 }
    143 
    144 long oggpack_bits(oggpack_buffer *b){
    145   long ret;
    146   if(b->bitsLeftInSegment<0) ret=(b->count+b->head->length)*8;
    147   else ret = b->count*8 + b->head->length*8 - b->bitsLeftInSegment;
    148   //fprintf(stderr, "count=%d length=%d bitsLeftInSegment=%d\n",
    149   //        b->count, b->head->length, b->bitsLeftInSegment);
    150   //fflush(stderr);
    151   return ret;
    152 }
    153 
    154 #else
    155 
    156 /* spans forward, skipping as many bytes as headend is negative; if
    157    headend is zero, simply finds next byte.  If we're up to the end
    158    of the buffer, leaves headend at zero.  If we've read past the end,
    159    halt the decode process. */
    160 
    161 static void _span(oggpack_buffer *b){
    162   while(b->headend-(b->headbit>>3)<1){
    163     b->headend-=b->headbit>>3;
    164     b->headbit&=0x7;
    165 
    166     if(b->head && b->head->next){
    167       b->count+=b->head->length;
    168       b->head=b->head->next;
    169 
    170       if(b->headend+b->head->length>0)
    171 	b->headptr=b->head->buffer->data+b->head->begin-b->headend;
    172 
    173       b->headend+=b->head->length;
    174     }else{
    175       /* we've either met the end of decode, or gone past it. halt
    176 	 only if we're past */
    177       if(b->headend*8<b->headbit)
    178 	/* read has fallen off the end */
    179 	b->headend=-1;
    180         break;
    181     }
    182   }
    183 }
    184 
    185 void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){
    186   memset(b,0,sizeof(*b));
    187 
    188   b->tail=b->head=r;
    189   b->count=0;
    190   if (b->head) {
    191     b->headptr=b->head->buffer->data+b->head->begin;
    192     b->headend=b->head->length;
    193   } else {
    194     b->headptr=0;
    195     b->headend=0;
    196   }
    197   _span(b);
    198 
    199   //fprintf(stderr,
    200   //        "Init: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x\n",
    201   //        b->headbit, b->headptr, b->headend, b->count,
    202   //        b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
    203   //        b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0]);
    204   //fflush(stderr);
    205 }
    206 
    207 #define _lookspan()   while(!end){\
    208                         head=head->next;\
    209                         if(!head) return -1;\
    210                         ptr=head->buffer->data + head->begin;\
    211                         end=head->length;\
    212                       }
    213 
    214 /* Read in bits without advancing the bitptr; bits <= 32 */
    215 long oggpack_look(oggpack_buffer *b,int bits){
    216   unsigned long m=mask[bits];
    217   unsigned long ret;
    218   int BITS = bits;
    219 
    220   bits+=b->headbit;
    221 
    222   if(bits >= b->headend<<3){
    223     int            end=b->headend;
    224     unsigned char *ptr=b->headptr;
    225     ogg_reference *head=b->head;
    226 
    227     if(end<0)return -1;
    228     if (!head || !end)return -1;
    229 
    230     if(bits){
    231       _lookspan();
    232       ret=*ptr++>>b->headbit;
    233       if(bits>8){
    234         --end;
    235         _lookspan();
    236         ret|=*ptr++<<(8-b->headbit);
    237         if(bits>16){
    238           --end;
    239           _lookspan();
    240           ret|=*ptr++<<(16-b->headbit);
    241           if(bits>24){
    242             --end;
    243             _lookspan();
    244             ret|=*ptr++<<(24-b->headbit);
    245             if(bits>32 && b->headbit){
    246               --end;
    247               _lookspan();
    248               ret|=*ptr<<(32-b->headbit);
    249             }
    250           }
    251         }
    252       }
    253     }
    254 
    255   }else{
    256 
    257     /* make this a switch jump-table */
    258     ret=b->headptr[0]>>b->headbit;
    259     if(bits>8){
    260       ret|=b->headptr[1]<<(8-b->headbit);
    261       if(bits>16){
    262         ret|=b->headptr[2]<<(16-b->headbit);
    263         if(bits>24){
    264           ret|=b->headptr[3]<<(24-b->headbit);
    265           if(bits>32 && b->headbit)
    266             ret|=b->headptr[4]<<(32-b->headbit);
    267         }
    268       }
    269     }
    270   }
    271 
    272   ret&=m;
    273   //fprintf(stderr,
    274   //        "Look: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x (%d bits) return=%x\n",
    275   //        b->headbit, b->headptr, b->headend, b->count,
    276   //        b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
    277   //        b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0],
    278   //        BITS, ret);
    279   //fflush(stderr);
    280   return ret;
    281 }
    282 
    283 /* limited to 32 at a time */
    284 void oggpack_adv(oggpack_buffer *b,int bits){
    285     int BITS=bits;
    286   bits+=b->headbit;
    287   b->headbit=bits&7;
    288   b->headend-=(bits>>3);
    289   b->headptr+=(bits>>3);
    290   if(b->headend<1)_span(b);
    291   //fprintf(stderr, "Adv: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x (%d bits)\n",
    292   //        b->headbit, b->headptr, b->headend,b->count,
    293   //        b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
    294   //        b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0],
    295   //        BITS);
    296   //fflush(stderr);
    297 }
    298 
    299 int oggpack_eop(oggpack_buffer *b){
    300   int ret;
    301   if(b->headend<0)ret= -1;
    302   else ret = 0;
    303   //fprintf(stderr, "EOP %d\n", ret);
    304   //fflush(stderr);
    305   return ret;
    306 }
    307 
    308 long oggpack_bytes(oggpack_buffer *b){
    309   long ret;
    310   if(b->headend<0) ret = b->count+b->head->length;
    311   ret = b->count + b->head->length-b->headend + (b->headbit+7)/8;
    312   //fprintf(stderr, "Bytes: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x (%d bytes)\n",
    313   //        b->headbit, b->headptr, b->headend, b->count,
    314   //        b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
    315   //        b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0],
    316   //        ret);
    317   //fflush(stderr);
    318   return ret;
    319 }
    320 
    321 long oggpack_bits(oggpack_buffer *b){
    322   long ret;
    323   if(b->headend<0) ret = (b->count+b->head->length)*8;
    324   else ret = (b->count + b->head->length-b->headend)*8 + b->headbit;
    325   //fprintf(stderr, "Bits: buffer=(%x,%x,%x) %02x%02x%02x%02x%02x%02x%02x%02x (%d bits)\n",
    326   //        b->headbit, b->headptr, b->headend,
    327   //        b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
    328   //        b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0],
    329   //        ret);
    330   //fflush(stderr);
    331   return ret;
    332 }
    333 
    334 /* bits <= 32 */
    335 long oggpack_read(oggpack_buffer *b,int bits){
    336   long ret=oggpack_look(b,bits);
    337   oggpack_adv(b,bits);
    338   return(ret);
    339 }
    340 
    341 #endif
    342 
    343 /* Self test of the bitwise routines; everything else is based on
    344    them, so they damned well better be solid. */
    345 
    346 #ifdef _V_BIT_TEST
    347 #include <string.h>
    348 #include <stdlib.h>
    349 #include <stdio.h>
    350 #include "framing.c"
    351 
    352 static int ilog(unsigned long v){
    353   int ret=0;
    354   while(v){
    355     ret++;
    356     v>>=1;
    357   }
    358   return(ret);
    359 }
    360 
    361 oggpack_buffer r;
    362 oggpack_buffer o;
    363 ogg_buffer_state *bs;
    364 ogg_reference *or;
    365 #define TESTWORDS 256
    366 
    367 void report(char *in){
    368   fprintf(stderr,"%s",in);
    369   exit(1);
    370 }
    371 
    372 int getbyte(ogg_reference *or,int position){
    373   while(or && position>=or->length){
    374     position-=or->length;
    375     or=or->next;
    376     if(or==NULL){
    377       fprintf(stderr,"\n\tERROR: getbyte ran off end of buffer.\n");
    378       exit(1);
    379     }
    380   }
    381 
    382   if((position+or->begin)&1)
    383     return (or->buffer->data[(position+or->begin)>>1])&0xff;
    384   else
    385     return (or->buffer->data[(position+or->begin)>>1]>>8)&0xff;
    386 }
    387 
    388 void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){
    389   long i,bitcount=0;
    390   ogg_reference *or=ogg_buffer_alloc(bs,64);
    391   for(i=0;i<compsize;i++)
    392     or->buffer->data[i]= comp[i];
    393   or->length=i;
    394 
    395   oggpack_readinit(&r,or);
    396   for(i=0;i<vals;i++){
    397     unsigned long test;
    398     int tbit=bits?bits:ilog(b[i]);
    399     if((test=oggpack_look(&r,tbit))==0xffffffff)
    400       report("out of data!\n");
    401     if(test!=(b[i]&mask[tbit])){
    402       fprintf(stderr,"%ld) %lx %lx\n",i,(b[i]&mask[tbit]),test);
    403       report("looked at incorrect value!\n");
    404     }
    405     if((test=oggpack_read(&r,tbit))==0xffffffff){
    406       report("premature end of data when reading!\n");
    407     }
    408     if(test!=(b[i]&mask[tbit])){
    409       fprintf(stderr,"%ld) %lx %lx\n",i,(b[i]&mask[tbit]),test);
    410       report("read incorrect value!\n");
    411     }
    412     bitcount+=tbit;
    413 
    414     if(bitcount!=oggpack_bits(&r))
    415       report("wrong number of bits while reading!\n");
    416     if((bitcount+7)/8!=oggpack_bytes(&r))
    417       report("wrong number of bytes while reading!\n");
    418 
    419   }
    420   if(oggpack_bytes(&r)!=(bitcount+7)/8){
    421       fprintf(stderr, "%d vs %d\n", oggpack_bytes(&r), (bitcount+7)/8);
    422       report("leftover bytes after read!\n");
    423   }
    424   ogg_buffer_release(or);
    425 }
    426 
    427 void _end_verify(int count){
    428   int i;
    429 
    430   /* are the proper number of bits left over? */
    431   int leftover=count*8-oggpack_bits(&o);
    432   if(leftover>7)
    433     report("\nERROR: too many bits reported left over.\n");
    434 
    435   /* does reading to exactly byte alignment *not* trip EOF? */
    436   if(oggpack_read(&o,leftover)==-1)
    437     report("\nERROR: read to but not past exact end tripped EOF.\n");
    438   if(oggpack_bits(&o)!=count*8)
    439     report("\nERROR: read to but not past exact end reported bad bitcount.\n");
    440 
    441   /* does EOF trip properly after a single additional bit? */
    442   if(oggpack_read(&o,1)!=-1)
    443     report("\nERROR: read past exact end did not trip EOF.\n");
    444   if(oggpack_bits(&o)!=count*8)
    445     report("\nERROR: read past exact end reported bad bitcount.\n");
    446 
    447   /* does EOF stay set over additional bit reads? */
    448   for(i=0;i<=32;i++){
    449     if(oggpack_read(&o,i)!=-1)
    450       report("\nERROR: EOF did not stay set on stream.\n");
    451     if(oggpack_bits(&o)!=count*8)
    452       report("\nERROR: read past exact end reported bad bitcount.\n");
    453   }
    454 }
    455 
    456 void _end_verify2(int count){
    457   int i;
    458 
    459   /* are the proper number of bits left over? */
    460   int leftover=count*8-oggpack_bits(&o);
    461   if(leftover>7)
    462     report("\nERROR: too many bits reported left over.\n");
    463 
    464   /* does reading to exactly byte alignment *not* trip EOF? */
    465   oggpack_adv(&o,leftover);
    466 #ifdef ARM_LITTLE_ENDIAN
    467     if(o.bitsLeftInSegment!=0)
    468 #else
    469   if(o.headend!=0)
    470 #endif
    471     report("\nERROR: read to but not past exact end tripped EOF.\n");
    472   if(oggpack_bits(&o)!=count*8)
    473     report("\nERROR: read to but not past exact end reported bad bitcount.\n");
    474 
    475   /* does EOF trip properly after a single additional bit? */
    476   oggpack_adv(&o,1);
    477 #ifdef ARM_LITTLE_ENDIAN
    478     if(o.bitsLeftInSegment>=0)
    479 #else
    480   if(o.headend>=0)
    481 #endif
    482     report("\nERROR: read past exact end did not trip EOF.\n");
    483   if(oggpack_bits(&o)!=count*8)
    484     report("\nERROR: read past exact end reported bad bitcount.\n");
    485 
    486   /* does EOF stay set over additional bit reads? */
    487   for(i=0;i<=32;i++){
    488     oggpack_adv(&o,i);
    489 #ifdef ARM_LITTLE_ENDIAN
    490     if(o.bitsLeftInSegment>=0)
    491 #else
    492     if(o.headend>=0)
    493 #endif
    494       report("\nERROR: EOF did not stay set on stream.\n");
    495     if(oggpack_bits(&o)!=count*8)
    496       report("\nERROR: read past exact end reported bad bitcount.\n");
    497   }
    498 }
    499 
    500 long ogg_buffer_length(ogg_reference *or){
    501   int count=0;
    502   while(or){
    503     count+=or->length;
    504     or=or->next;
    505   }
    506   return count;
    507 }
    508 
    509 ogg_reference *ogg_buffer_extend(ogg_reference *or,long bytes){
    510   if(or){
    511     while(or->next){
    512       or=or->next;
    513     }
    514     or->next=ogg_buffer_alloc(or->buffer->ptr.owner,bytes);
    515     return(or->next);
    516   }
    517   return 0;
    518 }
    519 
    520 void ogg_buffer_posttruncate(ogg_reference *or,long pos){
    521   /* walk to the point where we want to begin truncate */
    522   while(or && pos>or->length){
    523     pos-=or->length;
    524     or=or->next;
    525   }
    526   if(or){
    527     ogg_buffer_release(or->next);
    528     or->next=0;
    529     or->length=pos;
    530   }
    531 }
    532 
    533 int main(void){
    534   long i;
    535   static unsigned long testbuffer1[]=
    536     {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7,
    537        567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4};
    538   int test1size=43;
    539 
    540   static unsigned long testbuffer2[]=
    541     {216531625L,1237861823,56732452,131,3212421,12325343,34547562,12313212,
    542        1233432,534,5,346435231,14436467,7869299,76326614,167548585,
    543        85525151,0,12321,1,349528352};
    544   int test2size=21;
    545 
    546   static unsigned long testbuffer3[]=
    547     {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,
    548        0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1};
    549   int test3size=56;
    550 
    551   static unsigned long large[]=
    552     {2136531625L,2137861823,56732452,131,3212421,12325343,34547562,12313212,
    553        1233432,534,5,2146435231,14436467,7869299,76326614,167548585,
    554        85525151,0,12321,1,2146528352};
    555 
    556   int onesize=33;
    557   static int one[33]={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40,
    558                     34,242,223,136,35,222,211,86,171,50,225,135,214,75,172,
    559                     223,4};
    560 
    561   int twosize=6;
    562   static int two[6]={61,255,255,251,231,29};
    563 
    564   int threesize=54;
    565   static int three[54]={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254,
    566                       142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83,
    567                       58,135,196,61,55,129,183,54,101,100,170,37,127,126,10,
    568                       100,52,4,14,18,86,77,1};
    569 
    570   int foursize=38;
    571   static int four[38]={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72,
    572                      132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169,
    573                      28,2,133,0,1};
    574 
    575   int fivesize=45;
    576   static int five[45]={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62,
    577                      241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169,
    578                      84,75,159,2,1,0,132,192,8,0,0,18,22};
    579 
    580   int sixsize=7;
    581   static int six[7]={17,177,170,242,169,19,148};
    582 
    583   /* Test read/write together */
    584   /* Later we test against pregenerated bitstreams */
    585   bs=ogg_buffer_create();
    586 
    587   fprintf(stderr,"\nSmall preclipped packing (LSb): ");
    588   cliptest(testbuffer1,test1size,0,one,onesize);
    589   fprintf(stderr,"ok.");
    590 
    591   fprintf(stderr,"\nNull bit call (LSb): ");
    592   cliptest(testbuffer3,test3size,0,two,twosize);
    593   fprintf(stderr,"ok.");
    594 
    595   fprintf(stderr,"\nLarge preclipped packing (LSb): ");
    596   cliptest(testbuffer2,test2size,0,three,threesize);
    597   fprintf(stderr,"ok.");
    598 
    599   fprintf(stderr,"\n32 bit preclipped packing (LSb): ");
    600 
    601   or=ogg_buffer_alloc(bs,128);
    602   for(i=0;i<test2size;i++){
    603     or->buffer->data[i*4]  = large[i]&0xff;
    604     or->buffer->data[i*4+1]  = (large[i]>>8)&0xff;
    605     or->buffer->data[i*4+2]  = (large[i]>>16)&0xff;
    606     or->buffer->data[i*4+3]  = (large[i]>>24)&0xff;
    607   }
    608   or->length=test2size*4;
    609   oggpack_readinit(&r,or);
    610   for(i=0;i<test2size;i++){
    611     unsigned long test;
    612     if((test=oggpack_look(&r,32))==0xffffffffUL)report("out of data. failed!");
    613     if(test!=large[i]){
    614       fprintf(stderr,"%ld != %ld (%lx!=%lx):",test,large[i],
    615               test,large[i]);
    616       report("read incorrect value!\n");
    617     }
    618     oggpack_adv(&r,32);
    619   }
    620   ogg_buffer_release(or);
    621   if(oggpack_bytes(&r)!=test2size*4){
    622     fprintf(stderr, "%d vs %d\n", oggpack_bytes(&r), test2size*4);
    623     report("leftover bytes after read!\n");
    624   }
    625   fprintf(stderr,"ok.");
    626 
    627   fprintf(stderr,"\nSmall unclipped packing (LSb): ");
    628   cliptest(testbuffer1,test1size,7,four,foursize);
    629   fprintf(stderr,"ok.");
    630 
    631   fprintf(stderr,"\nLarge unclipped packing (LSb): ");
    632   cliptest(testbuffer2,test2size,17,five,fivesize);
    633   fprintf(stderr,"ok.");
    634 
    635   fprintf(stderr,"\nSingle bit unclipped packing (LSb): ");
    636   cliptest(testbuffer3,test3size,1,six,sixsize);
    637   fprintf(stderr,"ok.");
    638 
    639   fprintf(stderr,"\nTesting read past end (LSb): ");
    640   {
    641     unsigned char dda[]={0,0,0,0};
    642     ogg_buffer lob={dda,8,0,{0}};
    643     ogg_reference lor={&lob,0,8,0};
    644 
    645     oggpack_readinit(&r,&lor);
    646     for(i=0;i<64;i++){
    647       if(oggpack_read(&r,1)<0){
    648         fprintf(stderr,"failed; got -1 prematurely.\n");
    649         exit(1);
    650       }
    651     }
    652     if(oggpack_look(&r,1)!=-1 ||
    653        oggpack_read(&r,1)!=-1){
    654       fprintf(stderr,"failed; read past end without -1.\n");
    655       exit(1);
    656     }
    657   }
    658   {
    659     unsigned char dda[]={0,0,0,0};
    660     ogg_buffer lob={dda,8,0,{0}};
    661     ogg_reference lor={&lob,0,8,0};
    662     unsigned long test;
    663 
    664     oggpack_readinit(&r,&lor);
    665     if((test=oggpack_read(&r,30))==0xffffffffUL ||
    666        (test=oggpack_read(&r,16))==0xffffffffUL){
    667       fprintf(stderr,"failed 2; got -1 prematurely.\n");
    668       exit(1);
    669     }
    670 
    671     if((test=oggpack_look(&r,18))==0xffffffffUL){
    672       fprintf(stderr,"failed 3; got -1 prematurely.\n");
    673       exit(1);
    674     }
    675     if((test=oggpack_look(&r,19))!=0xffffffffUL){
    676       fprintf(stderr,"failed; read past end without -1.\n");
    677       exit(1);
    678     }
    679     if((test=oggpack_look(&r,32))!=0xffffffffUL){
    680       fprintf(stderr,"failed; read past end without -1.\n");
    681       exit(1);
    682     }
    683   }
    684   fprintf(stderr,"ok.\n");
    685 
    686   /* now the scary shit: randomized testing */
    687 
    688   for(i=0;i<10000;i++){
    689     long j,count=0,count2=0,bitcount=0;
    690     unsigned long values[TESTWORDS];
    691     int len[TESTWORDS];
    692     unsigned char flat[4*TESTWORDS]; /* max possible needed size */
    693 
    694     memset(flat,0,sizeof(flat));
    695     fprintf(stderr,"\rRandomized testing (LSb)... (%ld)   ",10000-i);
    696 
    697     /* generate a list of words and lengths */
    698     /* write the required number of bits out to packbuffer */
    699     {
    700       long word=0;
    701       long bit=0;
    702       int k;
    703 
    704       for(j=0;j<TESTWORDS;j++){
    705 	values[j]=rand();
    706 	len[j]=(rand()%33);
    707 
    708 	for(k=0;k<len[j];k++){
    709 	  flat[word] |= ((values[j]>>k)&0x1)<<bit;
    710 	  bit++;
    711 	  bitcount++;
    712 	  if(bit>7){
    713 	    bit=0;
    714 	    word++;
    715 	  }
    716 	}
    717       }
    718     }
    719     count2=(bitcount+7)>>3;
    720 
    721     /* construct random-length buffer chain from flat vector; random
    722        byte starting offset within the length of the vector */
    723     {
    724       ogg_reference *or=NULL,*orl=NULL;
    725       long pos=0;
    726 
    727       /* build buffer chain */
    728       while(count2){
    729         int ilen=(rand()%32),k;
    730         int ibegin=(rand()%32);
    731 
    732 
    733         if(ilen>count2)ilen=count2;
    734 
    735         if(or)
    736           orl=ogg_buffer_extend(orl,64);
    737         else
    738           or=orl=ogg_buffer_alloc(bs,64);
    739 
    740         orl->length=ilen;
    741         orl->begin=ibegin;
    742 
    743 	for(k=0;k<ilen;k++)
    744 	  orl->buffer->data[ibegin++]= flat[pos++];
    745 
    746         count2-=ilen;
    747       }
    748 
    749       if(ogg_buffer_length(or)!=(bitcount+7)/8){
    750         fprintf(stderr,"\nERROR: buffer length incorrect after build.\n");
    751         exit(1);
    752       }
    753 
    754 
    755       {
    756         int begin=0; //=(rand()%TESTWORDS);
    757         int ilen=(rand()%(TESTWORDS-begin));
    758         int bitoffset,bitcount=0;
    759         unsigned long temp;
    760 
    761         for(j=0;j<begin;j++)
    762           bitcount+=len[j];
    763         or=ogg_buffer_pretruncate(or,bitcount/8);
    764         bitoffset=bitcount%=8;
    765         for(;j<begin+ilen;j++)
    766           bitcount+=len[j];
    767         ogg_buffer_posttruncate(or,((bitcount+7)/8));
    768 
    769         if((count=ogg_buffer_length(or))!=(bitcount+7)/8){
    770           fprintf(stderr,"\nERROR: buffer length incorrect after truncate.\n");
    771           exit(1);
    772         }
    773 
    774         oggpack_readinit(&o,or);
    775 
    776         /* verify bit count */
    777         if(oggpack_bits(&o)!=0){
    778           fprintf(stderr,"\nERROR: Read bitcounter not zero!\n");
    779           exit(1);
    780         }
    781         if(oggpack_bytes(&o)!=0){
    782           fprintf(stderr,"\nERROR: Read bytecounter not zero!\n");
    783           exit(1);
    784         }
    785 
    786         bitcount=bitoffset;
    787         oggpack_read(&o,bitoffset);
    788 
    789         /* read and compare to original list */
    790         for(j=begin;j<begin+ilen;j++){
    791 	  temp=oggpack_read(&o,len[j]);
    792           if(temp==0xffffffffUL){
    793             fprintf(stderr,"\nERROR: End of stream too soon! word: %ld,%d\n",
    794                     j-begin,ilen);
    795             exit(1);
    796           }
    797           if(temp!=(values[j]&mask[len[j]])){
    798             fprintf(stderr,"\nERROR: Incorrect read %lx != %lx, word %ld, len %d\n"
    799 ,
    800                     values[j]&mask[len[j]],temp,j-begin,len[j]);
    801             exit(1);
    802           }
    803           bitcount+=len[j];
    804           if(oggpack_bits(&o)!=bitcount){
    805             fprintf(stderr,"\nERROR: Read bitcounter %d != %ld!\n",
    806                     bitcount,oggpack_bits(&o));
    807             exit(1);
    808           }
    809           if(oggpack_bytes(&o)!=(bitcount+7)/8){
    810             fprintf(stderr,"\nERROR: Read bytecounter %d != %ld!\n",
    811                     (bitcount+7)/8,oggpack_bytes(&o));
    812             exit(1);
    813           }
    814 
    815         }
    816         _end_verify(count);
    817 
    818         /* look/adv version */
    819         oggpack_readinit(&o,or);
    820         bitcount=bitoffset;
    821         oggpack_adv(&o,bitoffset);
    822 
    823         /* read and compare to original list */
    824         for(j=begin;j<begin+ilen;j++){
    825 	  temp=oggpack_look(&o,len[j]);
    826 
    827           if(temp==0xffffffffUL){
    828             fprintf(stderr,"\nERROR: End of stream too soon! word: %ld\n",
    829                     j-begin);
    830             exit(1);
    831           }
    832           if(temp!=(values[j]&mask[len[j]])){
    833             fprintf(stderr,"\nERROR: Incorrect look %lx != %lx, word %ld, len %d\n"
    834 ,
    835                     values[j]&mask[len[j]],temp,j-begin,len[j]);
    836             exit(1);
    837           }
    838 	  oggpack_adv(&o,len[j]);
    839           bitcount+=len[j];
    840           if(oggpack_bits(&o)!=bitcount){
    841             fprintf(stderr,"\nERROR: Look/Adv bitcounter %d != %ld!\n",
    842                     bitcount,oggpack_bits(&o));
    843             exit(1);
    844           }
    845           if(oggpack_bytes(&o)!=(bitcount+7)/8){
    846             fprintf(stderr,"\nERROR: Look/Adv bytecounter %d != %ld!\n",
    847                     (bitcount+7)/8,oggpack_bytes(&o));
    848             exit(1);
    849           }
    850 
    851         }
    852         _end_verify2(count);
    853 
    854       }
    855       ogg_buffer_release(or);
    856     }
    857   }
    858   fprintf(stderr,"\rRandomized testing (LSb)... ok.   \n");
    859 
    860   return(0);
    861 }
    862 
    863 #ifdef _WIN32_WCE
    864 int WinMain(void){
    865     return main();
    866 }
    867 #endif
    868 
    869 #endif
    870