stringtranslate.com

LEB128

LEB128 o Little Endian Base 128 es una compresión de código de longitud variable que se utiliza para almacenar números enteros arbitrariamente grandes en una pequeña cantidad de bytes. LEB128 se utiliza en el formato de archivo de depuración DWARF [1] [2] y la codificación binaria WebAssembly para todos los literales enteros. [3]

Formato de codificación

El formato LEB128 es muy similar al formato de cantidad de longitud variable (VLQ); la principal diferencia es que LEB128 es little-endian mientras que las cantidades de longitud variable son big-endian . Ambos permiten almacenar números pequeños en un solo byte, al tiempo que permiten la codificación de números arbitrariamente largos. Hay dos versiones de LEB128: LEB128 sin firmar y LEB128 firmada. El decodificador debe saber si el valor codificado es LEB128 sin signo o LEB128 con signo.

LEB128 sin firmar

Para codificar un número sin signo utilizando LEB128 sin signo ( ULEB128 ), primero represente el número en binario. Luego , cero extiende el número hasta un múltiplo de 7 bits (de modo que si el número es distinto de cero, los 7 bits más significativos no son todos 0). Divide el número en grupos de 7 bits. Genere un byte codificado para cada grupo de 7 bits, desde el grupo menos significativo hasta el más significativo. Cada byte tendrá el grupo en sus 7 bits menos significativos. Establezca el bit más significativo en cada byte excepto el último byte. El número cero está codificado como un solo byte 0x00.

Como ejemplo, así es como se codifica el número sin firmar 624485:

MSB ------------------ LSB 10011000011101100101 En binario sin formato 010011000011101100101 Rellenado a un múltiplo de 7 bits 0100110 0001110 1100101 Dividido en grupos de 7 bits00100110 10001110 11100101 Agregue bits 1 altos en todos los grupos excepto el último (el más significativo) para formar bytes 0x26 0x8E 0xE5 En hexadecimal→ 0xE5 0x8E 0x26 Flujo de salida (LSB a MSB)

LEB128 sin signo y VLQ ( cantidad de longitud variable ) comprimen cualquier número entero dado no solo en el mismo número de bits, sino exactamente en los mismos bits; los dos formatos difieren sólo en cómo se organizan exactamente esos bits.

Firmado LEB128

Un número con signo se representa de manera similar: comenzando con una representación en complemento a dos de bits , donde es un múltiplo de 7, el número se divide en grupos como para la codificación sin signo.

Por ejemplo, el número con signo -123456 está codificado como 0xC0 0xBB 0x78:

MSB ------------------ LSB 11110001001000000 Codificación binaria de 123456 000011110001001000000 Como número de 21 bits 111100001110110111111 Negando todos los bits ( complemento a unos ) 111100001110111000000 Sumando uno (complemento a dos) 1111000 0111011 1000000 Dividido en grupos de 7 bits01111000 10111011 11000000 Agregue bits 1 altos en todos los grupos excepto el último (el más significativo) para formar bytes 0x78 0xBB 0xC0 En hexadecimal→ 0xC0 0xBB 0x78 Flujo de salida (LSB a MSB)

Decodificación rápida

Una implementación escalar sencilla de la decodificación LEB128 es bastante lenta, más aún en hardware moderno donde la predicción errónea de ramas es relativamente costosa. Una serie de artículos presenta técnicas SIMD para acelerar la decodificación (en estos artículos se llama VByte, pero es otro nombre para la misma codificación). El artículo "Vectorized VByte Decoding" [4] presentó "Masked VByte", que demostró velocidades de 650 a 2700 millones de enteros por segundo en hardware Haswell básico , dependiendo de la densidad de codificación. Un artículo de seguimiento presentó una variante de codificación, "Stream VByte: Faster Byte Oriented Integer Compression", [5] que aumentó las velocidades a más de 4 mil millones de enteros por segundo. Esta codificación de flujo separa el flujo de control de los datos codificados, por lo que no es compatible binariamente con LEB128.

Pseudocódigo tipo C

Codificar entero sin signo

do { byte = 7 bits de valor de orden bajo ; valor >>= 7 ; if ( value != 0 ) /* vienen más bytes */ establece el bit de byte de orden superior ; emitir byte ; } mientras ( valor ! = 0 );                           

Codificar entero con signo

más = 1 ; negativo = ( valor < 0 );      /* el tamaño en bits del valor de la variable, por ejemplo, 64 si el tipo del valor es int64_t */ size = no . de bits en entero con signo ;       while ( more ) { byte = 7 bits de valor de orden inferior ; valor >>= 7 ; /* lo siguiente sólo es necesario si la implementación de >>= utiliza un  desplazamiento lógico en lugar de un desplazamiento aritmético para un operando izquierdo con signo */ if ( negativo ) valor |= ( ~ 0 << ( tamaño - 7 )); /* firmar extender */                        /* el bit de signo del byte es el segundo bit de orden superior (0x40) */ if (( valor == 0 && el bit de signo del byte está claro ) || ( valor == -1 && el bit de signo del byte está establecido )) más = 0 ; de lo contrario, establece un bit de byte de orden superior ; emitir byte ; }                                 

