位 reader 在连续非 8 的倍数读取时失败
Bit reader fails on consecutive non-multiple of 8 reads
过去两天我一直在为此苦苦挣扎,此时我可能已经修复了至少 20 个不同的错误。
基本上这个错误是如果你调用 ReadBits() 并请求任何不是 8 的倍数的东西,它第一次会工作,但如果你再次调用它,另一个非 8 的倍数,它会赢't.
我第一次使用 61 位,第二次使用 33 位。
这是请求 61 位的输出:0x1FFFFFFFFFFFFFFFF
从 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;
};
试试这个:
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;
}
过去两天我一直在为此苦苦挣扎,此时我可能已经修复了至少 20 个不同的错误。
基本上这个错误是如果你调用 ReadBits() 并请求任何不是 8 的倍数的东西,它第一次会工作,但如果你再次调用它,另一个非 8 的倍数,它会赢't.
我第一次使用 61 位,第二次使用 33 位。
这是请求 61 位的输出:0x1FFFFFFFFFFFFFFFF 从 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;
};
试试这个:
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;
}