私は、バイト境界を越えて大量のデータをビットにパッキングする仕様に準拠する必要があるツールに取り組んでいます。例: 2 バイトは 2 フィールド、10 ビット値、6 ビット許容値をエンコードします。他のフィールドは 2 ~ 4 バイトにまたがり、さらに多くのフィールドに分割される場合があります。
C# と戦って (C++ のように) ビットフィールドで構造体を取得しようとするのではなく、別の方法として、データを送信する直前/受信した直後に一般的なビット パッキング/アンパッキング関数を作成し、標準型を使用して C# ですべてのデータを操作することを考えました。 : byte、short、int、long など
私はC#が初めてなので、これにアプローチする最善の方法がわかりません。私が読んだことから、unsafe
ポインターと一緒に使用することはお勧めできませんが、ジェネリック型を使用しようとする私の試みは惨めに失敗しました:
private static bool GetBitsFromByte<T,U>(T input, byte count, out U output, byte start = 0) where T:struct where U:struct
{
if (input == default(T))
return false;
if( (start + count) > Marshal.SizeOf(input))
return false;
if(count > Marshal.SizeOf(output))
return false;
// I'd like to setup the correct output container based on the
// number of bits that are needed
if(count <= 8)
output = new byte();
else if (count <= 16)
output = new UInt16();
else if (count <= 32)
output = new UInt32();
else if (count <= 64)
output = new UInt64();
else
return false;
output = 0; // Init output
// Copy bits out in order
for (int i = start; i < count; i++)
{
output |= (input & (1 << i)); // This is not possible with generic types from my understanding
}
return true;
}
このような方法でメソッドを呼び出して、(LSB から) から 10 ビットを取り出しdata_in
、data_out
次の 6 ビットを からdata_in
取り出しnext_data_out
ます。
Uint32 data_in = 0xdeadbeef;
Uint16 data_out;
byte next_data_out;
if(GetBitsFromByte<Uint32,Uint16>(data_in, 10, out data_out, 0))
{
// data_out should now = 0x2EF
if(GetBitsFromByte<Uint32,byte>(data_in, 6, out next_data_out, data_out.Length))
{
// next_data_out should now = 0x2F
}
}
byte
、ushort
、uint
、のすべての可能な組み合わせに対して関数を記述する必要はありませんがulong
、それは別の方法だと思います。
私はすでにBitConverter
クラスを見ましたが、それはビットを操作しないバイト配列用です。また、私は:やのようなことはできないことも理解しているので、提案をお待ちしています。where T : INumeric
where T : System.ValueType
ありがとう!