DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
C# (csharp) Bitfields - PackedByte, PackedUShort
In c++ it is possible to have fields smaller than one byte with bitfields:
struct Tile
{
char Type:4;
bool River:1;
bool Fortress:1;
char Road:2;
};
Below is a way to have bitfields in C#. The speed is quite acceptable, and in this example PackedByte allowed to fit four byte values in one byte. How to use:
public struct Tile
{
PackedByte data1;
/// <summary>
/// 4 bits (0-15)
/// </summary>
public byte Type
{
get { return (byte)data1.Get(0,4); }
set { data1.Set(0,4,(byte)value); }
}
/// <summary>
/// 1 bit
/// </summary>
public bool River
{
get { return data1.Get(4,1)!=0; }
set { data1.Set(4,1,value?(byte)1:(byte)0); }
}
/// <summary>
/// 1 bit
/// </summary>
public bool Fortress
{
get { return data1.Get(5,1)!=0; }
set { data1.Set(5,1,value?(byte)1:(byte)0); }
}
/// <summary>
/// 2 bits (0-3)
/// </summary>
public RoadState Road
{
get { return (RoadState)data1.Get(6,2); }
set { data1.Set(6,2,(byte)value); }
}
}
public struct PackedByte
{
public PackedByte(byte data)
{
this.data=data;
}
static byte[] masks=
{
0,
2-1,//1
4-1,//2
8-1,//3
16-1,//4
32-1,//5
64-1,//6
128-1,//7
256-1,//8
};
public byte Get(int start,int count)
{
byte mask=masks[count];
return (byte)((data&(mask<<start))>>start);
}
public void Set(int start,int count,byte data)
{
byte mask=masks[count];
if (data>mask)
{
throw new ArgumentOutOfRangeException();
}
this.data=(byte)(this.data&(~(mask<<start)));
this.data=(byte)(this.data|((data<<start)));
}
byte data;
public byte Data
{
get { return data; }
set { data=value; }
}
}
public struct PackedUShort
{
public PackedUShort(ushort data)
{
this.data=data;
}
static ushort[] masks=
{
0,
2-1,//1
4-1,//2
8-1,//3
16-1,//4
32-1,//5
64-1,//6
128-1,//7
256-1,//8
512-1,//9
1024-1,//10
2048-1,//11
4096-1,//12
8192-1,//13
16384-1,//14
32768-1,//15
65536-1,//16
};
public ushort Get(int start,int count)
{
ushort mask=masks[count];
return (ushort)((data&(mask<<start))>>start);
}
public void Set(int start,int count,ushort data)
{
ushort mask=masks[count];
if (data>mask)
{
throw new ArgumentOutOfRangeException();
}
this.data=(ushort)(this.data&(~(mask<<start)));
this.data=(ushort)(this.data|((data<<start)));
}
ushort data;
public ushort Data
{
get { return data; }
set { data=value; }
}
}





