1

我尝试解决Android的各种限制,但我很困惑如何解释以下代码

static bool read_mbf(SkStream* stream, int* value)
{
    int n = 0;
    uint8_t data;
    do {
        if (!read_byte(stream, &data)) {
            return false;
        }
        n = (n << 7) | (data & 0x7F); // Appends lower 7 bits
    } while (data & 0x80); // Handles upper bit as flag!?

    *value = n;
    return true;
}

在我看来,高位是数据继续的标志。当它丢失时,读取 int 停止。这个对吗?

要在 Java 中正确编码(另见 Daniel 的回答):

private void encode( byte[] array, int offset, int value ) {
    if( (value & 0xF0000000) != 0 )
        throw new InvalidParameterException("Value " + value + "is too big to be encoded (max: " + 0x0FFFFFFF + ")");

    // | 0x80 makes sure, upper most bit is set so next byte is processed
    // & 0x7F makes sure, upper most bit is NOT set to end processing
    array[offset + 0] = (byte)((value >> 21) | 0x80);
    array[offset + 1] = (byte)((value >> 14) | 0x80);
    array[offset + 2] = (byte)((value >>  7) | 0x80);
    array[offset + 3] = (byte)((value >>  0) & 0x7F);
}

有人可以确认或指出我做错了什么吗?

编辑:

更新了 Java 代码以反映 Daniel Fischer 的更正

4

1 回答 1

1

您的实现几乎是正确的,但是由于太累了,您将错误的值转移到错误的方向:

array[offset + 0] = (byte)((value & (0x7F << 21)) | 0x80);

因此,您从 中屏蔽除位置 21 到 27 之外的所有位value,然后按位或使用0x80. 然后将结果转换为byte,这意味着丢弃除最低有效 8 位之外的所有位。那离开

array[offset + 0] = (byte)0x80;

你要

array[offset + 0] = (byte)(((value >> 21) & 0x7F) | 0x80);

等等

而你的例外条件,

if( (value & 0xF0000000) == 0xF0000000 )

不正确。仅当设置了所有四个最高有效位时才会抛出。如果只设置了其中一些,您的编码只会丢弃它们。条件可能是

if( (value & 0xF0000000) != 0 )

检查是否设置了这些位中的任何一个。

但是你真的想要那个例外吗?C 代码中没有理由限制这种限制(但是,有理由禁止负ints,因为这会导致溢出,从而导致上次左移时出现未定义的行为)。

如果你想用编码允许的最小字节数对任何非负数int进行编码,代码会变得有点复杂,因为使用的字节数会随着编码值的大小而变化。

private int encode( byte[] array, int offset, int value ) {
    if (value < 0)
        throw new InvalidParameterException("Value " + value + " is negative and cannot safely be decoded.");
    byte temp;
    int shift = 28;
    // find highest set septet
    while(shift > 0 && (value >> shift) == 0) {
        shift -= 7;
    }
    // encode parts that have a successor
    while(shift > 0) {
        array[offset++] = (byte)(((value >> shift) & 0x7F) | 0x80);
        shift -= 7;
    }
    // last septet
    array[offset++] = (byte)(value & 0x7F);
    // return offset for next value
    return offset;
}

线

array[offset++] = (byte)(((value >> shift) & 0x7F) | 0x80);

也可以写成

array[offset++] = (byte)((value >> shift) | 0x80);

因为强制转换为byte丢弃所有其他位。

(我省略了对 的检查offset < array.length,因为这不是算法的一部分,为了安全起见应该添加它们。)

于 2013-01-04T03:51:40.450 回答