namespace System.Runtime.InteropServices
{
- [CLSCompliant (false)]
public abstract class SafeBuffer : SafeHandleZeroOrMinusOneIsInvalid, IDisposable {
ulong byte_length;
+ unsafe byte *last_byte;
bool inited;
- protected SafeBuffer (bool ownsHandle) : base (ownsHandle) {
+ protected SafeBuffer (bool ownsHandle) : base (ownsHandle)
+ {
}
- public void Initialize (ulong numBytes) {
- byte_length = numBytes;
+ [CLSCompliant (false)]
+ public void Initialize (ulong numBytes)
+ {
+ if (numBytes == 0)
+ throw new ArgumentOutOfRangeException ("numBytes");
+
inited = true;
+ byte_length = numBytes;
+ unsafe {
+ last_byte = (byte *) (((byte *) handle) + numBytes);
+ }
}
- public void Initialize (uint numElements, uint sizeOfEachElement) {
+ [CLSCompliant (false)]
+ public void Initialize (uint numElements, uint sizeOfEachElement)
+ {
Initialize (numElements * sizeOfEachElement);
}
- public void Initialize<T> (uint numElements) where T : struct {
+ [CLSCompliant (false)]
+ public void Initialize<T> (uint numElements) where T : struct
+ {
Initialize (numElements, (uint)Marshal.SizeOf (typeof (T)));
}
+ [CLSCompliant (false)]
public unsafe void AcquirePointer (ref byte* pointer) {
if (!inited)
throw new InvalidOperationException ();
DangerousRelease ();
}
+ [CLSCompliant (false)]
public ulong ByteLength {
get {
return byte_length;
}
}
- [MonoTODO]
- public T Read<T> (ulong byteOffset) where T : struct {
- throw new NotImplementedException ();
+ [CLSCompliant (false)]
+ public T Read<T> (ulong byteOffset) where T : struct
+ {
+ if (!inited)
+ throw new InvalidOperationException ();
+
+ unsafe {
+ byte *source = (((byte *) handle) + byteOffset);
+ if (source >= last_byte || source + Marshal.SizeOf (typeof (T)) > last_byte){
+ throw new ArgumentException ("byteOffset");
+ }
+
+ return (T) Marshal.PtrToStructure ((IntPtr) source, typeof (T));
+ }
}
- [MonoTODO]
+ [CLSCompliant (false)]
public void ReadArray<T> (ulong byteOffset, T[] array, int index, int count) where T : struct {
- throw new NotImplementedException ();
+ if (!inited)
+ throw new InvalidOperationException ();
+
+ unsafe {
+ int size = Marshal.SizeOf (typeof (T)) * count;
+ byte *source = (((byte *) handle) + byteOffset);
+ if (source >= last_byte || source + size > last_byte)
+ throw new ArgumentException ("byteOffset");
+
+ Marshal.copy_from_unmanaged ((IntPtr) source, index, array, count);
+ }
}
- [MonoTODO]
+ [CLSCompliant (false)]
public void Write<T> (ulong byteOffset, T value) where T : struct {
- throw new NotImplementedException ();
+ if (!inited)
+ throw new InvalidOperationException ();
+
+ unsafe {
+ byte *target = (((byte *) handle) + byteOffset);
+ if (target >= last_byte || target + Marshal.SizeOf (typeof (T)) > last_byte)
+ throw new ArgumentException ("byteOffset");
+
+ Marshal.StructureToPtr (value, (IntPtr) target, false);
+ }
}
- [MonoTODO]
- public void WriteArray<T> (ulong byteOffset, T[] array, int index, int count) where T : struct {
- throw new NotImplementedException ();
+ [CLSCompliant (false)]
+ public void WriteArray<T> (ulong byteOffset, T[] array, int index, int count) where T : struct
+ {
+ if (!inited)
+ throw new InvalidOperationException ();
+
+ unsafe {
+ byte *target = ((byte *) handle) + byteOffset;
+ int size = Marshal.SizeOf (typeof (T)) * count;
+ if (target >= last_byte || target + size > last_byte)
+ throw new ArgumentException ("would overrite");
+
+ Marshal.copy_to_unmanaged (array, index, (IntPtr) target, count);
+ }
}
}
}