Fix the bug that was causing the last byte of the stream to be returned incorrectly, as well as undo jm's reversion, which can cause ec_dec_tell() to operate incorrectly at the end of the stream.

A few other minor updates are included as well.

git-svn-id: http://svn.xiph.org/trunk/ghost@14427 0101bb08-14d6-0310-b084-bc0e0c8e3800
This commit is contained in:
tterribe 2008-01-23 23:04:43 +00:00 committed by Jean-Marc Valin
parent 77ff83a28c
commit 7e3293f713
5 changed files with 85 additions and 55 deletions

View file

@ -1,3 +1,4 @@
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
#include "probenc.h" #include "probenc.h"
@ -139,6 +140,32 @@ int main(int _argc,char **_argv){
ldexp(nbits2,-4),ldexp(nbits,-4)); ldexp(nbits2,-4),ldexp(nbits,-4));
} }
ec_byte_writeclear(&buf); ec_byte_writeclear(&buf);
fprintf(stderr,"All tests passed.\n"); fprintf(stderr,"Testing random streams...\n");
srand(0);
for(i=0;i<1024;i++){
unsigned *data;
int j;
ft=rand()/((RAND_MAX>>9)+1)+512;
sz=rand()/((RAND_MAX>>9)+1);
data=(unsigned *)malloc(sz*sizeof(*data));
ec_byte_writeinit(&buf);
ec_enc_init(&enc,&buf);
for(j=0;j<sz;j++){
data[j]=rand()%ft;
ec_enc_uint(&enc,data[j],ft);
}
ec_enc_done(&enc);
ec_byte_readinit(&buf,ec_byte_get_buffer(&buf),ec_byte_bytes(&buf));
ec_dec_init(&dec,&buf);
for(j=0;j<sz;j++){
sym=ec_dec_uint(&dec,ft);
if(sym!=data[j]){
fprintf(stderr,
"Decoded %i instead of %i with ft of %i at position %i of %i.\n",
sym,data[j],ft,j,sz);
}
}
ec_byte_writeclear(&buf);
}
return 0; return 0;
} }

View file

@ -138,25 +138,26 @@ static int ec_dec_in(ec_dec *_this){
ret=ec_byte_read1(_this->buf); ret=ec_byte_read1(_this->buf);
if(ret<0){ if(ret<0){
unsigned char *buf; unsigned char *buf;
long bytes; long i;
bytes=ec_byte_bytes(_this->buf); i=ec_byte_bytes(_this->buf);
buf=ec_byte_get_buffer(_this->buf); buf=ec_byte_get_buffer(_this->buf);
/*Breaking abstraction: don't do this at home, kids.*/ /*Breaking abstraction: don't do this at home, kids.*/
if(_this->buf->storage==bytes){ if(_this->buf->storage==i&&i>0){
ec_byte_adv1(_this->buf); unsigned char *buf;
if(bytes>0){ buf=ec_byte_get_buffer(_this->buf);
unsigned char *p; /*If we end in a string of 0 or more EC_FOF_RSV1 bytes preceded by a
p=buf+bytes; zero, return an extra EC_FOF_RSV1 byte.*/
/*If we end in a string of 0 or more EC_FOF_RSV1 bytes preceded by a do i--;
zero, return an extra EC_FOF_RSV1 byte.*/ while(i>0&&buf[i]==EC_FOF_RSV1);
do p--; if(!buf[i])ret=EC_FOF_RSV1;
while(p>buf&&p[0]==EC_FOF_RSV1); else ret=0;
if(!p[0])return EC_FOF_RSV1;
}
} }
return 0; else ret=0;
/*Needed to make sure the above conditional only triggers once, and to keep
oc_dec_tell() operating correctly.*/
ec_byte_adv1(_this->buf);
} }
else return ret; return ret;
} }
/*Normalizes the contents of dif and rng so that rng lies entirely in the /*Normalizes the contents of dif and rng so that rng lies entirely in the

View file

@ -169,25 +169,26 @@ void ec_enc_done(ec_enc *_this){
} }
/*If we have a buffered byte...*/ /*If we have a buffered byte...*/
if(_this->rem>=0){ if(_this->rem>=0){
unsigned char *p;
unsigned char *buf; unsigned char *buf;
long i;
/*Flush it into the output buffer.*/ /*Flush it into the output buffer.*/
ec_enc_carry_out(_this,0); ec_enc_carry_out(_this,0);
_this->rem=-1; _this->rem=-1;
/*We may be able to drop some redundant bytes from the end.*/ /*We may be able to drop some redundant bytes from the end.*/
buf=ec_byte_get_buffer(_this->buf); buf=ec_byte_get_buffer(_this->buf);
p=buf+ec_byte_bytes(_this->buf)-1; i=ec_byte_bytes(_this->buf);
/*Strip trailing zeros.*/ /*Strip trailing zeros.*/
while(p>=buf&&!p[0])p--; do i--;
while(i>0&&!buf[i]);
/*Strip one trailing EC_FOF_RSV1 byte if the buffer ends in a string of /*Strip one trailing EC_FOF_RSV1 byte if the buffer ends in a string of
consecutive EC_FOF_RSV1 bytes preceded by one (or more) zeros.*/ consecutive EC_FOF_RSV1 bytes preceded by one (or more) zeros.*/
if(p>buf&&p[0]==EC_FOF_RSV1){ if(i>0&&buf[i]==EC_FOF_RSV1){
unsigned char *q; long j;
q=p; j=i;
do q--; do j--;
while(q>buf&&q[0]==EC_FOF_RSV1); while(j>0&&buf[j]==EC_FOF_RSV1);
if(!q[0])p--; if(!buf[j])i--;
} }
ec_byte_writetrunc(_this->buf,p+1-buf); ec_byte_writetrunc(_this->buf,i+1);
} }
} }

