/******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * ALL REDISTRIBUTION RIGHTS RESERVED. * * * ******************************************************************** 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 #include #include "ogg.h" #define BUFFER_INCREMENT 256 static unsigned long mask[]= {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff, 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff, 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, 0x3fffffff,0x7fffffff,0xffffffff }; void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){ memset(b,0,sizeof(*b)); b->buffer=b->ptr=buf; b->storage=bytes; } /* Read in bits without advancing the bitptr; bits <= 32 */ long oggpack_look(oggpack_buffer *b,int bits){ unsigned long ret; unsigned long m=mask[bits]; bits+=b->endbit; if(b->endbyte+4>=b->storage){ /* not the main path */ if(b->endbyte*8+bits>b->storage*8)return(-1); } 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); } long oggpack_look1(oggpack_buffer *b){ if(b->endbyte>=b->storage)return(-1); return((b->ptr[0]>>b->endbit)&1); } void oggpack_adv(oggpack_buffer *b,int bits){ bits+=b->endbit; b->ptr+=bits/8; b->endbyte+=bits/8; b->endbit=bits&7; } void oggpack_adv1(oggpack_buffer *b){ if(++(b->endbit)>7){ b->endbit=0; b->ptr++; b->endbyte++; } } /* bits <= 32 */ long oggpack_read(oggpack_buffer *b,int bits){ unsigned long ret; unsigned long m=mask[bits]; bits+=b->endbit; if(b->endbyte+4>=b->storage){ /* not the main path */ ret=-1UL; if(b->endbyte*8+bits>b->storage*8)goto overflow; } 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; overflow: b->ptr+=bits/8; b->endbyte+=bits/8; b->endbit=bits&7; return(ret); } long oggpack_read1(oggpack_buffer *b){ unsigned long ret; if(b->endbyte>=b->storage){ /* not the main path */ ret=-1UL; goto overflow; } ret=(b->ptr[0]>>b->endbit)&1; overflow: b->endbit++; if(b->endbit>7){ b->endbit=0; b->ptr++; b->endbyte++; } return(ret); } #undef BUFFER_INCREMENT