diff options
Diffstat (limited to 'drivers/ogg/bitwise.c')
-rw-r--r-- | drivers/ogg/bitwise.c | 315 |
1 files changed, 273 insertions, 42 deletions
diff --git a/drivers/ogg/bitwise.c b/drivers/ogg/bitwise.c index 3d02198094..145901d185 100644 --- a/drivers/ogg/bitwise.c +++ b/drivers/ogg/bitwise.c @@ -5,13 +5,13 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2014 * * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** function: packing variable sized words into an octet stream - last mod: $Id: bitwise.c 17287 2010-06-10 13:42:06Z tterribe $ + last mod: $Id: bitwise.c 19149 2014-05-27 16:26:23Z giles $ ********************************************************************/ @@ -93,11 +93,11 @@ void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){ b->ptr=b->buffer+b->endbyte; } - value&=mask[bits]; + value&=mask[bits]; bits+=b->endbit; - b->ptr[0]|=value<<b->endbit; - + b->ptr[0]|=value<<b->endbit; + if(bits>=8){ b->ptr[1]=(unsigned char)(value>>(8-b->endbit)); if(bits>=16){ @@ -136,11 +136,11 @@ void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){ b->ptr=b->buffer+b->endbyte; } - value=(value&mask[bits])<<(32-bits); + value=(value&mask[bits])<<(32-bits); bits+=b->endbit; - b->ptr[0]|=value>>(24+b->endbit); - + b->ptr[0]|=value>>(24+b->endbit); + if(bits>=8){ b->ptr[1]=(unsigned char)(value>>(16+b->endbit)); if(bits>=16){ @@ -187,37 +187,41 @@ static void oggpack_writecopy_helper(oggpack_buffer *b, unsigned char *ptr=(unsigned char *)source; long bytes=bits/8; + long pbytes=(b->endbit+bits)/8; bits-=bytes*8; + /* expand storage up-front */ + if(b->endbyte+pbytes>=b->storage){ + void *ret; + if(!b->ptr) goto err; + if(b->storage>b->endbyte+pbytes+BUFFER_INCREMENT) goto err; + b->storage=b->endbyte+pbytes+BUFFER_INCREMENT; + ret=_ogg_realloc(b->buffer,b->storage); + if(!ret) goto err; + b->buffer=ret; + b->ptr=b->buffer+b->endbyte; + } + + /* copy whole octets */ if(b->endbit){ int i; /* unaligned copy. Do it the hard way. */ for(i=0;i<bytes;i++) - w(b,(unsigned long)(ptr[i]),8); + w(b,(unsigned long)(ptr[i]),8); }else{ /* aligned block copy */ - if(b->endbyte+bytes+1>=b->storage){ - void *ret; - if(!b->ptr) goto err; - if(b->endbyte+bytes+BUFFER_INCREMENT>b->storage) goto err; - b->storage=b->endbyte+bytes+BUFFER_INCREMENT; - ret=_ogg_realloc(b->buffer,b->storage); - if(!ret) goto err; - b->buffer=ret; - b->ptr=b->buffer+b->endbyte; - } - memmove(b->ptr,source,bytes); b->ptr+=bytes; b->endbyte+=bytes; *b->ptr=0; - } + + /* copy trailing bits */ if(bits){ if(msb) - w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits); + w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits); else - w(b,(unsigned long)(ptr[bytes]),bits); + w(b,(unsigned long)(ptr[bytes]),bits); } return; err: @@ -281,11 +285,11 @@ long oggpack_look(oggpack_buffer *b,int bits){ ret=b->ptr[0]>>b->endbit; if(bits>8){ - ret|=b->ptr[1]<<(8-b->endbit); + ret|=b->ptr[1]<<(8-b->endbit); if(bits>16){ - ret|=b->ptr[2]<<(16-b->endbit); + ret|=b->ptr[2]<<(16-b->endbit); if(bits>24){ - ret|=b->ptr[3]<<(24-b->endbit); + ret|=b->ptr[3]<<(24-b->endbit); if(bits>32 && b->endbit) ret|=b->ptr[4]<<(32-b->endbit); } @@ -312,11 +316,11 @@ long oggpackB_look(oggpack_buffer *b,int bits){ ret=b->ptr[0]<<(24+b->endbit); if(bits>8){ - ret|=b->ptr[1]<<(16+b->endbit); + ret|=b->ptr[1]<<(16+b->endbit); if(bits>16){ - ret|=b->ptr[2]<<(8+b->endbit); + ret|=b->ptr[2]<<(8+b->endbit); if(bits>24){ - ret|=b->ptr[3]<<(b->endbit); + ret|=b->ptr[3]<<(b->endbit); if(bits>32 && b->endbit) ret|=b->ptr[4]>>(8-b->endbit); } @@ -386,11 +390,11 @@ long oggpack_read(oggpack_buffer *b,int bits){ ret=b->ptr[0]>>b->endbit; if(bits>8){ - ret|=b->ptr[1]<<(8-b->endbit); + ret|=b->ptr[1]<<(8-b->endbit); if(bits>16){ - ret|=b->ptr[2]<<(16-b->endbit); + ret|=b->ptr[2]<<(16-b->endbit); if(bits>24){ - ret|=b->ptr[3]<<(24-b->endbit); + ret|=b->ptr[3]<<(24-b->endbit); if(bits>32 && b->endbit){ ret|=b->ptr[4]<<(32-b->endbit); } @@ -429,11 +433,11 @@ long oggpackB_read(oggpack_buffer *b,int bits){ ret=b->ptr[0]<<(24+b->endbit); if(bits>8){ - ret|=b->ptr[1]<<(16+b->endbit); + ret|=b->ptr[1]<<(16+b->endbit); if(bits>16){ - ret|=b->ptr[2]<<(8+b->endbit); + ret|=b->ptr[2]<<(8+b->endbit); if(bits>24){ - ret|=b->ptr[3]<<(b->endbit); + ret|=b->ptr[3]<<(b->endbit); if(bits>32 && b->endbit) ret|=b->ptr[4]>>(8-b->endbit); } @@ -511,7 +515,7 @@ long oggpackB_bytes(oggpack_buffer *b){ long oggpackB_bits(oggpack_buffer *b){ return oggpack_bits(b); } - + unsigned char *oggpack_get_buffer(oggpack_buffer *b){ return(b->buffer); } @@ -534,7 +538,7 @@ static int ilog(unsigned int v){ } return(ret); } - + oggpack_buffer o; oggpack_buffer r; @@ -581,7 +585,7 @@ void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){ void cliptestB(unsigned long *b,int vals,int bits,int *comp,int compsize){ long bytes,i; unsigned char *buffer; - + oggpackB_reset(&o); for(i=0;i<vals;i++) oggpackB_write(&o,b[i],bits?bits:ilog(b[i])); @@ -613,9 +617,190 @@ void cliptestB(unsigned long *b,int vals,int bits,int *comp,int compsize){ if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n"); } +void copytest(int prefill, int copy){ + oggpack_buffer source_write; + oggpack_buffer dest_write; + oggpack_buffer source_read; + oggpack_buffer dest_read; + unsigned char *source; + unsigned char *dest; + long source_bytes,dest_bytes; + int i; + + oggpack_writeinit(&source_write); + oggpack_writeinit(&dest_write); + + for(i=0;i<(prefill+copy+7)/8;i++) + oggpack_write(&source_write,(i^0x5a)&0xff,8); + source=oggpack_get_buffer(&source_write); + source_bytes=oggpack_bytes(&source_write); + + /* prefill */ + oggpack_writecopy(&dest_write,source,prefill); + + /* check buffers; verify end byte masking */ + dest=oggpack_get_buffer(&dest_write); + dest_bytes=oggpack_bytes(&dest_write); + if(dest_bytes!=(prefill+7)/8){ + fprintf(stderr,"wrong number of bytes after prefill! %ld!=%d\n",dest_bytes,(prefill+7)/8); + exit(1); + } + oggpack_readinit(&source_read,source,source_bytes); + oggpack_readinit(&dest_read,dest,dest_bytes); + + for(i=0;i<prefill;i+=8){ + int s=oggpack_read(&source_read,prefill-i<8?prefill-i:8); + int d=oggpack_read(&dest_read,prefill-i<8?prefill-i:8); + if(s!=d){ + fprintf(stderr,"prefill=%d mismatch! byte %d, %x!=%x\n",prefill,i/8,s,d); + exit(1); + } + } + if(prefill<dest_bytes){ + if(oggpack_read(&dest_read,dest_bytes-prefill)!=0){ + fprintf(stderr,"prefill=%d mismatch! trailing bits not zero\n",prefill); + exit(1); + } + } + + /* second copy */ + oggpack_writecopy(&dest_write,source,copy); + + /* check buffers; verify end byte masking */ + dest=oggpack_get_buffer(&dest_write); + dest_bytes=oggpack_bytes(&dest_write); + if(dest_bytes!=(copy+prefill+7)/8){ + fprintf(stderr,"wrong number of bytes after prefill+copy! %ld!=%d\n",dest_bytes,(copy+prefill+7)/8); + exit(1); + } + oggpack_readinit(&source_read,source,source_bytes); + oggpack_readinit(&dest_read,dest,dest_bytes); + + for(i=0;i<prefill;i+=8){ + int s=oggpack_read(&source_read,prefill-i<8?prefill-i:8); + int d=oggpack_read(&dest_read,prefill-i<8?prefill-i:8); + if(s!=d){ + fprintf(stderr,"prefill=%d mismatch! byte %d, %x!=%x\n",prefill,i/8,s,d); + exit(1); + } + } + + oggpack_readinit(&source_read,source,source_bytes); + for(i=0;i<copy;i+=8){ + int s=oggpack_read(&source_read,copy-i<8?copy-i:8); + int d=oggpack_read(&dest_read,copy-i<8?copy-i:8); + if(s!=d){ + fprintf(stderr,"prefill=%d copy=%d mismatch! byte %d, %x!=%x\n",prefill,copy,i/8,s,d); + exit(1); + } + } + + if(copy+prefill<dest_bytes){ + if(oggpack_read(&dest_read,dest_bytes-copy-prefill)!=0){ + fprintf(stderr,"prefill=%d copy=%d mismatch! trailing bits not zero\n",prefill,copy); + exit(1); + } + } + + oggpack_writeclear(&source_write); + oggpack_writeclear(&dest_write); + + +} + +void copytestB(int prefill, int copy){ + oggpack_buffer source_write; + oggpack_buffer dest_write; + oggpack_buffer source_read; + oggpack_buffer dest_read; + unsigned char *source; + unsigned char *dest; + long source_bytes,dest_bytes; + int i; + + oggpackB_writeinit(&source_write); + oggpackB_writeinit(&dest_write); + + for(i=0;i<(prefill+copy+7)/8;i++) + oggpackB_write(&source_write,(i^0x5a)&0xff,8); + source=oggpackB_get_buffer(&source_write); + source_bytes=oggpackB_bytes(&source_write); + + /* prefill */ + oggpackB_writecopy(&dest_write,source,prefill); + + /* check buffers; verify end byte masking */ + dest=oggpackB_get_buffer(&dest_write); + dest_bytes=oggpackB_bytes(&dest_write); + if(dest_bytes!=(prefill+7)/8){ + fprintf(stderr,"wrong number of bytes after prefill! %ld!=%d\n",dest_bytes,(prefill+7)/8); + exit(1); + } + oggpackB_readinit(&source_read,source,source_bytes); + oggpackB_readinit(&dest_read,dest,dest_bytes); + + for(i=0;i<prefill;i+=8){ + int s=oggpackB_read(&source_read,prefill-i<8?prefill-i:8); + int d=oggpackB_read(&dest_read,prefill-i<8?prefill-i:8); + if(s!=d){ + fprintf(stderr,"prefill=%d mismatch! byte %d, %x!=%x\n",prefill,i/8,s,d); + exit(1); + } + } + if(prefill<dest_bytes){ + if(oggpackB_read(&dest_read,dest_bytes-prefill)!=0){ + fprintf(stderr,"prefill=%d mismatch! trailing bits not zero\n",prefill); + exit(1); + } + } + + /* second copy */ + oggpackB_writecopy(&dest_write,source,copy); + + /* check buffers; verify end byte masking */ + dest=oggpackB_get_buffer(&dest_write); + dest_bytes=oggpackB_bytes(&dest_write); + if(dest_bytes!=(copy+prefill+7)/8){ + fprintf(stderr,"wrong number of bytes after prefill+copy! %ld!=%d\n",dest_bytes,(copy+prefill+7)/8); + exit(1); + } + oggpackB_readinit(&source_read,source,source_bytes); + oggpackB_readinit(&dest_read,dest,dest_bytes); + + for(i=0;i<prefill;i+=8){ + int s=oggpackB_read(&source_read,prefill-i<8?prefill-i:8); + int d=oggpackB_read(&dest_read,prefill-i<8?prefill-i:8); + if(s!=d){ + fprintf(stderr,"prefill=%d mismatch! byte %d, %x!=%x\n",prefill,i/8,s,d); + exit(1); + } + } + + oggpackB_readinit(&source_read,source,source_bytes); + for(i=0;i<copy;i+=8){ + int s=oggpackB_read(&source_read,copy-i<8?copy-i:8); + int d=oggpackB_read(&dest_read,copy-i<8?copy-i:8); + if(s!=d){ + fprintf(stderr,"prefill=%d copy=%d mismatch! byte %d, %x!=%x\n",prefill,copy,i/8,s,d); + exit(1); + } + } + + if(copy+prefill<dest_bytes){ + if(oggpackB_read(&dest_read,dest_bytes-copy-prefill)!=0){ + fprintf(stderr,"prefill=%d copy=%d mismatch! trailing bits not zero\n",prefill,copy); + exit(1); + } + } + + oggpackB_writeclear(&source_write); + oggpackB_writeclear(&dest_write); + +} + int main(void){ unsigned char *buffer; - long bytes,i; + long bytes,i,j; static unsigned long testbuffer1[]= {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7, 567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4}; @@ -761,7 +946,31 @@ int main(void){ exit(1); } oggpack_writeclear(&o); - fprintf(stderr,"ok.\n"); + fprintf(stderr,"ok."); + + /* this is partly glassbox; we're mostly concerned about the allocation boundaries */ + + fprintf(stderr,"\nTesting aligned writecopies (LSb): "); + for(i=0;i<71;i++) + for(j=0;j<5;j++) + copytest(j*8,i); + for(i=BUFFER_INCREMENT*8-71;i<BUFFER_INCREMENT*8+71;i++) + for(j=0;j<5;j++) + copytest(j*8,i); + fprintf(stderr,"ok. "); + + fprintf(stderr,"\nTesting unaligned writecopies (LSb): "); + for(i=0;i<71;i++) + for(j=1;j<40;j++) + if(j&0x7) + copytest(j,i); + for(i=BUFFER_INCREMENT*8-71;i<BUFFER_INCREMENT*8+71;i++) + for(j=1;j<40;j++) + if(j&0x7) + copytest(j,i); + + fprintf(stderr,"ok. \n"); + /********** lazy, cut-n-paste retest with MSb packing ***********/ @@ -846,12 +1055,34 @@ int main(void){ fprintf(stderr,"failed; read past end without -1.\n"); exit(1); } + fprintf(stderr,"ok."); oggpackB_writeclear(&o); - fprintf(stderr,"ok.\n\n"); + /* this is partly glassbox; we're mostly concerned about the allocation boundaries */ + + fprintf(stderr,"\nTesting aligned writecopies (MSb): "); + for(i=0;i<71;i++) + for(j=0;j<5;j++) + copytestB(j*8,i); + for(i=BUFFER_INCREMENT*8-71;i<BUFFER_INCREMENT*8+71;i++) + for(j=0;j<5;j++) + copytestB(j*8,i); + fprintf(stderr,"ok. "); + + fprintf(stderr,"\nTesting unaligned writecopies (MSb): "); + for(i=0;i<71;i++) + for(j=1;j<40;j++) + if(j&0x7) + copytestB(j,i); + for(i=BUFFER_INCREMENT*8-71;i<BUFFER_INCREMENT*8+71;i++) + for(j=1;j<40;j++) + if(j&0x7) + copytestB(j,i); + + fprintf(stderr,"ok. \n\n"); return(0); -} +} #endif /* _V_SELFTEST */ #undef BUFFER_INCREMENT |