View file

@ -110,6 +110,7 @@
}*/ }*/
#include <stdio.h>
/*Gets the next byte of input. /*Gets the next byte of input.
After all the bytes in the current packet have been consumed, and the extra After all the bytes in the current packet have been consumed, and the extra
@ -121,25 +122,26 @@ static int ec_dec_in(ec_dec *_this){
ret=ec_byte_read1(_this->buf); ret=ec_byte_read1(_this->buf);
if(ret<0){ if(ret<0){
unsigned char *buf; unsigned char *buf;
long bytes; long i;
bytes=ec_byte_bytes(_this->buf); i=ec_byte_bytes(_this->buf);
buf=ec_byte_get_buffer(_this->buf); buf=ec_byte_get_buffer(_this->buf);
/*Breaking abstraction: don't do this at home, kids.*/ /*Breaking abstraction: don't do this at home, kids.*/
if(_this->buf->storage==bytes){ if(_this->buf->storage==i&&i>0){
ec_byte_adv1(_this->buf); unsigned char *buf;
if(bytes>0){ buf=ec_byte_get_buffer(_this->buf);
unsigned char *p; /*If we end in a string of 0 or more EC_FOF_RSV1 bytes preceded by a
p=buf+bytes; zero, return an extra EC_FOF_RSV1 byte.*/
/*If we end in a string of 0 or more EC_FOF_RSV1 bytes preceded by a do i--;
zero, return an extra EC_FOF_RSV1 byte.*/ while(i>0&&buf[i]==EC_FOF_RSV1);
do p--; if(!buf[i])ret=EC_FOF_RSV1;
while(p>buf&&p[0]==EC_FOF_RSV1); else ret=0;
if(!p[0])return EC_FOF_RSV1;
}
} }
return 0; else ret=0;
/*Needed to make sure the above conditional only triggers once, and to keep
oc_dec_tell() operating correctly.*/
ec_byte_adv1(_this->buf);
} }
else return ret; return ret;
} }
/*Normalizes the contents of dif and rng so that rng lies entirely in the /*Normalizes the contents of dif and rng so that rng lies entirely in the

View file

@ -79,12 +79,10 @@ void ec_enc_init(ec_enc *_this,ec_byte_buffer *_buf){
} }
void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){ void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
unsigned r; ec_uint32 r;
unsigned s;
r=_this->rng/_ft; r=_this->rng/_ft;
if(_fl>0){ if(_fl>0){
s=r*(_ft-_fl); _this->low+=_this->rng-r*(_ft-_fl);
_this->low+=_this->rng-s;
_this->rng=r*(_fh-_fl); _this->rng=r*(_fh-_fl);
} }
else _this->rng-=r*(_ft-_fh); else _this->rng-=r*(_ft-_fh);
@ -141,25 +139,26 @@ void ec_enc_done(ec_enc *_this){
} }
/*If we have a buffered byte...*/ /*If we have a buffered byte...*/
if(_this->rem>=0){ if(_this->rem>=0){
unsigned char *p;
unsigned char *buf; unsigned char *buf;
long i;
/*Flush it into the output buffer.*/ /*Flush it into the output buffer.*/
ec_enc_carry_out(_this,0); ec_enc_carry_out(_this,0);
_this->rem=-1; _this->rem=-1;
/*We may be able to drop some redundant bytes from the end.*/ /*We may be able to drop some redundant bytes from the end.*/
buf=ec_byte_get_buffer(_this->buf); buf=ec_byte_get_buffer(_this->buf);
p=buf+ec_byte_bytes(_this->buf)-1; i=ec_byte_bytes(_this->buf);
/*Strip trailing zeros.*/ /*Strip trailing zeros.*/
while(p>=buf&&!p[0])p--; do i--;
while(i>0&&!buf[i]);
/*Strip one trailing EC_FOF_RSV1 byte if the buffer ends in a string of /*Strip one trailing EC_FOF_RSV1 byte if the buffer ends in a string of
consecutive EC_FOF_RSV1 bytes preceded by one (or more) zeros.*/ consecutive EC_FOF_RSV1 bytes preceded by one (or more) zeros.*/
if(p>buf&&p[0]==EC_FOF_RSV1){ if(i>0&&buf[i]==EC_FOF_RSV1){
unsigned char *q; long j;
q=p; j=i;
do q--; do j--;
while(q>buf&&q[0]==EC_FOF_RSV1); while(j>0&&buf[j]==EC_FOF_RSV1);
if(!q[0])p--; if(!buf[j])i--;
} }
ec_byte_writetrunc(_this->buf,p+1-buf); ec_byte_writetrunc(_this->buf,i+1);
} }
} }