diff --git a/src/apps/debugger/util/BitBuffer.cpp b/src/apps/debugger/util/BitBuffer.cpp new file mode 100644 index 0000000000..15c8d1d699 --- /dev/null +++ b/src/apps/debugger/util/BitBuffer.cpp @@ -0,0 +1,140 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * 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; +} diff --git a/src/apps/debugger/util/BitBuffer.h b/src/apps/debugger/util/BitBuffer.h new file mode 100644 index 0000000000..59e9455df5 --- /dev/null +++ b/src/apps/debugger/util/BitBuffer.h @@ -0,0 +1,38 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef BIT_BUFFER_H +#define BIT_BUFFER_H + + +#include + + +#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 fBytes; + uint8 fMissingBits; +}; + + +#endif // BIT_BUFFER_H