LEB128 または Little Endian Base 128 は 任意精度の整数を少ないバイト数に格納するのに用いられる可変長符号圧縮である。
LEB128はDWARF デバッグファイルフォーマッ[1][2]や WebAssembly のすべての整数リテラルの符号化方式に使用されている[3]。
LEB128形式は可変長数値表現 (VLQ) と非常に似ている。主な違いは LEB128 は リトルエンディアン であるのに対し、可変長数値表現はビッグエンディアンであることであり、どちらも小さな数値を1バイトで格納できる一方で、任意の長さの数値をエンコードすることもできる。LEB128には2つのバージョンがあり、符号無しLEB128と符号付きLEB128である。復号する際は、エンコードされた値が符号無しLEB128か符号付きLEB128かを知っている必要がある。
符号無し整数を Unsigned LEB128 (ULEB128) にするには、まず2進数で表現する。
次に数値を7ビットの倍数になるようにゼロ拡張する(数値が0でない場合、最上位7ビットがすべて0にならないようにする)。数値を7ビットのグループに分割する。各7ビットグループに対して、最下位グループから最上位グループの順に1バイトずつ出力する。各バイトは、そのグループを7つの最下位ビットに持ちます。最後のバイトを除くすべてのバイトの最上位ビットを1に設定する。数値0は通常、単一バイト0x00としてエンコードされふ。WebAssemblyでは、0の代替エンコーディングも許可されている(0x80 0x00、0x80 0x80 0x00、...)。
MSB ------------------ LSB
10011000011101100101 元の値の2進数表現
010011000011101100101 7の倍数ビットに拡張
0100110 0001110 1100101 7ビットごとに分割
00100110 10001110 11100101 最後(最上位)のグループを除くすべてに高位1ビットを追加してバイトを形成
0x26 0x8E 0xE5 16進数表現
→ 0xE5 0x8E 0x26 出力 (最下位ビットから最上位ビットの順)
符号付きの数値も同様に表現される。2の補数 で表現された、7の倍数の ビットから始め、符号なしエンコーディングと同様にグループに分割する。
例えば、符号付き数値-123456は0xC0 0xBB 0x78としてエンコードされる。
MSB ------------------ LSB
11110001001000000 123456 の2進数表現
000011110001001000000 21ビットの
111100001110110111111 すべてのビットを反転 (1の補数)
111100001110111000000 1を足す(2の補数)
1111000 0111011 1000000 7ビットごとに分割
01111000 10111011 11000000 最後(最上位)のグループを除くすべてに高位1ビットを追加してバイトを形成
0x78 0xBB 0xC0 16進数表現
→ 0xC0 0xBB 0x78 出力 (最下位ビットから最上位ビットの順)
do {
byte = low-order 7 bits of value;
value >>= 7;
if (value != 0) /* more bytes to come */
set high-order bit of byte;
emit byte;
} while (value != 0);
more = 1;
negative = (value < 0);
/* the size in bits of the variable value, e.g., 64 if value's type is int64_t */
size = no. of bits in signed integer;
while (more) {
byte = low-order 7 bits of value;
value >>= 7;
/* the following is only necessary if the implementation of >>= uses a
logical shift rather than an arithmetic shift for a signed left operand */
if (negative)
value |= (~0 << (size - 7)); /* sign extend */
/* sign bit of byte is second high-order bit (0x40) */
if ((value == 0 && sign bit of byte is clear) || (value == -1 && sign bit of byte is set))
more = 0;
else
set high-order bit of byte;
emit byte;
}
result = 0;
shift = 0;
while (true) {
byte = next byte in input;
result |= (low-order 7 bits of byte) << shift;
if (high-order bit of byte == 0)
break;
shift += 7;
}
result = 0;
shift = 0;
/* the size in bits of the result variable, e.g., 64 if result's type is int64_t */
size = number of bits in signed integer;
do {
byte = next byte in input;
result |= (low-order 7 bits of byte << shift);
shift += 7;
} while (high-order bit of byte != 0);
/* sign bit of byte is second high-order bit (0x40) */
if ((shift <size) && (sign bit of byte is set))
/* sign extend */
result |= (~0 << shift);
未登録
IPFS未登録
📡 0ピア
N=1
CRITICAL
PQS C48