Decodificar entero sin signo

resultado = 0 ; cambio = 0 ; while ( verdadero ) { byte = siguiente byte en la entrada ; resultado |= ( 7 bits de byte de orden bajo ) << cambio ; if ( bit de byte de orden superior == 0 ) break ; cambio += 7 ; }                                

Decodificar entero con signo

resultado = 0 ; cambio = 0 ;    /* el tamaño en bits de la variable de resultado, por ejemplo, 64 si el tipo de resultado es int64_t */ tamaño = número de bits en entero con signo ;       hacer { byte = siguiente byte en la entrada ; resultado |= ( 7 bits de byte de orden bajo << cambio ); cambio += 7 ; } while ( bit de byte de orden superior ! = 0 );                          /* el bit de signo del byte es el segundo bit de orden superior (0x40) */ if (( cambio < tamaño ) && ( el bit de signo del byte está establecido )) /* extensión del signo */ resultado |= ( ~ 0 << cambio ) ;               

código javascript

Codificar entero de 32 bits con signo

const encodeSignedLeb128FromInt32 = ( valor ) => { valor |= 0 ; resultado constante = []; mientras ( verdadero ) { const byte_ = valor & 0x7f ; valor >>= 7 ; if ( ( valor === 0 && ( byte_ & 0x40 ) === 0 ) || ( valor === - 1 && ( byte_ & 0x40 ) !== 0 ) ) { resultado . empujar ( byte_ ); resultado de retorno ; } resultado . empujar ( byte_ | 0x80 ); } };                                                       

Decodificar un entero de 32 bits con signo

const decodeSignedLeb128 = ( entrada ) => { dejar resultado = 0 ; dejar cambio = 0 ; mientras ( verdadero ) { byte constante = entrada . cambio (); resultado |= ( byte & 0x7f ) << cambio ; cambio += 7 ; if (( 0x80 & byte ) === 0 ) { if ( shift < 32 && ( byte & 0x40 ) !== 0 ) { devolver resultado | ( ~ 0 << cambio ); } devolver resultado ; } } };                                                           

Usos

Codificaciones relacionadas

Referencias

  1. ^ UNIX International (julio de 1993), "7.8", Especificación de formato de información de depuración DWARF Versión 2.0, borrador (PDF) , consultado el 19 de julio de 2009
  2. ^ ab Free Standards Group (diciembre de 2005). "Especificación de formato de información de depuración DWARF versión 3.0" (PDF) . pag. 70 . Consultado el 19 de julio de 2009 .
  3. ^ ab Grupo comunitario WebAssembly (12 de noviembre de 2020). "Valores - Formato binario - WebAssembly 1.1" . Consultado el 31 de diciembre de 2020 .
  4. ^ Plaisance, Jeff; Kurz, Nathan; Lemire, Daniel (2015). "Decodificación de VByte vectorizada". arXiv : 1503.07387 . {{cite journal}}: Citar diario requiere |journal=( ayuda )
  5. ^ Lemire, Daniel; Kurz, Nathan; Rupp, Christoph (febrero de 1028). "Stream VByte: compresión de enteros orientada a bytes más rápida". Cartas de Procesamiento de Información . 130 . Primer Simposio Internacional sobre Algoritmos Web (publicado en junio de 2015): 1–6. arXiv : 1709.08990 . doi :10.1016/j.ipl.2017.09.011. S2CID  8265597.
  6. ^ "Formato ejecutable Dalvik" . Consultado el 18 de mayo de 2021 .
  7. ^ Christophe de Dinechin (octubre de 2000). "Manejo de excepciones de C++ para IA-64" . Consultado el 19 de julio de 2009 .
  8. ^ Proyecto LLVM (2016). "Formato de asignación de cobertura de código LLVM" . Consultado el 20 de octubre de 2016 .
  9. ^ Proyecto LLVM (2019). "Codificación y decodificación LLVM LEB128" . Consultado el 2 de noviembre de 2019 .
  10. ^ Método System.IO.BinaryWriter.Write7BitEncodedInt (int) y método System.IO.BinaryReader.Read7BitEncodedInt ().
  11. ^ "Minecraft Modern Varint y Varlong". wiki.vg. ​2020 . Consultado el 29 de noviembre de 2020 .
  12. ^ "Documentación de MPatrol". Diciembre de 2008 . Consultado el 19 de julio de 2009 .
  13. ^ "Osr (formato de archivo) - osu!wiki". osu.ppy.sh. ​Consultado el 18 de marzo de 2017 .
  14. ^ "Formato 1.0 de intercambio XML eficiente (EXI)". www.w3.org (Segunda ed.). Consorcio Mundial de la red . 2014-02-11 . Consultado el 31 de diciembre de 2020 .
  15. ^ "El formato de archivo .xz". tukaani.org . 2009 . Consultado el 30 de octubre de 2017 .
  16. ^ "Formato de archivo de código de bits LLVM: documentación de LLVM 13".

Ver también