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);
}

誰かが私が間違ったことを確認または指摘できますか?

編集:

DanielFischerによる修正を反映するようにJavaコードを更新しました

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 )

正しくありません。これは、最上位4ビットすべてが設定されている場合にのみスローされます。それらの一部のみが設定されている場合、エンコーディングはそれらを破棄するだけです。状態は次のようになります

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

これらのビットのいずれかが設定されているかどうかを確認します。

しかし、本当にその例外が必要ですか?Cコードには、その制限の理由はありません(ただし、負intのsを許可しない理由があります。これは、負の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) & 0x7F) | 0x80);

書くこともできます

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

キャストしbyteて他のすべてのビットを破棄するためです。

offset < array.length(これはアルゴリズムの一部ではないため、チェックを省略しました。安全のために追加する必要があります。)

于 2013-01-04T03:51:40.450 に答える