2009-09-08 8 views
5

Je regarde la bibliothèque C# appelée BitStream, qui vous permet d'écrire et de lire n'importe quel nombre de bits sur un objet C# Stream standard. J'ai remarqué ce qui m'a semblé une décision de conception étrange:Conception d'un BitStream en C#

Lors de l'ajout de bits à un octet vide, les bits sont ajoutés au MSB de l'octet. Par exemple:

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 

Cependant, lors du référencement bits dans un nombre comme entrée , le premier bit du nombre d'entrée est le bit de poids faible. Par exemple

//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) 

Cela semble incohérent pour moi. Puisque dans ce cas, lors de la copie "progressive" d'un octet comme dans l'exemple précédent (les quatre premiers bits, puis les quatre derniers bits), nous n'obtiendrons pas l'octet d'origine. Nous devons le copier "en arrière" (d'abord les quatre derniers bits, puis les quatre premiers bits).

Y a-t-il une raison pour cette conception qui me manque? Toute autre mise en œuvre de bits flux avec ce comportement? Quelles sont les considérations de conception pour cela?

Il semble que ffmpeg bitstream se comporte d'une manière que je considère cohérente. Regardez le montant qu'il déplace l'octet avant OR avec le pointeur src dans the put_bits function.

Comme une note de côté:

Le premier octet ajouté, est le premier octet dans le tableau d'octets. Par exemple

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 

Répondre

3

Voici quelques considérations supplémentaires:

Dans le cas du booléen - un seul bit est nécessaire pour représenter vrai ou faux. Lorsque ce bit est ajouté au début du flux, le flux de bits est "1". Lorsque vous étendez ce flux à la longueur de l'octet, il force le remplissage de zéro bits à la fin du flux, même si ces bits n'existaient pas dans le flux pour commencer. Position dans le flux est une information importante tout comme les valeurs des bits, et un flux de "1000000" ou 0x80 sauvegarde l'attente que les lecteurs suivants du flux peuvent avoir que le premier bit qu'ils lisent est le premier bit qui a été ajouté. Deuxièmement, d'autres types de données comme les entiers requièrent plus de bits à représenter, donc ils vont prendre plus de place dans le flux que les booléens. Le mélange de types de données de tailles différentes dans le même flux peut être très délicat lorsqu'ils ne sont pas alignés sur les limites d'octets. Enfin, si vous êtes sur Intel x86, l'architecture de votre processeur est «little-endian», ce qui signifie que LSB vous décrit d'abord. Si vous avez besoin de stocker des valeurs dans le flux en tant que big-endian, vous devez ajouter une couche de conversion dans votre code - similaire à celle que vous avez montrée ci-dessus lorsque vous insérez un octet dans le flux dans l'ordre souhaité .Ceci est ennuyeux, mais communément requis si vous avez besoin d'interopérer avec des boîtes Unix big-endian ou comme cela peut être requis par une spécification de protocole.

Espérons que ça aide!

1

Y at-il une raison pour que la conception que je suis absent? Toute autre mise en œuvre de bits flux avec ce comportement? Quelles sont les considérations de conception pour cela?

Je doute qu'il y avait une signification significative derrière la descision. Techniquement, cela n'a pas d'importance tant que l'auteur et le lecteur sont d'accord sur la commande.

+0

Cela semble incohérent pour moi. Depuis dans ce cas, quand "progressivement" Mais je viens de le montrer a de l'importance. Citation: "copier un octet comme dans l'exemple précédent (les quatre premiers bits, puis les quatre derniers bits), nous n'obtiendrons pas l'octet original, nous devons le copier" en arrière "(d'abord les quatre derniers bits, puis le quatre premiers bits). " –

+0

Comme je l'ai dit, lorsque le lecteur et l'auteur sont d'accord sur l'ordre des bits, cela n'a pas d'importance. IMO vous devriez utiliser le BitStream pour lire et écrire. Si vous avez d'autres intentions, comme lire les octets qui en résultent, vous devriez probablement écrire votre propre flux. –

1

Je suis d'accord avec Elazar. Comme il le fait remarquer, il s'agit d'un cas où le lecteur et l'auteur ne sont PAS d'accord sur l'ordre des bits. En fait, ils sont incompatibles.

Questions connexes