Java 使用掩蔽读取int的未知方法
我试图绕过Android的各种限制,但我对如何解释以下代码感到困惑Java 使用掩蔽读取int的未知方法,java,android,c,image-processing,Java,Android,C,Image Processing,我试图绕过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 &
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;
}
有人能证实或指出我做错了什么吗
编辑:
更新了Java代码以反映Daniel Fischer的更正您的实现几乎正确,但由于太累,您将错误的值移向了错误的方向:
array[offset + 0] = (byte)((value & (0x7F << 21)) | 0x80);
你想要
array[offset + 0] = (byte)(((value >> 21) & 0x7F) | 0x80);
等等
以及你的例外情况
if( (value & 0xF0000000) == 0xF0000000 )
这是不对的。只有在设置了所有四个最高有效位时才会抛出。如果只设置了其中的一部分,则编码将丢弃它们。情况可能是这样的
if( (value & 0xF0000000) != 0 )
检查是否设置了这些位中的任何一位
但你真的想要那个例外吗?C代码中没有理由存在这种限制(但是,有理由不允许负int
s,因为这会导致溢出,从而导致上次左移时的未定义行为)
如果要使用编码允许的最小字节数对任何非负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) | 0x80);
因为转换到字节
会丢弃所有其他位
(我省略了对
偏移量
的检查,因为这不是算法的一部分,为了安全起见,应该添加它们。)您的实现几乎是正确的,但由于太累,您将错误的值移到了错误的方向:
array[offset + 0] = (byte)((value & (0x7F << 21)) | 0x80);
你想要
array[offset + 0] = (byte)(((value >> 21) & 0x7F) | 0x80);
等等
以及你的例外情况
if( (value & 0xF0000000) == 0xF0000000 )
这是不对的。只有在设置了所有四个最高有效位时才会抛出。如果只设置了其中的一部分,则编码将丢弃它们。情况可能是这样的
if( (value & 0xF0000000) != 0 )
检查是否设置了这些位中的任何一位
但你真的想要那个例外吗?C代码中没有理由存在这种限制(但是,有理由不允许负int
s,因为这会导致溢出,从而导致上次左移时的未定义行为)
如果要使用编码允许的最小字节数对任何非负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) | 0x80);
因为转换到字节
会丢弃所有其他位
(我省略了对
偏移量
的检查,因为这不是算法的一部分,为了安全起见,应该添加它们。)您对C代码的解释听起来很合理。在Java中,你必须小心,因为所有的整数类型都是有符号的,这是行不通的。c函数读取被编码为尽可能少的字节数的整数以节省空间。例如,0到127取一个字节。不管发生什么,您总是输出四个字节。在这种情况下,c函数需要一个字节,当再次调用时,它会将以下内容读入其他数字。@DiegoBasch我真的不明白你在说什么。如果您有10000000
,则七个0
将向左移动,并且根本没有效果。当然,我可以钳制不必要的空字节,但在我看来它应该可以工作。如果将127编码为四个字节,它将只消耗这四个字节中的一个。下次它将读取四个字节中的第二个字节,并认为这是一个新的数字。我认为这会起作用,因为设置了0x80
(continue)位。但也许我太累了。明天我们再来看看。你对C代码的解释听起来很合理。在Java中,你必须小心,因为所有的整数类型都是有符号的,这是行不通的。c函数读取被编码为尽可能少的字节数的整数以节省空间。例如,0到127取一个字节。不管发生什么,您总是输出四个字节。在这种情况下,c函数需要一个字节,当再次调用时,它会将以下内容读入其他数字。@DiegoBasch我真的不明白你在说什么。如果您有10000000
,则七个0
将向左移动,并且根本没有效果。当然,我可以钳制不必要的空字节,但在我看来它应该可以工作。如果将127编码为四个字节,它将只消耗这四个字节中的一个。下次它将读取四个字节中的第二个字节,并认为这是一个新的数字。我认为这会起作用,因为设置了0x80
(continue)位。但也许我太累了。我明天再来看看。太好了。谢谢。把变化纳入我的问题。在我看来,我的天真方法更容易阅读/理解。哦,当然。固定长度编码提供了更简单的代码。但是它可以占用更多的空间,参见UTF-n。谢谢。把变化纳入我的问题。在我看来,我的天真方法更容易阅读/理解。哦,当然。固定长度编码提供了更简单的代码。但它可能会占用更多空间,请参见UTF-n。