You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
836 lines
15 KiB
C++
836 lines
15 KiB
C++
#include <iomanip>
|
|
#include <iostream>
|
|
#include <map>
|
|
|
|
#include "defines.h"
|
|
#include "cexception.h"
|
|
#include "cfilebuffer.h"
|
|
|
|
cFileBuffer::cFileBuffer(const unsigned int n)
|
|
{
|
|
m_buffer = new uint8_t[n];
|
|
memset(m_buffer, 0, n);
|
|
m_current = m_buffer;
|
|
m_size = n;
|
|
m_nextbit = 0;
|
|
}
|
|
|
|
cFileBuffer::~cFileBuffer()
|
|
{
|
|
if(m_buffer)
|
|
delete[] m_buffer;
|
|
}
|
|
|
|
void cFileBuffer::copyFrom(cFileBuffer* buf, const unsigned int n)
|
|
{
|
|
if(m_buffer && n && (m_current + n <= m_buffer + m_size))
|
|
{
|
|
buf->getData(m_current, n);
|
|
m_current += n;
|
|
}
|
|
}
|
|
|
|
void cFileBuffer::copyTo(cFileBuffer *buf, const unsigned int n)
|
|
{
|
|
if(m_buffer && n && (m_current + n <= m_buffer + m_size))
|
|
{
|
|
buf->putData(m_current, n);
|
|
m_current += n;
|
|
}
|
|
}
|
|
|
|
void cFileBuffer::fill(cFileBuffer *buf)
|
|
{
|
|
if(m_buffer)
|
|
{
|
|
m_current = m_buffer;
|
|
buf->getData(m_buffer, MIN(m_size, buf->getSize()));
|
|
}
|
|
}
|
|
|
|
void cFileBuffer::load(std::ifstream &ifs)
|
|
{
|
|
if(ifs.is_open())
|
|
{
|
|
m_current = m_buffer;
|
|
ifs.read((char *)m_buffer, m_size);
|
|
if(ifs.fail())
|
|
throw cIOError(__FILE__, __LINE__);
|
|
}
|
|
else
|
|
throw cOpenError(__FILE__, __LINE__);
|
|
}
|
|
|
|
void cFileBuffer::save(std::ofstream &ofs)
|
|
{
|
|
if(ofs.is_open())
|
|
{
|
|
m_current = m_buffer;
|
|
ofs.write((char *)m_buffer, m_size);
|
|
if(ofs.fail())
|
|
throw cIOError(__FILE__, __LINE__);
|
|
}
|
|
else
|
|
throw cOpenError(__FILE__, __LINE__);
|
|
}
|
|
|
|
void cFileBuffer::save(std::ofstream &ofs, const unsigned int n)
|
|
{
|
|
if (ofs.is_open())
|
|
{
|
|
if(n <= m_size)
|
|
{
|
|
m_current = m_buffer;
|
|
ofs.write((char *)m_buffer, n);
|
|
if(ofs.fail())
|
|
throw cIOError(__FILE__, __LINE__);
|
|
}
|
|
else
|
|
throw cBufferEmpty(__FILE__, __LINE__);
|
|
}
|
|
else
|
|
throw cOpenError(__FILE__, __LINE__);
|
|
}
|
|
|
|
void cFileBuffer::dump(const unsigned int n)
|
|
{
|
|
uint8_t* tmp = m_current;
|
|
unsigned int count = 0;
|
|
|
|
std::cout << std::setbase(16) << std::setfill('0') << std::setw(8) << count << ": ";
|
|
while((tmp < (m_buffer + m_size)) && ((tmp < (m_current + n)) || (n == 0)))
|
|
{
|
|
std::cout << std::setw(2) << (unsigned int)*tmp++ << " ";
|
|
if((++count & 0x1f) == 0)
|
|
std::cout << std::endl << std::setw(8) << count << ": ";
|
|
else if ((count & 0x07) == 0)
|
|
std::cout << "| ";
|
|
}
|
|
std::cout << std::setbase(10) << std::setfill(' ') << std::endl;
|
|
}
|
|
|
|
void cFileBuffer::seek(const unsigned int n)
|
|
{
|
|
if((m_current) && (n <= m_size))
|
|
m_current = m_buffer + n;
|
|
}
|
|
|
|
void cFileBuffer::skip(const int n)
|
|
{
|
|
if((m_current) && (m_current + n <= m_buffer + m_size))
|
|
m_current += n;
|
|
}
|
|
|
|
void cFileBuffer::skipBits()
|
|
{
|
|
if(m_nextbit)
|
|
{
|
|
skip(1);
|
|
m_nextbit = 0;
|
|
}
|
|
}
|
|
|
|
typedef union _HashTableEntry
|
|
{
|
|
uint32_t code;
|
|
struct
|
|
{
|
|
uint16_t prefix;
|
|
uint8_t append;
|
|
}
|
|
entry;
|
|
} HashTableEntry;
|
|
|
|
unsigned int cFileBuffer::compressLZW(cFileBuffer *result)
|
|
{
|
|
try
|
|
{
|
|
std::map<uint32_t, uint16_t> hashtable;
|
|
unsigned int n_bits = 9;
|
|
unsigned int free_entry = 257;
|
|
unsigned int bitpos = 0;
|
|
HashTableEntry hte;
|
|
|
|
hte.entry.prefix = getUint8();
|
|
|
|
while(!atEnd() && !result->atEnd())
|
|
{
|
|
hte.entry.append = getUint8();
|
|
std::map<uint32_t, uint16_t>::iterator it = hashtable.find(hte.code);
|
|
if(it == hashtable.end())
|
|
{
|
|
result->putBits(hte.entry.prefix, n_bits);
|
|
bitpos += n_bits;
|
|
hashtable.insert(std::pair<uint32_t, uint16_t>(hte.code, free_entry));
|
|
hte.entry.prefix = hte.entry.append;
|
|
free_entry++;
|
|
if(free_entry >= (unsigned int)(1 << n_bits))
|
|
{
|
|
if(n_bits < 12)
|
|
n_bits++;
|
|
else
|
|
{
|
|
hashtable.clear();
|
|
free_entry = 256;
|
|
result->putBits(free_entry, n_bits);
|
|
result->skipBits();
|
|
result->skip((((bitpos-1)+((n_bits<<3)-(bitpos-1+(n_bits<<3))%(n_bits<<3)))-bitpos)>>3);
|
|
n_bits = 9;
|
|
bitpos = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
hte.entry.prefix = it->second;
|
|
}
|
|
hashtable.clear();
|
|
unsigned int res = result->getBytesDone();
|
|
result->rewind();
|
|
return res;
|
|
}
|
|
catch (cException &e)
|
|
{
|
|
e.print("FileBuffer::CompressLZW");
|
|
throw;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
unsigned int cFileBuffer::compressLZSS(cFileBuffer *result)
|
|
{
|
|
try
|
|
{
|
|
uint8_t* data = getCurrent();
|
|
uint8_t* curr = getCurrent();
|
|
uint8_t* codeptr = result->getCurrent();
|
|
uint8_t byte = getUint8();
|
|
uint8_t code = 0;
|
|
uint8_t mask = 0;
|
|
|
|
while(!atEnd() && !result->atEnd())
|
|
{
|
|
if(!mask)
|
|
{
|
|
*codeptr = code;
|
|
codeptr = result->getCurrent();
|
|
result->skip(1);
|
|
code = 0;
|
|
mask = 0x01;
|
|
}
|
|
unsigned int off = 0;
|
|
unsigned int len = 0;
|
|
uint8_t* ptr = curr;
|
|
|
|
while(ptr > data)
|
|
{
|
|
ptr--;
|
|
if(*ptr == byte)
|
|
{
|
|
off = ptr - data;
|
|
len = 1;
|
|
while((curr + len < m_buffer + m_size) && (ptr[len] == curr[len]))
|
|
len++;
|
|
}
|
|
}
|
|
if(len < 5)
|
|
{
|
|
code |= mask;
|
|
result->putUint8(byte);
|
|
}
|
|
else
|
|
{
|
|
result->putUint16LE(off);
|
|
result->putUint8(len - 5);
|
|
skip(len - 1);
|
|
}
|
|
curr = getCurrent();
|
|
byte = getUint8();
|
|
mask <<= 1;
|
|
}
|
|
*codeptr = code;
|
|
unsigned int res = result->getBytesDone();
|
|
result->rewind();
|
|
return res;
|
|
}
|
|
catch (cException &e)
|
|
{
|
|
e.print("FileBuffer::CompressLZSS");
|
|
throw;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
unsigned int cFileBuffer::compressRLE(cFileBuffer *result)
|
|
{
|
|
try
|
|
{
|
|
uint8_t* skipptr = getCurrent();
|
|
uint8_t byte = 0;
|
|
uint8_t next = getUint8();
|
|
unsigned int count;
|
|
unsigned int skipped = 0;
|
|
|
|
while(!atEnd() && !result->atEnd())
|
|
{
|
|
count = 1;
|
|
do
|
|
{
|
|
byte = next;
|
|
next = getUint8();
|
|
count++;
|
|
}
|
|
while(!atEnd() && (next == byte));
|
|
|
|
if(next != byte)
|
|
count--;
|
|
|
|
if(count > 3)
|
|
{
|
|
if(skipped > 0)
|
|
{
|
|
while(skipped > 0)
|
|
{
|
|
unsigned int n;
|
|
if(skipped > 127)
|
|
n = 127;
|
|
else
|
|
n = skipped & 0x7f;
|
|
|
|
result->putUint8(n);
|
|
result->putData(skipptr, n);
|
|
skipped -= n;
|
|
skipptr += n;
|
|
}
|
|
}
|
|
while(count > 3)
|
|
{
|
|
unsigned int n;
|
|
if(count > 127)
|
|
n = 127;
|
|
else
|
|
n = count & 0x7f;
|
|
result->putUint8(n | 0x80);
|
|
result->putUint8(byte);
|
|
count -= n;
|
|
}
|
|
skipped = count;
|
|
skipptr = getCurrent() - skipped - 1;
|
|
}
|
|
else
|
|
skipped += count;
|
|
}
|
|
|
|
if(next != byte)
|
|
skipped++;
|
|
|
|
if(skipped > 0)
|
|
{
|
|
skip(-skipped);
|
|
while(skipped > 0)
|
|
{
|
|
unsigned int n = skipped & 0x7f;
|
|
result->putUint8(n);
|
|
result->copyFrom(this, n);
|
|
skipped -= n;
|
|
}
|
|
}
|
|
|
|
unsigned int res = result->getBytesDone();
|
|
result->rewind();
|
|
return res;
|
|
}
|
|
catch (cException &e)
|
|
{
|
|
e.print("FileBuffer::CompressRLE");
|
|
throw;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
unsigned int cFileBuffer::compress(cFileBuffer *result, const unsigned int method)
|
|
{
|
|
switch (method)
|
|
{
|
|
case COMPRESSION_LZW:
|
|
return(compressLZW(result));
|
|
break;
|
|
case COMPRESSION_LZSS:
|
|
return(compressLZSS(result));
|
|
break;
|
|
case COMPRESSION_RLE:
|
|
return(compressRLE(result));
|
|
break;
|
|
default:
|
|
throw cCompressionError(__FILE__, __LINE__);
|
|
break;
|
|
}
|
|
}
|
|
|
|
typedef struct _CodeTableEntry
|
|
{
|
|
uint16_t prefix;
|
|
uint8_t append;
|
|
} CodeTableEntry;
|
|
|
|
unsigned int cFileBuffer::decompressLZW(cFileBuffer *result)
|
|
{
|
|
try
|
|
{
|
|
CodeTableEntry* codetable = new CodeTableEntry[4096];
|
|
uint8_t* decodestack = new uint8_t[4096];
|
|
uint8_t* stackptr = decodestack;
|
|
unsigned int n_bits = 9;
|
|
unsigned int free_entry = 257;
|
|
unsigned int oldcode = getBits(n_bits);
|
|
unsigned int lastbyte = oldcode;
|
|
unsigned int bitpos = 0;
|
|
|
|
result->putUint8(oldcode);
|
|
|
|
while (!atEnd() && !result->atEnd())
|
|
{
|
|
unsigned int newcode = getBits(n_bits);
|
|
bitpos += n_bits;
|
|
|
|
if(newcode == 256)
|
|
{
|
|
skipBits();
|
|
skip((((bitpos-1)+((n_bits<<3)-(bitpos-1+(n_bits<<3))%(n_bits<<3)))-bitpos)>>3);
|
|
n_bits = 9;
|
|
free_entry = 256;
|
|
bitpos = 0;
|
|
}
|
|
else
|
|
{
|
|
unsigned int code = newcode;
|
|
if(code >= free_entry)
|
|
{
|
|
*stackptr++ = lastbyte;
|
|
code = oldcode;
|
|
}
|
|
|
|
while(code >= 256)
|
|
{
|
|
*stackptr++ = codetable[code].append;
|
|
code = codetable[code].prefix;
|
|
}
|
|
|
|
*stackptr++ = code;
|
|
lastbyte = code;
|
|
|
|
while(stackptr > decodestack)
|
|
result->putUint8(*--stackptr);
|
|
|
|
if(free_entry < 4096)
|
|
{
|
|
codetable[free_entry].prefix = oldcode;
|
|
codetable[free_entry].append = lastbyte;
|
|
free_entry++;
|
|
|
|
if((free_entry >= (unsigned int)(1 << n_bits)) && (n_bits < 12))
|
|
{
|
|
n_bits++;
|
|
bitpos = 0;
|
|
}
|
|
}
|
|
oldcode = newcode;
|
|
}
|
|
}
|
|
delete[] decodestack;
|
|
delete[] codetable;
|
|
unsigned int res = result->getBytesDone();
|
|
result->rewind();
|
|
return res;
|
|
}
|
|
catch (cException &e)
|
|
{
|
|
e.print("FileBuffer::DecompressLZW");
|
|
throw;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
unsigned int cFileBuffer::decompressLZSS(cFileBuffer *result)
|
|
{
|
|
try
|
|
{
|
|
uint8_t* data = result->getCurrent();
|
|
uint8_t code = 0;
|
|
uint8_t mask = 0;
|
|
|
|
while(!atEnd() && !result->atEnd())
|
|
{
|
|
if(!mask)
|
|
{
|
|
code = getUint8();
|
|
mask = 0x01;
|
|
}
|
|
|
|
if(code & mask)
|
|
result->putUint8(getUint8());
|
|
else
|
|
{
|
|
unsigned int off = getUint16LE();
|
|
unsigned int len = getUint8() + 5;
|
|
result->putData(data + off, len);
|
|
}
|
|
mask <<= 1;
|
|
}
|
|
|
|
unsigned int res = result->getBytesDone();
|
|
result->rewind();
|
|
return res;
|
|
}
|
|
catch (cException &e)
|
|
{
|
|
e.print("FileBuffer::DecompressLZSS");
|
|
throw;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
unsigned int cFileBuffer::decompressRLE(cFileBuffer *result)
|
|
{
|
|
try
|
|
{
|
|
while(!atEnd() && !result->atEnd())
|
|
{
|
|
uint8_t control = getUint8();
|
|
|
|
if(control & 0x80)
|
|
result->putData(getUint8(), control & 0x7f);
|
|
else
|
|
result->copyFrom(this, control);
|
|
}
|
|
|
|
unsigned int res = result->getBytesDone();
|
|
result->rewind();
|
|
return res;
|
|
}
|
|
catch (cException &e)
|
|
{
|
|
e.print("FileBuffer::DecompressRLE");
|
|
throw;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
unsigned int cFileBuffer::decompress(cFileBuffer *result, const unsigned int method)
|
|
{
|
|
switch(method)
|
|
{
|
|
case COMPRESSION_LZW:
|
|
if((getUint8() != 0x02) || (getUint32LE() != result->getSize()))
|
|
throw cDataCorruption(__FILE__, __LINE__);
|
|
|
|
return(decompressLZW(result));
|
|
break;
|
|
case COMPRESSION_LZSS:
|
|
return(decompressLZSS(result));
|
|
break;
|
|
case COMPRESSION_RLE:
|
|
return(decompressRLE(result));
|
|
break;
|
|
default:
|
|
throw cCompressionError(__FILE__, __LINE__);
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool cFileBuffer::atEnd() const
|
|
{
|
|
return(m_current >= m_buffer + m_size);
|
|
}
|
|
|
|
unsigned int cFileBuffer::getSize() const
|
|
{
|
|
return(m_size);
|
|
}
|
|
|
|
unsigned int cFileBuffer::getBytesDone() const
|
|
{
|
|
return(m_current - m_buffer);
|
|
}
|
|
|
|
unsigned int cFileBuffer::getBytesLeft() const
|
|
{
|
|
return(m_buffer + m_size - m_current);
|
|
}
|
|
|
|
uint8_t* cFileBuffer::getCurrent() const
|
|
{
|
|
return(m_current);
|
|
}
|
|
|
|
unsigned int cFileBuffer::getNextBit() const
|
|
{
|
|
return(m_nextbit);
|
|
}
|
|
|
|
void cFileBuffer::rewind()
|
|
{
|
|
m_current = m_buffer;
|
|
}
|
|
|
|
uint8_t cFileBuffer::getUint8()
|
|
{
|
|
uint8_t n;
|
|
getData(&n, 1);
|
|
return(n);
|
|
}
|
|
|
|
uint16_t cFileBuffer::getUint16LE()
|
|
{
|
|
uint16_t n;
|
|
getData(&n, 2);
|
|
return(SDL_SwapLE16(n));
|
|
}
|
|
|
|
uint16_t cFileBuffer::getUint16BE()
|
|
{
|
|
uint16_t n;
|
|
getData(&n, 2);
|
|
return(SDL_SwapBE16(n));
|
|
}
|
|
|
|
uint32_t cFileBuffer::getUint32LE()
|
|
{
|
|
uint32_t n;
|
|
getData(&n, 4);
|
|
return(SDL_SwapLE32(n));
|
|
}
|
|
|
|
uint32_t cFileBuffer::getUint32BE()
|
|
{
|
|
uint32_t n;
|
|
getData(&n, 4);
|
|
return(SDL_SwapBE32(n));
|
|
}
|
|
|
|
int8_t cFileBuffer::getSint8()
|
|
{
|
|
int8_t n;
|
|
getData(&n, 1);
|
|
return(n);
|
|
}
|
|
|
|
int16_t cFileBuffer::getSint16LE()
|
|
{
|
|
int16_t n;
|
|
getData(&n, 2);
|
|
return(SDL_SwapLE16(n));
|
|
}
|
|
|
|
int16_t cFileBuffer::getSint16BE()
|
|
{
|
|
int16_t n;
|
|
getData(&n, 2);
|
|
return(SDL_SwapBE16(n));
|
|
}
|
|
|
|
int32_t cFileBuffer::getSint32LE()
|
|
{
|
|
int32_t n;
|
|
getData(&n, 4);
|
|
return(SDL_SwapLE32(n));
|
|
}
|
|
|
|
int32_t cFileBuffer::getSint32BE()
|
|
{
|
|
int32_t n;
|
|
getData(&n, 4);
|
|
return(SDL_SwapBE32(n));
|
|
}
|
|
|
|
std::string cFileBuffer::getString()
|
|
{
|
|
if(m_current)
|
|
{
|
|
std::string s((char *)m_current);
|
|
if((m_current + s.length() + 1) <= (m_buffer + m_size))
|
|
{
|
|
m_current += s.length() + 1;
|
|
return(s);
|
|
}
|
|
else
|
|
throw cBufferEmpty(__FILE__, __LINE__);
|
|
}
|
|
return "";
|
|
}
|
|
|
|
std::string cFileBuffer::getString(const unsigned int len)
|
|
{
|
|
if((m_current) && (m_current + len <= m_buffer + m_size))
|
|
{
|
|
std::string s((char *)m_current);
|
|
m_current += len;
|
|
return(s);
|
|
}
|
|
else
|
|
throw cBufferEmpty(__FILE__, __LINE__);
|
|
return "";
|
|
}
|
|
|
|
void cFileBuffer::getData(void *data, const unsigned int n)
|
|
{
|
|
if(m_current + n <= m_buffer + m_size)
|
|
{
|
|
memcpy(data, m_current, n);
|
|
m_current += n;
|
|
}
|
|
else
|
|
throw cBufferEmpty(__FILE__, __LINE__);
|
|
}
|
|
|
|
unsigned int cFileBuffer::getBits(const unsigned int n)
|
|
{
|
|
if(m_current + ((m_nextbit + n + 7)/8) <= m_buffer + m_size)
|
|
{
|
|
unsigned int x = 0;
|
|
|
|
for(unsigned int i = 0; i < n; i++)
|
|
{
|
|
if(*m_current & (1 << m_nextbit))
|
|
x += (1 << i);
|
|
|
|
m_nextbit++;
|
|
if(m_nextbit > 7)
|
|
{
|
|
m_current++;
|
|
m_nextbit = 0;
|
|
}
|
|
}
|
|
return(x);
|
|
}
|
|
else
|
|
throw cBufferEmpty(__FILE__, __LINE__);
|
|
}
|
|
|
|
void cFileBuffer::putUint8(const uint8_t x)
|
|
{
|
|
uint8_t xx = x;
|
|
putData(&xx, 1);
|
|
}
|
|
|
|
void cFileBuffer::putUint16LE(const uint16_t x)
|
|
{
|
|
uint16_t xx = SDL_SwapLE16(x);
|
|
putData(&xx, 2);
|
|
}
|
|
|
|
void cFileBuffer::putUint16BE(const uint16_t x)
|
|
{
|
|
uint16_t xx = SDL_SwapBE16(x);
|
|
putData(&xx, 2);
|
|
}
|
|
|
|
void cFileBuffer::putUint32LE(const uint32_t x)
|
|
{
|
|
uint32_t xx = SDL_SwapLE32(x);
|
|
putData(&xx, 4);
|
|
}
|
|
|
|
void cFileBuffer::putUint32BE(const uint32_t x)
|
|
{
|
|
uint32_t xx = SDL_SwapBE32(x);
|
|
putData(&xx, 4);
|
|
}
|
|
|
|
void cFileBuffer::putSint8(const int8_t x)
|
|
{
|
|
int8_t xx = x;
|
|
putData(&xx, 1);
|
|
}
|
|
|
|
void cFileBuffer::putSint16LE(const int16_t x)
|
|
{
|
|
int16_t xx = SDL_SwapLE16(x);
|
|
putData(&xx, 2);
|
|
}
|
|
|
|
void cFileBuffer::putSint16BE(const int16_t x)
|
|
{
|
|
int16_t xx = SDL_SwapBE16(x);
|
|
putData(&xx, 2);
|
|
}
|
|
|
|
void cFileBuffer::putSint32LE(const int32_t x)
|
|
{
|
|
int32_t xx = SDL_SwapLE32(x);
|
|
putData(&xx, 4);
|
|
}
|
|
|
|
void cFileBuffer::putSint32BE(const int32_t x)
|
|
{
|
|
int32_t xx = SDL_SwapBE32(x);
|
|
putData(&xx, 4);
|
|
}
|
|
|
|
void cFileBuffer::putString(const std::string s)
|
|
{
|
|
if((m_current) && (m_current + s.length() + 1 <= m_buffer + m_size))
|
|
{
|
|
strncpy((char *)m_current, s.c_str(), s.length() + 1);
|
|
m_current += s.length() + 1;
|
|
}
|
|
else
|
|
throw cBufferFull(__FILE__, __LINE__);
|
|
}
|
|
|
|
void cFileBuffer::putString(const std::string s, const unsigned int len)
|
|
{
|
|
if((m_current) && (m_current + len <= m_buffer + m_size))
|
|
{
|
|
memset(m_current, 0, len);
|
|
strncpy((char *)m_current, s.c_str(), len);
|
|
m_current += len;
|
|
}
|
|
else
|
|
throw cBufferFull(__FILE__, __LINE__);
|
|
}
|
|
|
|
void cFileBuffer::putData(void *data, const unsigned int n)
|
|
{
|
|
if(m_current + n <= m_buffer + m_size)
|
|
{
|
|
memcpy(m_current, data, n);
|
|
m_current += n;
|
|
}
|
|
else
|
|
throw cBufferFull(__FILE__, __LINE__);
|
|
}
|
|
|
|
void cFileBuffer::putData(const uint8_t x, const unsigned int n)
|
|
{
|
|
if(m_current + n <= m_buffer + m_size)
|
|
{
|
|
memset(m_current, x, n);
|
|
m_current += n;
|
|
}
|
|
else
|
|
throw cBufferFull(__FILE__, __LINE__);
|
|
}
|
|
|
|
void cFileBuffer::putBits(const unsigned int x, const unsigned int n)
|
|
{
|
|
if(m_current + ((m_nextbit + n + 7)/8) <= m_buffer + m_size)
|
|
{
|
|
for(unsigned int i = 0; i < n; i++)
|
|
{
|
|
if(x & (1 << i))
|
|
*m_current |= (1 << m_nextbit);
|
|
else
|
|
*m_current &= ~(1 << m_nextbit);
|
|
|
|
m_nextbit++;
|
|
if(m_nextbit > 7)
|
|
{
|
|
m_current++;
|
|
m_nextbit = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
throw cBufferFull(__FILE__, __LINE__);
|
|
}
|