Páginas

2011/12/09

C# : Big/Little Endian Integers using struct + implicit operator

Using binary data with C/C++ or D is pretty easy. Those languages have pointers and structs and fields on structs have a fixed memory offset related to the start of the struct. That way you can read a bunch of bytes and get a pointer to a struct on those bytes without extracting or reinserting the struct fields on the array.

On C# using the unsafe + fixed keywords we can use pointers and even pointers to simple structs. Only if those structs contains just primitive values or structs satifying this condition. This allows mapping a byte array to a struct pointer, and that simplifies a lot working with structures and binary data.

Lately I have been working on stuff where i had to work with binary data that contained Big Endian and in some cases mixed with other fields in Little Endian. How to work with this stuff easily?

Some people says that using BitConverter. Other even using bit shifting directly.

I have a much better alternative that will allow us to have structures/fields/variables or parameters using BigEndian and work with them seamlessly. Though the real utility is for serializing/deserializing and mapping pointer's memory.

We can achieve that creating an structure containing a single private integer of the desired width, and using the implicit operator.

For a 32 bits integer:

public struct uint_be
{
 private uint _InternalValue;

 public uint NativeValue
 {
  set
  {
   _InternalValue = MathUtils.ByteSwap(value);
  }
  get
  {
   return MathUtils.ByteSwap(_InternalValue);
  }
 }

 public static implicit operator uint(uint_be that)
 {
  return that.NativeValue;
 }

 public static implicit operator uint_be(uint that)
 {
  return new uint_be()
  {
   NativeValue = that,
  };
 }
}


With this we will be able to use the uint_be type as if it were a normal uint value. This will make an automatical cast to the uint type. The field on memory will be as a big endian integer. But we will be able to get the value as a little endian with the property or just using the value as if it were a normal uint. This struct could be improved detecting the endianness of the platform and avoiding to perform the ByteSwap if it is already big endian.

No comments:

Post a Comment