Friday, May 15, 2009

Copy from Byte Array To Structure

I've seen a few bad (or at least suboptimal) implementations of this out there, so I thought I'd throw my own implementation into the mix.

There are three reasons why I have some issues with many other implementations I've been seeing:
  1. The implementation uses managed pointers to access the byte array as though they are unmanaged pointers. Unfortunately, this doesn't really work.
  2. The implementation locks the managed pointer on the byte array, which affects garbage collection and can seriously affect throughput. Locking should be avoided for copying small structs around.
  3. The implementation copies the data properly into an unmanaged pointer first, but it uses a heap allocation method to get the memory, which for small structures is somewhat suboptimal - stack memory is probably better for this sort of thing.
The following code snippet avoids all three of the issues above. The only problem is there is an extra memory copy which could only be avoided with managed C++ and its managed pointer construct (I may post that another time). Enjoy.

public sealed abstract class BinaryStreamSupport
{
private BinaryStreamSupport() { }
public static T ReadStruct(Stream s)

{
int size;
byte[] data;

size = Marshal.SizeOf(typeof(T));
data = new byte[size];
s.Read(data, 0, size);
return _ReadStruct(data, 0, size);
}

public static T ReadStruct(byte[] data, int start)
{
return _ReadStruct(data, start, Marshal.SizeOf(typeof(T)));
}

private static T _ReadStruct(byte[] data, int start, int size)
{
T returnValue;
unsafe
{
byte* stackDataPtr = stackalloc byte[size];
IntPtr stackData = new IntPtr(stackDataPtr);
Marshal.Copy(data, start, stackData, size);
returnValue = (T)Marshal.PtrToStructure(stackData, typeof(T));
}

return returnValue;
}
}

No comments: