IntPtr initial_pointer;
long initial_position;
long current_position;
+#if NET_4_0
+ SafeBuffer safebuffer;
+#endif
internal event EventHandler Closed;
}
[CLSCompliantAttribute(false)]
- public unsafe UnmanagedMemoryStream (byte *pointer, long length)
+ public unsafe UnmanagedMemoryStream (byte *pointer, long length) :
+ this (pointer, length, length, FileAccess.Read)
{
- Initialize (pointer, length, length, FileAccess.Read);
}
[CLSCompliantAttribute(false)]
public unsafe UnmanagedMemoryStream (byte *pointer, long length, long capacity, FileAccess access)
{
+ closed = true;
Initialize (pointer, length, capacity, access);
}
-
+
+#if NET_4_0
+ public UnmanagedMemoryStream (SafeBuffer buffer, long offset, long length) :
+ this (buffer, offset, length, FileAccess.Read)
+ {
+ }
+
+ public UnmanagedMemoryStream (SafeBuffer buffer, long offset, long length, FileAccess access)
+ {
+ closed = true;
+ Initialize (buffer, offset, length, access);
+ }
+#endif
#endregion
#region Properties
[CLSCompliantAttribute (false)]
public unsafe byte* PositionPointer {
get {
+#if NET_4_0
+ if (safebuffer != null)
+ throw new NotSupportedException ("Not supported when using SafeBuffer");
+#endif
if (closed)
throw new ObjectDisposedException("The stream is closed");
if (current_position >= length)
return (byte *) initial_pointer + current_position;
}
set {
+#if NET_4_0
+ if (safebuffer != null)
+ throw new NotSupportedException ("Not supported when using SafeBuffer");
+#endif
if (closed)
throw new ObjectDisposedException("The stream is closed");
if (fileaccess == FileAccess.Write)
throw new NotSupportedException("Stream does not support reading");
- else {
- if (current_position >= length)
- return (0);
- else {
- int progress = current_position + count < length ? count : (int) (length - current_position);
- for (int i = 0; i < progress; i++)
- buffer [offset + i] = Marshal.ReadByte (initial_pointer, (int) current_position++);
- return progress;
+
+ if (current_position >= length)
+ return 0;
+
+ int progress = current_position + count < length ? count : (int) (length - current_position);
+#if NET_4_0
+ if (safebuffer != null) {
+ unsafe {
+ byte *ptr = null;
+ try {
+ safebuffer.AcquirePointer (ref ptr);
+ Marshal.Copy (new IntPtr (ptr + current_position), buffer, offset, progress);
+ } finally {
+ if (ptr != null)
+ safebuffer.ReleasePointer ();
+ }
}
+ } else
+#endif
+ {
+ Marshal.Copy (new IntPtr (initial_pointer.ToInt64 () + current_position), buffer, offset, progress);
}
+ current_position += progress;
+ return progress;
}
public override int ReadByte ()
if (fileaccess== FileAccess.Write)
throw new NotSupportedException("Stream does not support reading");
- else {
- if (current_position >= length)
- return (-1);
+
+ if (current_position >= length)
+ return (-1);
+
+#if NET_4_0
+ if (safebuffer != null) {
+ unsafe {
+ byte *ptr = null;
+ try {
+ safebuffer.AcquirePointer (ref ptr);
+ return (int) Marshal.ReadByte (new IntPtr (ptr), (int) current_position++);
+ } finally {
+ if (ptr != null)
+ safebuffer.ReleasePointer ();
+ }
+ }
+ } else
+#endif
+ {
return (int) Marshal.ReadByte(initial_pointer, (int) current_position++);
}
}
public override void SetLength (long value)
{
+#if NET_4_0
+ if (safebuffer != null)
+ throw new NotSupportedException ("Not supported when using SafeBuffer");
+#endif
if (closed)
throw new ObjectDisposedException("The stream is closed");
if (value < 0)
throw new NotSupportedException ("Unable to expand length of this stream beyond its capacity.");
if (fileaccess == FileAccess.Read)
throw new NotSupportedException ("Stream does not support writing.");
- else {
- unsafe {
- // use Marshal.WriteByte since that allow us to start writing
- // from the current position
- for (int i = 0; i < count; i++)
- Marshal.WriteByte (initial_pointer, (int) current_position++, buffer [offset + i]);
- if (current_position > length)
- length = current_position;
+#if NET_4_0
+ if (safebuffer != null) {
+ unsafe {
+ byte *dest = null;
+ try {
+ safebuffer.AcquirePointer (ref dest);
+ fixed (byte *src = buffer) {
+ dest += current_position;
+ String.memcpy (dest, src + offset, count);
+ }
+ } finally {
+ if (dest != null)
+ safebuffer.ReleasePointer ();
+ }
+ }
+ } else
+#endif
+ {
+ unsafe {
+ fixed (byte *src = buffer) {
+ byte *dest = (byte *) initial_pointer + current_position;
+ String.memcpy (dest, src + offset, count);
+ }
}
}
+ current_position += count;
+ if (current_position > length)
+ length = current_position;
}
public override void WriteByte (byte value)
throw new NotSupportedException("The current position is at the end of the capacity of the stream");
if (fileaccess == FileAccess.Read)
throw new NotSupportedException("Stream does not support writing.");
- else {
+
+#if NET_4_0
+ if (safebuffer != null) {
+ unsafe {
+ byte *dest = null;
+ try {
+ safebuffer.AcquirePointer (ref dest);
+ dest += current_position++;
+ *dest = value;
+ } finally {
+ if (dest != null)
+ safebuffer.ReleasePointer ();
+ }
+ }
+ } else
+#endif
+ {
unsafe {
- Marshal.WriteByte(initial_pointer, (int)current_position, value);
- current_position++;
- if (current_position > length)
- length = current_position;
+ byte *dest = (byte *) initial_pointer + (int) current_position++;
+ *dest = value;
}
}
+ if (current_position > length)
+ length = current_position;
}
[CLSCompliant (false)]
throw new ArgumentOutOfRangeException("length", "The length cannot be greater than the capacity.");
if ((access < FileAccess.Read) || (access > FileAccess.ReadWrite))
throw new ArgumentOutOfRangeException ("access", "Enum value was out of legal range.");
+ if (!closed)
+ throw new InvalidOperationException ("Called Initialize twice");
fileaccess = access;
this.length = length;
initial_pointer = new IntPtr ((void*)pointer);
closed = false;
}
+
+#if NET_4_0
+ protected void Initialize (SafeBuffer buffer, long offset, long length, FileAccess access)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException ("offset");
+
+ if (length < 0)
+ throw new ArgumentOutOfRangeException ("length");
+
+ ulong blength = buffer.ByteLength;
+ if ((blength - (ulong) length) < (ulong) offset)
+ throw new ArgumentException ("Invalid offset and/or length");
+
+ if (access < FileAccess.Read || access > FileAccess.ReadWrite)
+ throw new ArgumentOutOfRangeException ("access");
+
+ if (!closed)
+ throw new InvalidOperationException ("Called Initialize twice");
+
+ this.length = length;
+ this.capacity = length;
+ this.fileaccess = access;
+ this.safebuffer = buffer;
+ initial_position = offset;
+ current_position = offset;
+ closed = false;
+ }
+#endif
#endregion
}
}