Class helping with assembling data from chunks of byte unaligned bit arrays.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31629 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "BitBuffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BitReader
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BitBuffer
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// handle special case first: no more bits than missing
|
||||||
|
size_t oldSize = fBytes.Size();
|
||||||
|
if (fMissingBits > 0 && bitSize <= fMissingBits) {
|
||||||
|
fMissingBits -= bitSize;
|
||||||
|
uint8 bits = reader.ReadBits(bitSize) << fMissingBits;
|
||||||
|
fBytes[oldSize - 1] |= bits;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// resize the buffer
|
||||||
|
if (!fBytes.AddUninitialized((reader.bitSize - fMissingBits + 7) / 8))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// fill in missing bits
|
||||||
|
if (fMissingBits > 0) {
|
||||||
|
fBytes[oldSize - 1] |= reader.ReadBits(fMissingBits);
|
||||||
|
fMissingBits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read full bytes as long as we can
|
||||||
|
uint8* buffer = fBytes.Elements() + oldSize;
|
||||||
|
while (reader.bitSize >= 8) {
|
||||||
|
*buffer = reader.ReadByte();
|
||||||
|
buffer++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have left-over bits, write a partial byte.
|
||||||
|
if (reader.bitSize > 0) {
|
||||||
|
fMissingBits = 8 - reader.bitSize;
|
||||||
|
*buffer = reader.ReadBits(reader.bitSize) << fMissingBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef BIT_BUFFER_H
|
||||||
|
#define BIT_BUFFER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "Array.h"
|
||||||
|
|
||||||
|
|
||||||
|
class BitBuffer {
|
||||||
|
public:
|
||||||
|
BitBuffer();
|
||||||
|
~BitBuffer();
|
||||||
|
|
||||||
|
bool AddBytes(const void* data, size_t size);
|
||||||
|
bool AddBits(const void* data, uint64 bitSize,
|
||||||
|
uint32 bitOffset = 0);
|
||||||
|
|
||||||
|
uint8* Bytes() const { return fBytes.Elements(); }
|
||||||
|
size_t Size() const { return fBytes.Size(); }
|
||||||
|
size_t BitSize() const
|
||||||
|
{ return Size() * 8 - fMissingBits; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct BitReader;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Array<uint8> fBytes;
|
||||||
|
uint8 fMissingBits;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BIT_BUFFER_H
|
||||||
Reference in New Issue
Block a user