我尝试解决 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的更正
答案 0 :(得分:1)
您的实施几乎是正确的,但由于太累了,您将错误的方向转移错误的方向:
array[offset + 0] = (byte)((value & (0x7F << 21)) | 0x80);
因此,除了来自value
的位置21到27中的所有位,然后按位 - 或者用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代码中没有理由说明该限制(但是,有一个理由不允许使用负int
s,因为这会导致溢出,因此在最后一次左移时会导致未定义的行为。) p>
如果要编码具有编码允许的最小字节数的任何非负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
的检查,因为这不是算法的一部分,为了安全起见,应加上它们。)