位读取器连续非多次读取8次失败

时间:2015-12-11 22:34:23

标签: c bit-manipulation

过去两天我一直在努力解决这个问题,而且我现在可能至少修复了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;
};

1 个答案:

答案 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;
}