Spesso capita di dover lavorare con i bit, specialmente quando si lavora con i protocolli di comunicazione.
Sfortunatamente nei linguaggi di programmazione ad alto livello a differenza dell’asm, spesso mancano le funzioni giuste per accedere direttamente ai valori dei bit e il dato minimo che si può leggere è il byte.
In questo articolo propongo una semplice classe per il linguaggio di programmazione C# .Net utile per accedere direttamente ai bit di una variabile di tipo byte. Per un ulteriore dimostrazione dell’utilità di questa classe ho implementato anche l’algoritmo Base64 sfruttando i metodi per i bit.
I metodi della classe consentono di :
-Leggere il valore di un bit da un byte
-Settare il valore di un bit in un byte
-Codificare e Decodificare in base64
Spero che questa classe torni utile a qualcuno a presto!
using System;
using System.Collections.Generic;
using System.Text;
namespace BitClass
{
class BitFunction
{
//Get bit 0-7 flag return 1 or 0, if any error return -1
public int GetBitFlag ( Byte MyByte , int BitN )
{
Byte B;
switch (BitN)
{
case 0:
B = (byte)((byte)MyByte & (byte)0×01);
return System.Convert.ToInt32(B);
break;
case 1:
B = (byte)((byte)MyByte & (byte)0×02);
B = System.Convert.ToByte(B >> 1);
return System.Convert.ToInt32(B);
break;
case 2:
B = (byte)((byte)MyByte & (byte)0×04);
B = System.Convert.ToByte(B >> 2);
return System.Convert.ToInt32(B);
break;
case 3:
B = (byte)((byte)MyByte & (byte)0×08);
B = System.Convert.ToByte(B >> 3);
return System.Convert.ToInt32(B);
break;
case 4:
B = (byte)((byte)MyByte & (byte)0×10);
B = System.Convert.ToByte(B >> 4);
return System.Convert.ToInt32(B);
break;
case 5:
B = (byte)((byte)MyByte & (byte)0×20);
B = System.Convert.ToByte(B >> 5);
return System.Convert.ToInt32(B);
break;
case 6:
B = (byte)((byte)MyByte & (byte)0×40);
B = System.Convert.ToByte(B >> 6);
return System.Convert.ToInt32(B);
break;
case 7:
B = (byte)((byte)MyByte & (byte)0×80);
B = System.Convert.ToByte(B >> 7);
return System.Convert.ToInt32(B);
break;
default:
return -1;
break;
}
return -1;
}
//Set bit 0-7 flag, return a setted Byte.. if any error return the original byte
public Byte SetBitFlag(Byte MyByte, int BitN, int value)
{
// If any errors return the original Byte!
if (((BitN < 0) && (BitN > 7)) || ((value < 0) && (value > 1)))
return MyByte;
//Setting the bit…
switch (BitN)
{
case 0:
if (value == 0)
{
// Is the bit 0 == 0?
if (GetBitFlag(MyByte, 0) == 0)
return MyByte; // It’s Already setted to 0!
else //it’s setted to 1
{
MyByte = (byte)( MyByte ^ (byte)0×01); // Need to set it to 0
return MyByte;
}
}
if (value == 1)
// Is the bit 0 == 1?
if (GetBitFlag(MyByte, 0) == 1)
return MyByte; // It’s Already setted to 1!
else //it’s setted to 0
{
MyByte = (byte)(MyByte ^ (byte)0×01);// Need to set it to 1
return MyByte;
}
break;
case 1:
if (value == 0)
{
// Is the bit 0 == 0?
if (GetBitFlag(MyByte, 1) == 0)
return MyByte; // It’s Already setted to 0!
else //it’s setted to 1
{
MyByte = (byte)(MyByte ^ (byte)0×02); // Need to set it to 0
return MyByte;
}
}
if (value == 1)
// Is the bit 0 == 1?
if (GetBitFlag(MyByte, 1) == 1)
return MyByte; // It’s Already setted to 1!
else //it’s setted to 0
{
MyByte = (byte)(MyByte ^ (byte)0×02);// Need to set it to 1
return MyByte;
}
break;
case 2:
if (value == 0)
{
// Is the bit 0 == 0?
if (GetBitFlag(MyByte, 2) == 0)
return MyByte; // It’s Already setted to 0!
else //it’s setted to 1
{
MyByte = (byte)(MyByte ^ (byte)0×04); // Need to set it to 0
return MyByte;
}
}
if (value == 1)
// Is the bit 0 == 1?
if (GetBitFlag(MyByte, 2) == 1)
return MyByte; // It’s Already setted to 1!
else //it’s setted to 0
{
MyByte = (byte)(MyByte ^ (byte)0×04);// Need to set it to 1
return MyByte;
}
break;
case 3:
if (value == 0)
{
// Is the bit 0 == 0?
if (GetBitFlag(MyByte, 3) == 0)
return MyByte; // It’s Already setted to 0!
else //it’s setted to 1
{
MyByte = (byte)(MyByte ^ (byte)0×08); // Need to set it to 0
return MyByte;
}
}
if (value == 1)
// Is the bit 0 == 1?
if (GetBitFlag(MyByte, 3) == 1)
return MyByte; // It’s Already setted to 1!
else //it’s setted to 0
{
MyByte = (byte)(MyByte ^ (byte)0×08);// Need to set it to 1
return MyByte;
}
break;
case 4:
if (value == 0)
{
// Is the bit 0 == 0?
if (GetBitFlag(MyByte, 4) == 0)
return MyByte; // It’s Already setted to 0!
else //it’s setted to 1
{
MyByte = (byte)(MyByte ^ (byte)0×10); // Need to set it to 0
return MyByte;
}
}
if (value == 1)
// Is the bit 0 == 1?
if (GetBitFlag(MyByte, 4) == 1)
return MyByte; // It’s Already setted to 1!
else //it’s setted to 0
{
MyByte = (byte)(MyByte ^ (byte)0×10);// Need to set it to 1
return MyByte;
}
break;
case 5:
if (value == 0)
{
// Is the bit 0 == 0?
if (GetBitFlag(MyByte, 5) == 0)
return MyByte; // It’s Already setted to 0!
else //it’s setted to 1
{
MyByte = (byte)(MyByte ^ (byte)0×20); // Need to set it to 0
return MyByte;
}
}
if (value == 1)
// Is the bit 0 == 1?
if (GetBitFlag(MyByte, 5) == 1)
return MyByte; // It’s Already setted to 1!
else //it’s setted to 0
{
MyByte = (byte)(MyByte ^ (byte)0×20);// Need to set it to 1
return MyByte;
}
break;
case 6:
if (value == 0)
{
// Is the bit 0 == 0?
if (GetBitFlag(MyByte, 6) == 0)
return MyByte; // It’s Already setted to 0!
else //it’s setted to 1
{
MyByte = (byte)(MyByte ^ (byte)0×40); // Need to set it to 0
return MyByte;
}
}
if (value == 1)
// Is the bit 0 == 1?
if (GetBitFlag(MyByte, 6) == 1)
return MyByte; // It’s Already setted to 1!
else //it’s setted to 0
{
MyByte = (byte)(MyByte ^ (byte)0×40);// Need to set it to 1
return MyByte;
}
break;
case 7:
if (value == 0)
{
// Is the bit 0 == 0?
if (GetBitFlag(MyByte, 7) == 0)
return MyByte; // It’s Already setted to 0!
else //it’s setted to 1
{
MyByte = (byte)(MyByte ^ (byte)0×80); // Need to set it to 0
return MyByte;
}
}
if (value == 1)
// Is the bit 0 == 1?
if (GetBitFlag(MyByte, 7) == 1)
return MyByte; // It’s Already setted to 1!
else //it’s setted to 0
{
MyByte = (byte)(MyByte ^ (byte)0×80);// Need to set it to 1
return MyByte;
}
break;
case 8:
if (value == 0)
{
// Is the bit 0 == 0?
if (GetBitFlag(MyByte, 8) == 0)
return MyByte; // It’s Already setted to 0!
else //it’s setted to 1
{
MyByte = (byte)(MyByte ^ (byte)0×01); // Need to set it to 0
return MyByte;
}
}
if (value == 1)
// Is the bit 0 == 1?
if (GetBitFlag(MyByte, 8) == 1)
return MyByte; // It’s Already setted to 1!
else //it’s setted to 0
{
MyByte = (byte)(MyByte ^ (byte)0×01);// Need to set it to 1
return MyByte;
}
break;
default:
return MyByte;
break;
}
return MyByte;
}
//GEt the value of Upper Nibble of a byte
public byte GetUpperNibble(Byte B) // Return Upper nibble of a byte
{
B = (byte)((byte)B & (byte)0xF0);
B = System.Convert.ToByte(B >> 4);
return B;
}
//GEt the value of Lower Nibble of a byte
public byte GetLowerNibble(Byte B) // Return Lower nibble of a byte
{
B = (byte)((byte)B & (byte)0×0F);
return B;
}
public string Base64_Encode ( Byte[] ToEncode )
{
String BaseArray = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”;
String Encoded = “”;
Byte[] encoded_char = new Byte[4];
int BitIndex = 7;
for (int i = 0; i < ToEncode.Length – ToEncode.Length % 3; )
{
for (int x = 0; x < 4; x++)
{
for (int j = 5; j >= 0; j–)
{
encoded_char[x] = SetBitFlag(encoded_char[x], j, GetBitFlag(ToEncode[i], BitIndex));
BitIndex = BitIndex – 1;
if (BitIndex == -1)
{
BitIndex = 7;
i++;
}
}
}
for (int y = 0; y < 4; y++)
Encoded += BaseArray[System.Convert.ToInt32(encoded_char[y])].ToString();
}
encoded_char[0] = 0;
encoded_char[1] = 0;
encoded_char[2] = 0;
encoded_char[3] = 0;
// If 1 byte miss case
if (ToEncode.Length % 3 == 2)
{
BitIndex = 7;
for (int i = ToEncode.Length – 2; i < ToEncode.Length; )
{
for (int x = 0; x < 3; x++)
{
for (int j = 5; j >= 0; j–)
{
if (i < ToEncode.Length )
encoded_char[x] = SetBitFlag(encoded_char[x], j, GetBitFlag(ToEncode[i], BitIndex));
else
{
i++;
}
BitIndex = BitIndex – 1;
if (BitIndex == -1)
{
BitIndex = 7;
i++;
}
}
}
for (int y = 0; y < 3; y++)
Encoded += BaseArray[System.Convert.ToInt32(encoded_char[y])].ToString();
Encoded += “=”;
}
}
encoded_char[0] = 0;
encoded_char[1] = 0;
encoded_char[2] = 0;
encoded_char[3] = 0;
// If 1 byte miss case
if (ToEncode.Length % 3 == 1)
{
BitIndex = 7;
for (int i = ToEncode.Length – 1; i < ToEncode.Length; )
{
for (int x = 0; x < 2; x++)
{
for (int j = 5; j >= 0; j–)
{
encoded_char[x] = SetBitFlag(encoded_char[x], j, GetBitFlag(ToEncode[i], BitIndex));
BitIndex = BitIndex – 1;
if (BitIndex == -1)
{
BitIndex = 7;
i++;
if (i == ToEncode.Length)
break;
}
}
}
for (int y = 0; y < 2; y++)
Encoded += BaseArray[System.Convert.ToInt32(encoded_char[y])].ToString();
Encoded += “==”;
}
}
return Encoded;
}
public byte[] Base64_Decode(String ToDecode)
{
String BaseArray = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”;
byte[] Decoded = new byte[0];
int LenDecoded = 0;
int StopIt = 0;
if (ToDecode.Length > 3)
{
Byte[] ToDecodeValue = new Byte[ToDecode.Length];
if ((ToDecode[ToDecode.Length - 1] == ‘=’) && (ToDecode[ToDecode.Length - 2] != ‘=’))
{
StopIt = 1;
if (ToDecode.Length > 4)
LenDecoded = (((ToDecode.Length – 4) / 4) * 3) + 2;
else
LenDecoded = 2;
}
if ((ToDecode[ToDecode.Length - 1] == ‘=’) && (ToDecode[ToDecode.Length - 2] == ‘=’))
{
StopIt = 2;
if (ToDecode.Length > 4)
LenDecoded = (((ToDecode.Length – 4) / 4) * 3) + 1;
else
LenDecoded = 1;
}
if ((ToDecode[ToDecode.Length - 1] != ‘=’) && (ToDecode[ToDecode.Length - 2] != ‘=’))
{
LenDecoded = (((ToDecode.Length) / 4) * 3);
}
Decoded = new byte[LenDecoded];
for (int i = 0; i < ToDecode.Length – StopIt; i++)
{
int z = 0;
while ( ToDecode[i] != BaseArray[z] )
z++;
ToDecodeValue[i] = System.Convert.ToByte( z );
}
int BitIndex = 5;
int EncodedIndex = 0;
for (int i = 0; i < LenDecoded; i++)
{
for (int j = 7; j >= 0; j–)
{
Decoded[i] = SetBitFlag(Decoded[i], j, GetBitFlag(ToDecodeValue[EncodedIndex], BitIndex));
BitIndex = BitIndex – 1;
if (BitIndex == -1)
{
BitIndex = 5;
EncodedIndex = EncodedIndex + 1;
}
}
}
}
return Decoded;
}
}
}