/********************************************************************
* *
* THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* 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-2014 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: packing variable sized words into an octet stream
********************************************************************/
/* We're 'LSb' endian; if we write a word but read individual bits,
then we'll read the lsb first */
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <ogg/ogg.h>
#define BUFFER_INCREMENT
256
static const unsigned long mask[]=
{
0 x00000000,
0 x00000001,
0 x00000003,
0 x00000007,
0 x0000000f,
0 x0000001f,
0 x0000003f,
0 x0000007f,
0 x000000ff,
0 x000001ff,
0 x000003ff,
0 x000007ff,
0 x00000fff,
0 x00001fff,
0 x00003fff,
0 x00007fff,
0 x0000ffff,
0 x0001ffff,
0 x0003ffff,
0 x0007ffff,
0 x000fffff,
0 x001fffff,
0 x003fffff,
0 x007fffff,
0 x00ffffff,
0 x01ffffff,
0 x03ffffff,
0 x07ffffff,
0 x0fffffff,
0 x1fffffff,
0 x3fffffff,
0 x7fffffff,
0 xffffffff };
static const unsigned int mask8B[]=
{
0 x00,
0 x80,
0 xc0,
0 xe0,
0 xf0,
0 xf8,
0 xfc,
0 xfe,
0 xff};
void oggpack_writeinit(oggpack_buffer *b){
memset(b,
0 ,
sizeof (*b));
b->ptr=b->buffer=_ogg_malloc(BUFFER_INCREMENT);
b->buffer[
0 ]=
'\0' ;
b->storage=BUFFER_INCREMENT;
}
void oggpackB_writeinit(oggpack_buffer *b){
oggpack_writeinit(b);
}
int oggpack_writecheck(oggpack_buffer *b){
if (!b->ptr || !b->storage)
return -
1 ;
return 0 ;
}
int oggpackB_writecheck(oggpack_buffer *b){
return oggpack_writecheck(b);
}
void oggpack_writetrunc(oggpack_buffer *b,
long bits){
long bytes=bits>>
3 ;
if (b->ptr){
bits-=bytes*
8 ;
b->ptr=b->buffer+bytes;
b->endbit=bits;
b->endbyte=bytes;
*b->ptr&=mask[bits];
}
}
void oggpackB_writetrunc(oggpack_buffer *b,
long bits){
long bytes=bits>>
3 ;
if (b->ptr){
bits-=bytes*
8 ;
b->ptr=b->buffer+bytes;
b->endbit=bits;
b->endbyte=bytes;
*b->ptr&=mask8B[bits];
}
}
/* Takes only up to 32 bits. */
void oggpack_write(oggpack_buffer *b,
unsigned long value,
int bits){
if (bits<
0 || bits>
32 )
goto err;
if (b->endbyte>=b->storage-
4 ){
void *ret;
if (!b->ptr)
return ;
if (b->storage>LONG_MAX-BUFFER_INCREMENT)
goto err;
ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
if (!ret)
goto err;
b->buffer=ret;
b->storage+=BUFFER_INCREMENT;
b->ptr=b->buffer+b->endbyte;
}
value&=mask[bits];
bits+=b->endbit;
b->ptr[
0 ]|=value<<b->endbit;
if (bits>=
8 ){
b->ptr[
1 ]=(
unsigned char )(value>>(
8 -b->endbit));
if (bits>=
16 ){
b->ptr[
2 ]=(
unsigned char )(value>>(
16 -b->endbit));
if (bits>=
24 ){
b->ptr[
3 ]=(
unsigned char )(value>>(
24 -b->endbit));
if (bits>=
32 ){
if (b->endbit)
b->ptr[
4 ]=(
unsigned char )(value>>(
32 -b->endbit));
else
b->ptr[
4 ]=
0 ;
}
}
}
}
b->endbyte+=bits/
8 ;
b->ptr+=bits/
8 ;
b->endbit=bits&
7 ;
return ;
err:
oggpack_writeclear(b);
}
/* Takes only up to 32 bits. */
void oggpackB_write(oggpack_buffer *b,
unsigned long value,
int bits){
if (bits<
0 || bits>
32 )
goto err;
if (b->endbyte>=b->storage-
4 ){
void *ret;
if (!b->ptr)
return ;
if (b->storage>LONG_MAX-BUFFER_INCREMENT)
goto err;
ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
if (!ret)
goto err;
b->buffer=ret;
b->storage+=BUFFER_INCREMENT;
b->ptr=b->buffer+b->endbyte;
}
value=(value&mask[bits])<<(
32 -bits);
bits+=b->endbit;
b->ptr[
0 ]|=value>>(
24 +b->endbit);
if (bits>=
8 ){
b->ptr[
1 ]=(
unsigned char )(value>>(
16 +b->endbit));
if (bits>=
16 ){
b->ptr[
2 ]=(
unsigned char )(value>>(
8 +b->endbit));
if (bits>=
24 ){
b->ptr[
3 ]=(
unsigned char )(value>>(b->endbit));
if (bits>=
32 ){
if (b->endbit)
b->ptr[
4 ]=(
unsigned char )(value<<(
8 -b->endbit));
else
b->ptr[
4 ]=
0 ;
}
}
}
}
b->endbyte+=bits/
8 ;
b->ptr+=bits/
8 ;
b->endbit=bits&
7 ;
return ;
err:
oggpack_writeclear(b);
}
void oggpack_writealign(oggpack_buffer *b){
int bits=
8 -b->endbit;
if (bits<
8 )
oggpack_write(b,
0 ,bits);
}
void oggpackB_writealign(oggpack_buffer *b){
int bits=
8 -b->endbit;
if (bits<
8 )
oggpackB_write(b,
0 ,bits);
}
static void oggpack_writecopy_helper(oggpack_buffer *b,
void *source,
long bits,
void (*w)(oggpack_buffer *,
unsigned long ,
int ),
int msb){
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 );
}
else {
/* aligned block copy */
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);
else
w(b,(
unsigned long )(ptr[bytes]),bits);
}
return ;
err:
oggpack_writeclear(b);
}
void oggpack_writecopy(oggpack_buffer *b,
void *source,
long bits){
oggpack_writecopy_helper(b,source,bits,oggpack_write,
0 );
}
void oggpackB_writecopy(oggpack_buffer *b,
void *source,
long bits){
oggpack_writecopy_helper(b,source,bits,oggpackB_write,
1 );
}
void oggpack_reset(oggpack_buffer *b){
if (!b->ptr)
return ;
b->ptr=b->buffer;
b->buffer[
0 ]=
0 ;
b->endbit=b->endbyte=
0 ;
}
void oggpackB_reset(oggpack_buffer *b){
oggpack_reset(b);
}
void oggpack_writeclear(oggpack_buffer *b){
if (b->buffer)_ogg_free(b->buffer);
memset(b,
0 ,
sizeof (*b));
}
void oggpackB_writeclear(oggpack_buffer *b){
oggpack_writeclear(b);
}
void oggpack_readinit(oggpack_buffer *b,
unsigned char *buf,
int bytes){
memset(b,
0 ,
sizeof (*b));
b->buffer=b->ptr=buf;
b->storage=bytes;
}
void oggpackB_readinit(oggpack_buffer *b,
unsigned char *buf,
int bytes){
oggpack_readinit(b,buf,bytes);
}
/* Read in bits without advancing the bitptr; bits <= 32 */
long oggpack_look(oggpack_buffer *b,
int bits){
unsigned long ret;
unsigned long m;
if (bits<
0 || bits>
32 )
return -
1 ;
m=mask[bits];
bits+=b->endbit;
if (b->endbyte >= b->storage-
4 ){
/* not the main path */
if (b->endbyte > b->storage-((bits+
7 )>>
3 ))
return -
1 ;
/* special case to avoid reading b->ptr[0], which might be past the end of
the buffer; also skips some useless accounting */
else if (!bits)
return (
0 L);
}
ret=b->ptr[
0 ]>>b->endbit;
if (bits>
8 ){
ret|=b->ptr[
1 ]<<(
8 -b->endbit);
if (bits>
16 ){
ret|=b->ptr[
2 ]<<(
16 -b->endbit);
if (bits>
24 ){
ret|=b->ptr[
3 ]<<(
24 -b->endbit);
if (bits>
32 && b->endbit)
ret|=b->ptr[
4 ]<<(
32 -b->endbit);
}
}
}
return (m&ret);
}
/* Read in bits without advancing the bitptr; bits <= 32 */
long oggpackB_look(oggpack_buffer *b,
int bits){
unsigned long ret;
int m=
32 -bits;
if (m<
0 || m>
32 )
return -
1 ;
bits+=b->endbit;
if (b->endbyte >= b->storage-
4 ){
/* not the main path */
if (b->endbyte > b->storage-((bits+
7 )>>
3 ))
return -
1 ;
/* special case to avoid reading b->ptr[0], which might be past the end of
the buffer; also skips some useless accounting */
else if (!bits)
return (
0 L);
}
ret=b->ptr[
0 ]<<(
24 +b->endbit);
if (bits>
8 ){
ret|=b->ptr[
1 ]<<(
16 +b->endbit);
if (bits>
16 ){
ret|=b->ptr[
2 ]<<(
8 +b->endbit);
if (bits>
24 ){
ret|=b->ptr[
3 ]<<(b->endbit);
if (bits>
32 && b->endbit)
ret|=b->ptr[
4 ]>>(
8 -b->endbit);
}
}
}
return ((ret&
0 xffffffff)>>(m>>
1 ))>>((m+
1 )>>
1 );
}
long oggpack_look1(oggpack_buffer *b){
if (b->endbyte>=b->storage)
return (-
1 );
return ((b->ptr[
0 ]>>b->endbit)&
1 );
}
long oggpackB_look1(oggpack_buffer *b){
if (b->endbyte>=b->storage)
return (-
1 );
return ((b->ptr[
0 ]>>(
7 -b->endbit))&
1 );
}
void oggpack_adv(oggpack_buffer *b,
int bits){
bits+=b->endbit;
if (b->endbyte > b->storage-((bits+
7 )>>
3 ))
goto overflow;
b->ptr+=bits/
8 ;
b->endbyte+=bits/
8 ;
b->endbit=bits&
7 ;
return ;
overflow:
b->ptr=NULL;
b->endbyte=b->storage;
b->endbit=
1 ;
}
void oggpackB_adv(oggpack_buffer *b,
int bits){
oggpack_adv(b,bits);
}
void oggpack_adv1(oggpack_buffer *b){
if (++(b->endbit)>
7 ){
b->endbit=
0 ;
b->ptr++;
b->endbyte++;
}
}
void oggpackB_adv1(oggpack_buffer *b){
oggpack_adv1(b);
}
/* bits <= 32 */
long oggpack_read(oggpack_buffer *b,
int bits){
long ret;
unsigned long m;
if (bits<
0 || bits>
32 )
goto err;
m=mask[bits];
bits+=b->endbit;
if (b->endbyte >= b->storage-
4 ){
/* not the main path */
if (b->endbyte > b->storage-((bits+
7 )>>
3 ))
goto overflow;
/* special case to avoid reading b->ptr[0], which might be past the end of
the buffer; also skips some useless accounting */
else if (!bits)
return (
0 L);
}
ret=b->ptr[
0 ]>>b->endbit;
if (bits>
8 ){
ret|=b->ptr[
1 ]<<(
8 -b->endbit);
if (bits>
16 ){
ret|=b->ptr[
2 ]<<(
16 -b->endbit);
if (bits>
24 ){
ret|=b->ptr[
3 ]<<(
24 -b->endbit);
if (bits>
32 && b->endbit){
ret|=b->ptr[
4 ]<<(
32 -b->endbit);
}
}
}
}
ret&=m;
b->ptr+=bits/
8 ;
b->endbyte+=bits/
8 ;
b->endbit=bits&
7 ;
return ret;
overflow:
err:
b->ptr=NULL;
b->endbyte=b->storage;
b->endbit=
1 ;
return -
1 L;
}
/* bits <= 32 */
long oggpackB_read(oggpack_buffer *b,
int bits){
long ret;
long m=
32 -bits;
if (m<
0 || m>
32 )
goto err;
bits+=b->endbit;
if (b->endbyte+
4 >=b->storage){
/* not the main path */
if (b->endbyte > b->storage-((bits+
7 )>>
3 ))
goto overflow;
/* special case to avoid reading b->ptr[0], which might be past the end of
the buffer; also skips some useless accounting */
else if (!bits)
return (
0 L);
}
ret=b->ptr[
0 ]<<(
24 +b->endbit);
if (bits>
8 ){
ret|=b->ptr[
1 ]<<(
16 +b->endbit);
if (bits>
16 ){
ret|=b->ptr[
2 ]<<(
8 +b->endbit);
if (bits>
24 ){
ret|=b->ptr[
3 ]<<(b->endbit);
if (bits>
32 && b->endbit)
ret|=b->ptr[
4 ]>>(
8 -b->endbit);
}
}
}
ret=((ret&
0 xffffffffUL)>>(m>>
1 ))>>((m+
1 )>>
1 );
b->ptr+=bits/
8 ;
b->endbyte+=bits/
8 ;
b->endbit=bits&
7 ;
return ret;
overflow:
err:
b->ptr=NULL;
b->endbyte=b->storage;
b->endbit=
1 ;
return -
1 L;
}
long oggpack_read1(oggpack_buffer *b){
long ret;
if (b->endbyte >= b->storage)
goto overflow;
ret=(b->ptr[
0 ]>>b->endbit)&
1 ;
b->endbit++;
if (b->endbit>
7 ){
b->endbit=
0 ;
b->ptr++;
b->endbyte++;
}
return ret;
overflow:
b->ptr=NULL;
b->endbyte=b->storage;
b->endbit=
1 ;
return -
1 L;
}
long oggpackB_read1(oggpack_buffer *b){
long ret;
if (b->endbyte >= b->storage)
goto overflow;
ret=(b->ptr[
0 ]>>(
7 -b->endbit))&
1 ;
b->endbit++;
if (b->endbit>
7 ){
b->endbit=
0 ;
b->ptr++;
b->endbyte++;
}
return ret;
overflow:
b->ptr=NULL;
b->endbyte=b->storage;
b->endbit=
1 ;
return -
1 L;
}
long oggpack_bytes(oggpack_buffer *b){
return (b->endbyte+(b->endbit+
7 )/
8 );
}
long oggpack_bits(oggpack_buffer *b){
return (b->endbyte*
8 +b->endbit);
}
long oggpackB_bytes(oggpack_buffer *b){
return oggpack_bytes(b);
}
long oggpackB_bits(oggpack_buffer *b){
return oggpack_bits(b);
}
unsigned char *oggpack_get_buffer(oggpack_buffer *b){
return (b->buffer);
}
unsigned char *oggpackB_get_buffer(oggpack_buffer *b){
return oggpack_get_buffer(b);
}
/* Self test of the bitwise routines; everything else is based on
them, so they damned well better be solid. */
#ifdef _V_SELFTEST
#include <stdio.h>
static int ilog(
unsigned int v){
int ret=
0 ;
while (v){
ret++;
v>>=
1 ;
}
return (ret);
}
oggpack_buffer o;
oggpack_buffer r;
void report(
char *in){
fprintf(stderr,
"%s" ,in);
exit (
1 );
}
void cliptest(
unsigned long *b,
int vals,
int bits,
int *comp,
int compsize){
long bytes,i;
unsigned char *buffer;
oggpack_reset(&o);
for (i=
0 ;i<vals;i++)
oggpack_write(&o,b[i],bits?bits:ilog(b[i]));
buffer=oggpack_get_buffer(&o);
bytes=oggpack_bytes(&o);
if (bytes!=compsize)report(
"wrong number of bytes!\n" );
for (i=
0 ;i<bytes;i++)
if (buffer[i]!=comp[i]){
for (i=
0 ;i<bytes;i++)fprintf(stderr,
"%x %x\n" ,(
int )buffer[i],(
int )comp[i]);
report(
"wrote incorrect value!\n" );
}
oggpack_readinit(&r,buffer,bytes);
for (i=
0 ;i<vals;i++){
int tbit=bits?bits:ilog(b[i]);
if (oggpack_look(&r,tbit)==-
1 )
report(
"out of data!\n" );
if (oggpack_look(&r,tbit)!=(b[i]&mask[tbit]))
report(
"looked at incorrect value!\n" );
if (tbit==
1 )
if (oggpack_look1(&r)!=(b[i]&mask[tbit]))
report(
"looked at single bit incorrect value!\n" );
if (tbit==
1 ){
if (oggpack_read1(&r)!=(b[i]&mask[tbit]))
report(
"read incorrect single bit value!\n" );
}
else {
if (oggpack_read(&r,tbit)!=(b[i]&mask[tbit]))
report(
"read incorrect value!\n" );
}
}
if (oggpack_bytes(&r)!=bytes)report(
"leftover bytes after read!\n" );
}
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]));
buffer=oggpackB_get_buffer(&o);
bytes=oggpackB_bytes(&o);
if (bytes!=compsize)report(
"wrong number of bytes!\n" );
for (i=
0 ;i<bytes;i++)
if (buffer[i]!=comp[i]){
for (i=
0 ;i<bytes;i++)fprintf(stderr,
"%x %x\n" ,(
int )buffer[i],(
int )comp[i]);
report(
"wrote incorrect value!\n" );
}
oggpackB_readinit(&r,buffer,bytes);
for (i=
0 ;i<vals;i++){
int tbit=bits?bits:ilog(b[i]);
if (oggpackB_look(&r,tbit)==-
1 )
report(
"out of data!\n" );
if (oggpackB_look(&r,tbit)!=(b[i]&mask[tbit]))
report(
"looked at incorrect value!\n" );
if (tbit==
1 )
if (oggpackB_look1(&r)!=(b[i]&mask[tbit]))
report(
"looked at single bit incorrect value!\n" );
if (tbit==
1 ){
if (oggpackB_read1(&r)!=(b[i]&mask[tbit]))
report(
"read incorrect single bit value!\n" );
}
else {
if (oggpackB_read(&r,tbit)!=(b[i]&mask[tbit]))
report(
"read incorrect value!\n" );
}
}
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^
0 x5a)&
0 xff,
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^0 x5a)&0 xff,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,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 };
int test1size=43 ;
static unsigned long testbuffer2[]=
{216531625 L,1237861823 ,56732452 ,131 ,3212421 ,12325343 ,34547562 ,12313212 ,
1233432 ,534 ,5 ,346435231 ,14436467 ,7869299 ,76326614 ,167548585 ,
85525151 ,0 ,12321 ,1 ,349528352 };
int test2size=21 ;
static unsigned long testbuffer3[]=
{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 ,
0 ,1 ,30 ,1 ,1 ,1 ,0 ,0 ,1 ,0 ,0 ,0 ,12 ,0 ,11 ,0 ,1 ,0 ,0 ,1 };
int test3size=56 ;
static unsigned long large[]=
{2136531625 L,2137861823 ,56732452 ,131 ,3212421 ,12325343 ,34547562 ,12313212 ,
1233432 ,534 ,5 ,2146435231 ,14436467 ,7869299 ,76326614 ,167548585 ,
85525151 ,0 ,12321 ,1 ,2146528352 };
int onesize=33 ;
static int one[33 ]={146 ,25 ,44 ,151 ,195 ,15 ,153 ,176 ,233 ,131 ,196 ,65 ,85 ,172 ,47 ,40 ,
34 ,242 ,223 ,136 ,35 ,222 ,211 ,86 ,171 ,50 ,225 ,135 ,214 ,75 ,172 ,
223 ,4 };
static int oneB[33 ]={150 ,101 ,131 ,33 ,203 ,15 ,204 ,216 ,105 ,193 ,156 ,65 ,84 ,85 ,222 ,
8 ,139 ,145 ,227 ,126 ,34 ,55 ,244 ,171 ,85 ,100 ,39 ,195 ,173 ,18 ,
245 ,251 ,128 };
int twosize=6 ;
static int two[6 ]={61 ,255 ,255 ,251 ,231 ,29 };
static int twoB[6 ]={247 ,63 ,255 ,253 ,249 ,120 };
int threesize=54 ;
static int three[54 ]={169 ,2 ,232 ,252 ,91 ,132 ,156 ,36 ,89 ,13 ,123 ,176 ,144 ,32 ,254 ,
142 ,224 ,85 ,59 ,121 ,144 ,79 ,124 ,23 ,67 ,90 ,90 ,216 ,79 ,23 ,83 ,
58 ,135 ,196 ,61 ,55 ,129 ,183 ,54 ,101 ,100 ,170 ,37 ,127 ,126 ,10 ,
100 ,52 ,4 ,14 ,18 ,86 ,77 ,1 };
static int threeB[54 ]={206 ,128 ,42 ,153 ,57 ,8 ,183 ,251 ,13 ,89 ,36 ,30 ,32 ,144 ,183 ,
130 ,59 ,240 ,121 ,59 ,85 ,223 ,19 ,228 ,180 ,134 ,33 ,107 ,74 ,98 ,
233 ,253 ,196 ,135 ,63 ,2 ,110 ,114 ,50 ,155 ,90 ,127 ,37 ,170 ,104 ,
200 ,20 ,254 ,4 ,58 ,106 ,176 ,144 ,0 };
int foursize=38 ;
static int four[38 ]={18 ,6 ,163 ,252 ,97 ,194 ,104 ,131 ,32 ,1 ,7 ,82 ,137 ,42 ,129 ,11 ,72 ,
132 ,60 ,220 ,112 ,8 ,196 ,109 ,64 ,179 ,86 ,9 ,137 ,195 ,208 ,122 ,169 ,
28 ,2 ,133 ,0 ,1 };
static int fourB[38 ]={36 ,48 ,102 ,83 ,243 ,24 ,52 ,7 ,4 ,35 ,132 ,10 ,145 ,21 ,2 ,93 ,2 ,41 ,
1 ,219 ,184 ,16 ,33 ,184 ,54 ,149 ,170 ,132 ,18 ,30 ,29 ,98 ,229 ,67 ,
129 ,10 ,4 ,32 };
int fivesize=45 ;
static int five[45 ]={169 ,2 ,126 ,139 ,144 ,172 ,30 ,4 ,80 ,72 ,240 ,59 ,130 ,218 ,73 ,62 ,
241 ,24 ,210 ,44 ,4 ,20 ,0 ,248 ,116 ,49 ,135 ,100 ,110 ,130 ,181 ,169 ,
84 ,75 ,159 ,2 ,1 ,0 ,132 ,192 ,8 ,0 ,0 ,18 ,22 };
static int fiveB[45 ]={1 ,84 ,145 ,111 ,245 ,100 ,128 ,8 ,56 ,36 ,40 ,71 ,126 ,78 ,213 ,226 ,
124 ,105 ,12 ,0 ,133 ,128 ,0 ,162 ,233 ,242 ,67 ,152 ,77 ,205 ,77 ,
172 ,150 ,169 ,129 ,79 ,128 ,0 ,6 ,4 ,32 ,0 ,27 ,9 ,0 };
int sixsize=7 ;
static int six[7 ]={17 ,177 ,170 ,242 ,169 ,19 ,148 };
static int sixB[7 ]={136 ,141 ,85 ,79 ,149 ,200 ,41 };
/* Test read/write together */
/* Later we test against pregenerated bitstreams */
oggpack_writeinit(&o);
fprintf(stderr,"\nSmall preclipped packing (LSb): " );
cliptest(testbuffer1,test1size,0 ,one,onesize);
fprintf(stderr,"ok." );
fprintf(stderr,"\nNull bit call (LSb): " );
cliptest(testbuffer3,test3size,0 ,two,twosize);
fprintf(stderr,"ok." );
fprintf(stderr,"\nLarge preclipped packing (LSb): " );
cliptest(testbuffer2,test2size,0 ,three,threesize);
fprintf(stderr,"ok." );
fprintf(stderr,"\n32 bit preclipped packing (LSb): " );
oggpack_reset(&o);
for (i=0 ;i<test2size;i++)
oggpack_write(&o,large[i],32 );
buffer=oggpack_get_buffer(&o);
bytes=oggpack_bytes(&o);
oggpack_readinit(&r,buffer,bytes);
for (i=0 ;i<test2size;i++){
if (oggpack_look(&r,32 )==-1 )report("out of data. failed!" );
if (oggpack_look(&r,32 )!=large[i]){
fprintf(stderr,"%ld != %lu (%lx!=%lx):" ,oggpack_look(&r,32 ),large[i],
oggpack_look(&r,32 ),large[i]);
report("read incorrect value!\n" );
}
oggpack_adv(&r,32 );
}
if (oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n" );
fprintf(stderr,"ok." );
fprintf(stderr,"\nSmall unclipped packing (LSb): " );
cliptest(testbuffer1,test1size,7 ,four,foursize);
fprintf(stderr,"ok." );
fprintf(stderr,"\nLarge unclipped packing (LSb): " );
cliptest(testbuffer2,test2size,17 ,five,fivesize);
fprintf(stderr,"ok." );
fprintf(stderr,"\nSingle bit unclipped packing (LSb): " );
cliptest(testbuffer3,test3size,1 ,six,sixsize);
fprintf(stderr,"ok." );
fprintf(stderr,"\nTesting read past end (LSb): " );
oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0" ,8 );
for (i=0 ;i<64 ;i++){
if (oggpack_read(&r,1 )!=0 ){
fprintf(stderr,"failed; got -1 prematurely.\n" );
exit (1 );
}
}
if (oggpack_look(&r,1 )!=-1 ||
oggpack_read(&r,1 )!=-1 ){
fprintf(stderr,"failed; read past end without -1.\n" );
exit (1 );
}
oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0" ,8 );
if (oggpack_read(&r,30 )!=0 || oggpack_read(&r,16 )!=0 ){
fprintf(stderr,"failed 2; got -1 prematurely.\n" );
exit (1 );
}
if (oggpack_look(&r,18 )!=0 ||
oggpack_look(&r,18 )!=0 ){
fprintf(stderr,"failed 3; got -1 prematurely.\n" );
exit (1 );
}
if (oggpack_look(&r,19 )!=-1 ||
oggpack_look(&r,19 )!=-1 ){
fprintf(stderr,"failed; read past end without -1.\n" );
exit (1 );
}
if (oggpack_look(&r,32 )!=-1 ||
oggpack_look(&r,32 )!=-1 ){
fprintf(stderr,"failed; read past end without -1.\n" );
exit (1 );
}
oggpack_writeclear(&o);
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&0 x7)
copytest(j,i);
for (i=BUFFER_INCREMENT*8 -71 ;i<BUFFER_INCREMENT*8 +71 ;i++)
for (j=1 ;j<40 ;j++)
if (j&0 x7)
copytest(j,i);
fprintf(stderr,"ok. \n" );
/********** lazy, cut-n-paste retest with MSb packing ***********/
/* Test read/write together */
/* Later we test against pregenerated bitstreams */
oggpackB_writeinit(&o);
fprintf(stderr,"\nSmall preclipped packing (MSb): " );
cliptestB(testbuffer1,test1size,0 ,oneB,onesize);
fprintf(stderr,"ok." );
fprintf(stderr,"\nNull bit call (MSb): " );
cliptestB(testbuffer3,test3size,0 ,twoB,twosize);
fprintf(stderr,"ok." );
fprintf(stderr,"\nLarge preclipped packing (MSb): " );
cliptestB(testbuffer2,test2size,0 ,threeB,threesize);
fprintf(stderr,"ok." );
fprintf(stderr,"\n32 bit preclipped packing (MSb): " );
oggpackB_reset(&o);
for (i=0 ;i<test2size;i++)
oggpackB_write(&o,large[i],32 );
buffer=oggpackB_get_buffer(&o);
bytes=oggpackB_bytes(&o);
oggpackB_readinit(&r,buffer,bytes);
for (i=0 ;i<test2size;i++){
if (oggpackB_look(&r,32 )==-1 )report("out of data. failed!" );
if (oggpackB_look(&r,32 )!=large[i]){
fprintf(stderr,"%ld != %lu (%lx!=%lx):" ,oggpackB_look(&r,32 ),large[i],
oggpackB_look(&r,32 ),large[i]);
report("read incorrect value!\n" );
}
oggpackB_adv(&r,32 );
}
if (oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n" );
fprintf(stderr,"ok." );
fprintf(stderr,"\nSmall unclipped packing (MSb): " );
cliptestB(testbuffer1,test1size,7 ,fourB,foursize);
fprintf(stderr,"ok." );
fprintf(stderr,"\nLarge unclipped packing (MSb): " );
cliptestB(testbuffer2,test2size,17 ,fiveB,fivesize);
fprintf(stderr,"ok." );
fprintf(stderr,"\nSingle bit unclipped packing (MSb): " );
cliptestB(testbuffer3,test3size,1 ,sixB,sixsize);
fprintf(stderr,"ok." );
fprintf(stderr,"\nTesting read past end (MSb): " );
oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0" ,8 );
for (i=0 ;i<64 ;i++){
if (oggpackB_read(&r,1 )!=0 ){
fprintf(stderr,"failed; got -1 prematurely.\n" );
exit (1 );
}
}
if (oggpackB_look(&r,1 )!=-1 ||
oggpackB_read(&r,1 )!=-1 ){
fprintf(stderr,"failed; read past end without -1.\n" );
exit (1 );
}
oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0" ,8 );
if (oggpackB_read(&r,30 )!=0 || oggpackB_read(&r,16 )!=0 ){
fprintf(stderr,"failed 2; got -1 prematurely.\n" );
exit (1 );
}
if (oggpackB_look(&r,18 )!=0 ||
oggpackB_look(&r,18 )!=0 ){
fprintf(stderr,"failed 3; got -1 prematurely.\n" );
exit (1 );
}
if (oggpackB_look(&r,19 )!=-1 ||
oggpackB_look(&r,19 )!=-1 ){
fprintf(stderr,"failed; read past end without -1.\n" );
exit (1 );
}
if (oggpackB_look(&r,32 )!=-1 ||
oggpackB_look(&r,32 )!=-1 ){
fprintf(stderr,"failed; read past end without -1.\n" );
exit (1 );
}
fprintf(stderr,"ok." );
oggpackB_writeclear(&o);
/* 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&0 x7)
copytestB(j,i);
for (i=BUFFER_INCREMENT*8 -71 ;i<BUFFER_INCREMENT*8 +71 ;i++)
for (j=1 ;j<40 ;j++)
if (j&0 x7)
copytestB(j,i);
fprintf(stderr,"ok. \n\n" );
return (0 );
}
#endif /* _V_SELFTEST */
#undef BUFFER_INCREMENT
Messung V0.5 in Prozent C=91 H=91 G=90
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-05)
¤
*© Formatika GbR, Deutschland