diff options
Diffstat (limited to 'Src/nsv/nsvbs.h')
-rw-r--r-- | Src/nsv/nsvbs.h | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/Src/nsv/nsvbs.h b/Src/nsv/nsvbs.h new file mode 100644 index 00000000..9ec59ef1 --- /dev/null +++ b/Src/nsv/nsvbs.h @@ -0,0 +1,202 @@ +/* +** nsvbs.h - NSV basic inline bitstream classes +** +** Copyright (C) 2001-2002 Nullsoft, Inc. +** Confidential Subject to NDA +** +** Note: these bitstream classes encode/decode everything in LSB. +** bits are stored from the lowest bit to the highest bit. +** putbits(4,0xE) will result in getbits(1)=0, getbits(1)=1, +** getbits(1)=1, getbits(1)=1 +** or of course, getbits(4) == 0xE :) +*/ + +#ifndef _NSVBS_H_ +#define _NSVBS_H_ + +#include <stdlib.h> +#include <memory.h> +#include <bfc/platform/types.h> +#include "../nu/GrowBuf.h" + +class nsv_OutBS +{ +public: + nsv_OutBS() { m_used = 0; m_curb=0; } + ~nsv_OutBS() { } + + void putbits(int nbits, unsigned int value) + { + while (nbits-- > 0) + { + m_curb|=(value&1)<<(m_used&7); + if (!((++m_used)&7)) + { + m_bits.add(&m_curb,1); + m_curb=0; + } + value>>=1; + } + } + + // lets you put in any amount of data, but does not preserve endianness. + void putdata(int nbits, void *data) + { + unsigned char *c=(unsigned char *)data; + if (!(m_used&7) && nbits >= 8) + { + m_bits.add(c,nbits/8); + c+=nbits/8; + m_used+=nbits&~7; + nbits&=7; + } + while (nbits > 0) + { + int tb=nbits; + if (tb > 8) tb=8; + putbits(tb,*c++); + nbits-=tb; + } + } + + int getlen() { return m_used; } // in bits + + void *get(int *len) // len is in bytes, forces to byte aligned. + { + if (m_used&7) + { + m_bits.add(&m_curb,1); + m_used=(m_used+7)&~7; + m_curb=0; + } + *len=m_used/8; + return m_bits.get(); + } + + void clear() + { + m_used=0; + m_curb=0; + m_bits.resize(0); + } + +private: + GrowBuf m_bits; + int m_used; // bits + unsigned char m_curb; +}; + +class nsv_InBS { +public: + nsv_InBS() { m_bitpos=0; m_eof=0; } + ~nsv_InBS() { } + + void clear() + { + m_eof=0; + m_bitpos=0; + m_bits.resize(0); + } + + void add(void *data, int len) + { + m_bits.add(data,len); + m_eof=0; + } + + void addbyte(unsigned char byte) + { + add(&byte,1); + } + + void addint(unsigned int dword) + { + addbyte(dword&0xff); + addbyte((dword>>8)&0xff); + addbyte((dword>>16)&0xff); + addbyte((dword>>24)&0xff); + } + + void compact() + { + size_t bytepos=m_bitpos/8; + if (bytepos) + { + unsigned char *t=(unsigned char *)m_bits.get(); + size_t l=m_bits.getlen()-bytepos; + memcpy(t,t+bytepos,l); + m_bits.resize(l); + m_bitpos&=7; + } + m_eof=0; + } + + void seek(ptrdiff_t nbits) + { + if (nbits < 0 && ((size_t)(-nbits)) > m_bitpos) + m_bitpos=0; + else + m_bitpos+=nbits; + m_eof=m_bits.getlen()*8 < m_bitpos; + } + + void rewind() { m_bitpos=0; m_eof=0; } + int eof() { return m_eof; } + size_t avail() { if (m_eof) return 0; return m_bits.getlen()*8 - m_bitpos; } + + unsigned int getbits(size_t nbits) + { + unsigned int ret=0; + if (!nbits) return ret; + unsigned char *t=(unsigned char *)m_bits.get(); + + if (!t || m_bits.getlen()*8 < m_bitpos+nbits) m_eof=1; + else + { + t+=m_bitpos/8; + for (size_t sh = 0; sh != nbits; sh ++) + { + ret|=((*t>>(m_bitpos&7))&1) << sh; + if (!((++m_bitpos)&7)) t++; + } + } + return ret; + } + + int getdata(size_t nbits, void *data) + { + unsigned char *t=(unsigned char *)data; + if (m_bits.getlen()*8 < m_bitpos+nbits) return 1; + if (!(m_bitpos&7) && nbits >= 8) + { + char *bitptr=(char*)m_bits.get(); + bitptr+=(m_bitpos/8); + memcpy(t,bitptr,nbits/8); + m_bitpos+=nbits&~7; + + t+=nbits/8; + nbits&=7; + } + while (nbits > 0) + { + size_t nb=nbits; + if (nb > 8) nb=8; + *t++=getbits(nb); + nbits-=nb; + } + return 0; + } + + void *getcurbyteptr() + { + char *t=(char*)m_bits.get(); + return (void *)(t+(m_bitpos/8)); + } + +private: + GrowBuf m_bits; + size_t m_bitpos; + int m_eof; +}; + +#endif//_NSVBS_H_
\ No newline at end of file |