2009-09-08 19 views
5

Estoy mirando la biblioteca C# llamada BitStream, que le permite escribir y leer cualquier cantidad de bits en un objeto estándar C# Stream. Noté lo que me pareció una extraña decisión de diseño:Diseñando un BitStream en C#

Al agregar bits a un byte vacío, los bits se agregan al MSB del byte. Por ejemplo:

var s = new BitStream(); 
s.Write(true); 
Debug.Assert(s.ToByteArray()[0] == 0x80); // and not 0x01 

var s = new BitStream(); 
s.Write(0x7,0,4); 
s.Write(0x3,0,4); 
Debug.Assert(s.ToByteArray()[0] == 0x73); // and not 0x37 

Sin embargo, cuando se hace referencia bits en un número que el de entrada, el primer bit del número de entrada es el LSB. Por ejemplo

//s.Write(int input,int bit_offset, int count_bits) 
//when referencing the LSB and the next bit we'll write 
s.Write(data,0,2); //and not s.Write(data,data_bits_number,data_bits_number-2) 

Me parece inconsistente. Como en este caso, al copiar "gradualmente" un byte como en el ejemplo anterior (los primeros cuatro bits y luego los últimos cuatro bits), no obtendremos el byte original. Necesitamos copiarlo "hacia atrás" (primero los últimos cuatro bits, luego los primeros cuatro bits).

¿Hay alguna razón para ese diseño que me falta? ¿Alguna otra implementación de bits transmite con este comportamiento? ¿Cuáles son las consideraciones de diseño para eso?

Parece que el flujo de bits ffmpeg se comporta de una manera que considero consistente. Mire la cantidad que cambia el byte antes de OR ing con el puntero src en the put_bits function.

Como una nota:

La primera byte añadió, es el primer byte en la matriz de bytes. Por ejemplo

var s = new BitStream(); 
s.Write(0x1,0,4); 
s.Write(0x2,0,4); 
s.Write(0x3,0,4); 
Debug.Assert(s.ToByteArray()[0] == 0x12); // and not s.ToByteArray()[1] == 0x12 

Respuesta

3

Estas son algunas consideraciones adicionales:

En el caso de la boolean - sólo se requiere un bit para representar verdaderas o falsas. Cuando ese bit se agrega al comienzo de la transmisión, la secuencia de bits es "1". Cuando extiende esa secuencia a la longitud de bytes, fuerza el relleno de cero bits al final de la secuencia, aunque para empezar, esos bits no existían en la secuencia. La posición en la secuencia es información importante al igual que los valores de los bits, y una secuencia de bits de "1000000" o 0x80 salvaguarda la expectativa de que los lectores subsiguientes de la secuencia puedan tener que el primer bit que leen es el primer bit que se agregó.

En segundo lugar, otros tipos de datos como los enteros requieren más bits para representar, por lo que ocuparán más espacio en la secuencia que los booleanos. Mezclar diferentes tipos de datos de tamaño en la misma secuencia puede ser muy complicado cuando no están alineados en los límites de bytes.

Finalmente, si tiene Intel x86, la arquitectura de su CPU es "little-endian", lo que significa LSB primero como lo describe. Si necesita almacenar valores en la transmisión como big-endian, deberá agregar una capa de conversión en su código, similar a lo que ha mostrado anteriormente, donde ingresa un byte a la vez en la secuencia en el orden que desee. .Esto es molesto, pero comúnmente requerido si necesita interoperar con cajas de Unix big-endian o según lo requiera una especificación de protocolo.

Espero que ayude!

1

¿Hay una razón para que el diseño que me falta? ¿Alguna otra implementación de bits transmite con este comportamiento? ¿Cuáles son las consideraciones de diseño para eso?

No creo que haya ningún significado significativo detrás de la descision. Técnicamente, no importa, siempre y cuando el escritor y el lector estén de acuerdo con el orden.

+0

Me parece inconsistente. Como en este caso, cuando "gradualmente" Pero acabo de mostrar que sí importa. Cita: "al copiar un byte como en el ejemplo anterior (los primeros cuatro bits y luego los últimos cuatro bits), no obtendremos el byte original. Necesitamos copiarlo" al revés "(primero los últimos cuatro bits, luego el primeros cuatro bits) ". –

+0

Como dije, cuando tanto el lector como el escritor están de acuerdo en el orden de los bits, no importa. IMO debe usar BitStream para leer y escribir. Si tiene otras intenciones, como leer los bytes resultantes, probablemente solo deba escribir su propia transmisión. –

1

Estoy de acuerdo con Elazar.

Como él/ella señala, este es un caso donde el lector y el escritor NO se ponen de acuerdo en el orden de los bits. De hecho, son incompatibles.