* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "BitBuffer.h"
struct BitBuffer::BitReader {
const uint8* data;
uint64 bitSize;
uint32 bitOffset;
BitReader(const uint8* data, uint64 bitSize, uint32 bitOffset)
:
data(data),
bitSize(bitSize),
bitOffset(bitOffset)
{
}
uint8 ReadByte()
{
uint8 byte = *data;
data++;
bitSize -= 8;
if (bitOffset == 0)
return byte;
return (byte << bitOffset) | (*data >> (8 - bitOffset));
}
uint8 ReadBits(uint32 count)
{
uint8 byte = *data;
bitSize -= count;
bitOffset += count;
if (bitOffset <= 8) {
if (bitOffset == 8) {
bitOffset = 0;
data++;
return byte & ((1 << count) - 1);
}
return (byte >> (8 - bitOffset)) & ((1 << count) - 1);
}
data++;
bitOffset -= 8;
return ((byte << bitOffset) | (*data >> (8 - bitOffset)))
& ((1 << count) - 1);
}
};
BitBuffer::BitBuffer()
:
fMissingBits(0)
{
}
BitBuffer::~BitBuffer()
{
}
bool
BitBuffer::AddBytes(const void* data, size_t size)
{
if (size == 0)
return true;
if (fMissingBits == 0) {
size_t oldSize = fBytes.Size();
if (!fBytes.AddUninitialized(size))
return false;
memcpy(fBytes.Elements() + oldSize, data, size);
return true;
}
return AddBits(data, (uint64)size * 8, 0);
}
bool
BitBuffer::AddBits(const void* _data, uint64 bitSize, uint32 bitOffset)
{
if (bitSize == 0)
return true;
const uint8* data = (const uint8*)_data + bitOffset / 8;
bitOffset %= 8;
BitReader reader(data, bitSize, bitOffset);
size_t oldSize = fBytes.Size();
if (fMissingBits > 0 && bitSize <= fMissingBits) {
fMissingBits -= bitSize;
uint8 bits = reader.ReadBits(bitSize) << fMissingBits;
fBytes[oldSize - 1] |= bits;
return true;
}
if (!fBytes.AddUninitialized((reader.bitSize - fMissingBits + 7) / 8))
return false;
if (fMissingBits > 0) {
fBytes[oldSize - 1] |= reader.ReadBits(fMissingBits);
fMissingBits = 0;
}
uint8* buffer = fBytes.Elements() + oldSize;
while (reader.bitSize >= 8) {
*buffer = reader.ReadByte();
buffer++;
}
if (reader.bitSize > 0) {
fMissingBits = 8 - reader.bitSize;
*buffer = reader.ReadBits(reader.bitSize) << fMissingBits;
}
return true;
}
bool
BitBuffer::AddZeroBits(uint64 bitSize)
{
if (bitSize == 0)
return true;
size_t oldSize = fBytes.Size();
if (fMissingBits > 0 && bitSize <= fMissingBits) {
fMissingBits -= bitSize;
return true;
}
if (!fBytes.AddUninitialized((bitSize - fMissingBits + 7) / 8))
return false;
if (fMissingBits > 0) {
bitSize -= fMissingBits;
fMissingBits = 0;
}
uint8* buffer = fBytes.Elements() + oldSize;
memset(buffer, 0, (bitSize + 7) / 8);
bitSize %= 8;
if (bitSize > 0)
fMissingBits = 8 - bitSize;
return true;
}