过去两天我一直在努力解决这个问题,而且我现在可能至少修复了20个不同的错误。
基本上,如果您调用ReadBits()并请求任何不是8的倍数的任何内容,那么它将首次运行,但如果您再次调用它,则使用另一个非倍数8,它赢了。
我第一次使用61位,第二次使用33位。
这里是请求61位的输出:0x1FFFFFFFFFFFFFFF 从33:0x1FFFFFFF8
33位输出中的最后一个字节应该是FF,但出于某种原因它是F8吗?如果我将它移到3个空位上,它只会是30位长,而不是像应该的那样33位。
struct BitIO {
FILE *InputFP;
fpos_t *InputOffset;
uint64_t InputFPSize;
uint8_t InputBuffer[BufferSizeInBytes];
uint64_t InputBitIndex;
} BitIO;
static const uint8_t ByteMask[2][8] = {
{0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01},
{0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE}
};
static const uint8_t ShiftTable[8] = {
0, 7, 6, 5, 4, 3, 2, 1
};
uint64_t Bits2Bytes(uint64_t Bits) {
return (Bits + 7) >> 3;
};
uint64_t ReadBits(int8_t Bits2Read) {
uint64_t OutputData = 0;
uint64_t StartByte = Bits2Bytes(BitIO.InputBitIndex - (BitIO.InputBitIndex % 8));
uint64_t EndByte = Bits2Bytes((BitIO.InputBitIndex + Bits2Read));
uint64_t BufferShift = ShiftTable[BitIO.InputBitIndex % 8];
uint64_t Bits2ReadShift = ShiftTable[Bits2Read % 8];
uint64_t ByteMaskStart = ByteMask[0][~(BitIO.InputBitIndex % 8)];
for (uint64_t Byte = StartByte; Byte < EndByte; Byte++) {
if (EndByte == StartByte + 1) {
OutputData += BitIO.InputBuffer[Byte] & ByteMask[1][(BitIO.InputBitIndex + Bits2Read) % 8];
OutputData >>= ShiftTable[(BitIO.InputBitIndex + Bits2Read) % 8];
} else if (Byte == StartByte) {
OutputData += BitIO.InputBuffer[Byte] & ByteMask[1][Bits2Read % 8];
OutputData >>= Bits2ReadShift;
OutputData <<= 8;
} else if (Byte == EndByte - 1) {
OutputData += BitIO.InputBuffer[Byte] & ByteMask[1][(BitIO.InputBitIndex % 8)];
} else if (Byte != StartByte && Byte != EndByte) {
OutputData += BitIO.InputBuffer[Byte];
OutputData <<= 8;
}
}
BitIO.InputBitIndex += Bits2Read;
return OutputData;
};
答案 0 :(得分:1)
试试这个:
static const uint8_t ByteMask[2][8] = {
{0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01},
{0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE}
};
第一个条目错了,但以下内容不使用它。
// assume 0 <= n <= 64
uint64_t ReadBits (int n)
{
uint64_t r = 0;
uint64_t byte = BitIO.InputBitIndex / 8;
uint64_t bit = BitIO.InputBitIndex % 8;
while (n > 0) {
int count = (n >= 8) ? 8 : n;
n -= count;
uint64_t tmp;
// We make sure not to look at two bytes if we don't have to
// to avoid a buffer overrun.
if (bit == 0) {
tmp = BitIO.InputBuffer[byte];
}
else {
uint64_t x = BitIO.InputBuffer[byte] & ByteMask[0][bit];
uint64_t y = BitIO.InputBuffer[byte + 1] & ByteMask[1][bit];
tmp = ((x << 8) | y) >> (8 - bit);
}
tmp >>= (8 - count);
BitIO.InputBitIndex += count;
byte++;
r = (r << count) | tmp;
}
return r;
}