Writing to unmanaged memory in C#
My line of work involves a great deal of interop, and although I've written a number of solutions for manipulating unmanaged memory in C#, this is probably the most elegant. Real programmers don't write safe C#.
PHP Code:
using System;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
namespace AngraMainyu.IO
{
public static class UnmanagedMemoryStreamExtension
{
unsafe public static T Read<T>(this UnmanagedMemoryStream stream) where T : struct
{
var t = (T)Marshal.PtrToStructure((IntPtr)(stream.PositionPointer), typeof(T));
stream.Position += Marshal.SizeOf(t);
return t;
}
unsafe public static String ReadString(this UnmanagedMemoryStream stream)
{
var s = new String((sbyte*)stream.PositionPointer);
stream.Position += s.Length;
return s;
}
unsafe public static String ReadString(this UnmanagedMemoryStream stream, int length)
{
var s = new String((sbyte*)stream.PositionPointer, 0, length);
stream.Position += s.Length;
return s;
}
public static byte ReadByte(this UnmanagedMemoryStream stream)
{
return Read<byte>(stream);
}
public static sbyte ReadSByte(this UnmanagedMemoryStream stream)
{
return Read<sbyte>(stream);
}
public static short ReadInt16(this UnmanagedMemoryStream stream)
{
return Read<Int16>(stream);
}
public static ushort ReadUInt16(this UnmanagedMemoryStream stream)
{
return Read<UInt16>(stream);
}
public static int ReadInt32(this UnmanagedMemoryStream stream)
{
return Read<Int32>(stream);
}
public static uint ReadUInt32(this UnmanagedMemoryStream stream)
{
return Read<UInt32>(stream);
}
public static long ReadInt64(this UnmanagedMemoryStream stream)
{
return Read<Int64>(stream);
}
public static ulong ReadUInt64(this UnmanagedMemoryStream stream)
{
return Read<UInt64>(stream);
}
public static Single ReadSingle(this UnmanagedMemoryStream stream)
{
return Read<Single>(stream);
}
public static Double ReadDouble(this UnmanagedMemoryStream stream)
{
return Read<Double>(stream);
}
public static Decimal ReadDecimal(this UnmanagedMemoryStream stream)
{
return Read<Decimal>(stream);
}
unsafe public static void Write<T>(this UnmanagedMemoryStream stream, T value) where T : struct
{
var length = Marshal.SizeOf(value);
if (stream.Position + length > stream.Length) {
throw new NotSupportedException();
} else {
var handle = GCHandle.Alloc(value);
for (int i = 0; i < length; i++) {
*(stream.PositionPointer + i) = ((byte*)handle.AddrOfPinnedObject())[i];
}
stream.Position += length;
handle.Free();
}
}
public static void WriteByte(this UnmanagedMemoryStream stream, byte value)
{
Write<byte>(stream, value);
}
public static void WriteSByte(this UnmanagedMemoryStream stream, sbyte value)
{
Write<sbyte>(stream, value);
}
public static void WriteInt16(this UnmanagedMemoryStream stream, short value)
{
Write<Int16>(stream, value);
}
public static void WriteUInt16(this UnmanagedMemoryStream stream, ushort value)
{
Write<UInt16>(stream, value);
}
public static void WriteInt32(this UnmanagedMemoryStream stream, int value)
{
Write<Int32>(stream, value);
}
public static void WriteUInt32(this UnmanagedMemoryStream stream, uint value)
{
Write<UInt32>(stream, value);
}
public static void WriteInt64(this UnmanagedMemoryStream stream, long value)
{
Write<Int64>(stream, value);
}
public static void WriteUInt64(this UnmanagedMemoryStream stream, ulong value)
{
Write<UInt64>(stream, value);
}
public static void WriteSingle(this UnmanagedMemoryStream stream, float value)
{
Write<Single>(stream, value);
}
public static void WriteDouble(this UnmanagedMemoryStream stream, double value)
{
Write<Double>(stream, value);
}
public static void WriteDecimal(this UnmanagedMemoryStream stream, decimal value)
{
Write<Decimal>(stream, value);
}
}
}