/// <summary> /// Gets a single value from the current buffer at the specified position. /// </summary> /// <typeparam name="T">The type of the value to be read from the buffer.</typeparam> /// <param name="positionInBytes">Relative position in bytes from the beginning of the buffer to get the data from.</param> /// <param name="value">The value as out.</param> /// <returns>The value that was read.</returns> public void Get <T>(int positionInBytes, out T value) where T : struct { unsafe { SdxUtilities.ReadOut((IntPtr)(_buffer + positionInBytes), out value); } }
/// <summary> /// Gets a sequence of elements from a position in the buffer into a target buffer. /// </summary> /// <param name="positionInBytes">Relative position in bytes from the beginning of the buffer to get the data from.</param> /// <param name = "buffer">An array of values to be read from the buffer.</param> /// <param name = "offset">The zero-based byte offset in buffer at which to begin storing /// the data read from the current buffer.</param> /// <param name = "count">The number of values to be read from the current buffer.</param> public void GetRange <T>(int positionInBytes, T[] buffer, int offset, int count) where T : struct { unsafe { SdxUtilities.Read((IntPtr)(_buffer + positionInBytes), buffer, offset, count); } }
/// <summary> /// Sets a range of data to a specified position into the buffer. /// </summary> /// <param name="positionInBytes">Relative position in bytes from the beginning of the buffer to set the data to.</param> /// <param name = "source">A pointer to the location to start copying from.</param> /// <param name = "count">The number of bytes to copy from source to the current buffer.</param> public void Set(int positionInBytes, IntPtr source, long count) { unsafe { SdxUtilities.CopyMemory((IntPtr)(_buffer + positionInBytes), source, (int)count); } }
/// <summary> /// Sets an array of values to a specified position into the buffer. /// </summary> /// <typeparam name = "T">The type of the values to be written to the buffer.</typeparam> /// <param name="positionInBytes">Relative position in bytes from the beginning of the buffer to set the data to.</param> /// <param name = "data">An array of values to be written to the buffer.</param> /// <param name = "offset">The zero-based offset in data at which to begin copying values to the current buffer.</param> /// <param name = "count">The number of values to be written to the current buffer. If this is zero, /// all of the contents <paramref name = "data" /> will be written.</param> public void Set <T>(int positionInBytes, T[] data, int offset, int count) where T : struct { unsafe { SdxUtilities.Write((IntPtr)(_buffer + positionInBytes), data, offset, count); } }
/// <summary> /// Creates the specified user buffer. /// </summary> /// <typeparam name="T">Type of the buffer.</typeparam> /// <param name="userBuffer">The buffer to use as a DataBuffer.</param> /// <param name="index">Index inside the buffer in terms of element count (not size in bytes).</param> /// <param name="pinBuffer">True to keep the managed buffer and pin it, false will allocate unmanaged memory and make a copy of it. Default is true.</param> /// <returns>An instance of a DataBuffer</returns> public static DataBuffer Create <T>(T[] userBuffer, int index = 0, bool pinBuffer = true) where T : struct { unsafe { if (userBuffer == null) { throw new ArgumentNullException("userBuffer"); } if (index < 0 || index > userBuffer.Length) { throw new ArgumentException("Index is out of range [0, userBuffer.Length-1]", "index"); } DataBuffer buffer; var sizeOfBuffer = SdxUtilities.SizeOf(userBuffer); var indexOffset = index * SdxUtilities.SizeOf <T>(); if (pinBuffer) { var handle = GCHandle.Alloc(userBuffer, GCHandleType.Pinned); buffer = new DataBuffer(indexOffset + (byte *)handle.AddrOfPinnedObject(), sizeOfBuffer - indexOffset, handle); } else { // The .NET Native compiler crashes if '(IntPtr)' is removed. buffer = new DataBuffer(indexOffset + (byte *)(IntPtr)Interop.Fixed(userBuffer), sizeOfBuffer - indexOffset, true); } return(buffer); } }
/// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (disposing) { #if !WINDOWS_UWP if (_blob != null) { _blob.Dispose(); _blob = null; } #endif } if (_gCHandle.IsAllocated) { _gCHandle.Free(); } unsafe { if (_ownsBuffer && _buffer != (sbyte *)0) { SdxUtilities.FreeMemory((IntPtr)_buffer); _buffer = (sbyte *)0; } } }
/// <summary> /// When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. /// </summary> /// <param name="buffer">An array of bytes. This method copies <paramref name="count" /> bytes from <paramref name="buffer" /> to the current stream.</param> /// <param name="offset">The zero-based byte offset in <paramref name="buffer" /> at which to begin copying bytes to the current stream.</param> /// <param name="count">The number of bytes to be written to the current stream.</param> public void Write(IntPtr buffer, int offset, int count) { unsafe { SdxUtilities.CopyMemory((IntPtr)(_buffer + _position), new IntPtr((byte *)buffer + offset), count); _position += count; } }
/// <summary> /// Gets a single value from the current buffer at the specified position. /// </summary> /// <param name="positionInBytes">Relative position in bytes from the beginning of the buffer to get the data from.</param> /// <typeparam name = "T">The type of the value to be read from the buffer.</typeparam> /// <returns>The value that was read.</returns> public T Get <T>(int positionInBytes) where T : struct { unsafe { T result = default(T); SdxUtilities.Read((IntPtr)(_buffer + positionInBytes), ref result); return(result); } }
/// <summary> /// Gets an array of values from a position in the buffer. /// </summary> /// <param name="positionInBytes">Relative position in bytes from the beginning of the buffer to get the data from.</param> /// <param name="count">number of T instance to get from the positionInBytes</param> /// <typeparam name = "T">The type of the values to be read from the buffer.</typeparam> /// <returns>An array of values that was read from the current buffer.</returns> public T[] GetRange <T>(int positionInBytes, int count) where T : struct { unsafe { var result = new T[count]; SdxUtilities.Read((IntPtr)(_buffer + positionInBytes), result, 0, count); return(result); } }
/// <summary> /// Converts this instance to a read only typed buffer. /// </summary> /// <typeparam name="T">Type of a buffer element</typeparam> /// <returns>A readonly typed buffer.</returns> /// <exception cref="System.InvalidOperationException">DataPointer is Zero</exception> public T[] ToArray <T>() where T : struct { if (Pointer == IntPtr.Zero) { throw new InvalidOperationException("DataPointer is Zero"); } var buffer = new T[Size / SdxUtilities.SizeOf <T>()]; CopyTo(buffer, 0, buffer.Length); return(buffer); }
/// <summary> /// Writes a single value to the stream, and advances the current position /// within this stream by the number of bytes written. /// </summary> /// <remarks> /// In order to provide faster read/write, this operation doesn't check stream bound. /// A client must carefully not read/write above the size of this datastream. /// </remarks> /// <typeparam name = "T">The type of the value to be written to the stream.</typeparam> /// <param name = "value">The value to write to the stream.</param> /// <exception cref = "T:System.NotSupportedException">The stream does not support writing.</exception> public void Write <T>(T value) where T : struct { if (!_canWrite) { throw new NotSupportedException(); } unsafe { _position = (byte *)SdxUtilities.WriteAndPosition((IntPtr)(_buffer + _position), ref value) - _buffer; } }
/// <summary> /// Initializes a new instance of the <see cref = "DataBuffer" /> class, and allocates a new buffer to use as a backing store. /// </summary> /// <param name = "sizeInBytes">The size of the buffer to be allocated, in bytes.</param> /// <exception cref = "T:System.ArgumentOutOfRangeException"> /// <paramref name = "sizeInBytes" /> is less than 1.</exception> public DataBuffer(int sizeInBytes) { unsafe { Debug.Assert(sizeInBytes > 0); _buffer = (sbyte *)SdxUtilities.AllocateMemory(sizeInBytes); _size = sizeInBytes; _ownsBuffer = true; } }
/// <summary> /// Writes an array of values to the current stream, and advances the current position /// within this stream by the number of bytes written. /// </summary> /// <remarks> /// In order to provide faster read/write, this operation doesn't check stream bound. /// A client must carefully not read/write above the size of this datastream. /// </remarks> /// <typeparam name = "T">The type of the values to be written to the stream.</typeparam> /// <param name = "data">An array of values to be written to the stream.</param> /// <param name = "offset">The zero-based offset in data at which to begin copying values to the current stream.</param> /// <param name = "count">The number of values to be written to the current stream. If this is zero, /// all of the contents <paramref name = "data" /> will be written.</param> /// <exception cref = "T:System.NotSupportedException">This stream does not support writing.</exception> public void WriteRange <T>(T[] data, int offset, int count) where T : struct { unsafe { if (!_canWrite) { throw new NotSupportedException(); } _position = (byte *)SdxUtilities.Write((IntPtr)(_buffer + _position), data, offset, count) - _buffer; } }
/// <summary> /// Initializes a new instance of the <see cref = "DataStream" /> class, and allocates a new buffer to use as a backing store. /// </summary> /// <param name = "sizeInBytes">The size of the buffer to be allocated, in bytes.</param> /// <param name = "canRead"> /// <c>true</c> if reading from the buffer should be allowed; otherwise, <c>false</c>.</param> /// <param name = "canWrite"> /// <c>true</c> if writing to the buffer should be allowed; otherwise, <c>false</c>.</param> public DataStream(int sizeInBytes, bool canRead, bool canWrite) { unsafe { Debug.Assert(sizeInBytes > 0); _buffer = (byte *)SdxUtilities.AllocateMemory(sizeInBytes); _size = sizeInBytes; _ownsBuffer = true; _canRead = canRead; _canWrite = canWrite; } }
/// <summary> /// Reads a sequence of elements from the current stream into a target buffer and /// advances the position within the stream by the number of bytes read. /// </summary> /// <remarks> /// In order to provide faster read/write, this operation doesn't check stream bound. /// A client must carefully not read/write above the size of this datastream. /// </remarks> /// <param name = "buffer">An array of values to be read from the stream.</param> /// <param name = "offset">The zero-based byte offset in buffer at which to begin storing /// the data read from the current stream.</param> /// <param name = "count">The number of values to be read from the current stream.</param> /// <returns>The number of bytes read from the stream.</returns> /// <exception cref = "T:System.NotSupportedException">This stream does not support reading.</exception> public int ReadRange <T>(T[] buffer, int offset, int count) where T : struct { unsafe { if (!_canRead) { throw new NotSupportedException(); } var oldPosition = _position; _position = (byte *)SdxUtilities.Read((IntPtr)(_buffer + _position), buffer, offset, count) - _buffer; return((int)(_position - oldPosition)); } }
/// <summary> /// Converts this instance to a read only byte buffer. /// </summary> /// <returns>A readonly byte buffer.</returns> /// <exception cref="System.InvalidOperationException"> /// DataPointer is Zero /// or /// Size cannot be < 0 /// </exception> public byte[] ToArray() { if (Pointer == IntPtr.Zero) { throw new InvalidOperationException("DataPointer is Zero"); } if (Size < 0) { throw new InvalidOperationException("Size cannot be < 0"); } var buffer = new byte[Size]; SdxUtilities.Read(Pointer, buffer, 0, Size); return(buffer); }
/// <summary> /// Reads a single value from the current stream and advances the current /// position within this stream by the number of bytes read. /// </summary> /// <remarks> /// In order to provide faster read/write, this operation doesn't check stream bound. /// A client must carefully not read/write above the size of this datastream. /// </remarks> /// <typeparam name = "T">The type of the value to be read from the stream.</typeparam> /// <returns>The value that was read.</returns> /// <exception cref = "T:System.NotSupportedException">This stream does not support reading.</exception> public T Read <T>() where T : struct { unsafe { if (!_canRead) { throw new NotSupportedException(); } byte *from = _buffer + _position; T result = default(T); _position = (byte *)SdxUtilities.ReadAndPosition((IntPtr)from, ref result) - _buffer; return(result); } }
/// <summary> /// Reads an array of values from the current stream, and advances the current position /// within this stream by the number of bytes written. /// </summary> /// <remarks> /// In order to provide faster read/write, this operation doesn't check stream bound. /// A client must carefully not read/write above the size of this datastream. /// </remarks> /// <typeparam name = "T">The type of the values to be read from the stream.</typeparam> /// <returns>An array of values that was read from the current stream.</returns> public T[] ReadRange <T>(int count) where T : struct { unsafe { if (!_canRead) { throw new NotSupportedException(); } byte *from = _buffer + _position; var result = new T[count]; _position = (byte *)SdxUtilities.Read((IntPtr)from, result, 0, count) - _buffer; return(result); } }
internal unsafe DataBuffer(void *buffer, int sizeInBytes, bool makeCopy) { Debug.Assert(sizeInBytes > 0); if (makeCopy) { _buffer = (sbyte *)SdxUtilities.AllocateMemory(sizeInBytes); SdxUtilities.CopyMemory((IntPtr)_buffer, (IntPtr)buffer, sizeInBytes); } else { _buffer = (sbyte *)buffer; } _size = sizeInBytes; _ownsBuffer = makeCopy; }
internal unsafe DataStream(void *buffer, int sizeInBytes, bool canRead, bool canWrite, bool makeCopy) { Debug.Assert(sizeInBytes > 0); if (makeCopy) { _buffer = (byte *)SdxUtilities.AllocateMemory(sizeInBytes); SdxUtilities.CopyMemory((IntPtr)_buffer, (IntPtr)buffer, sizeInBytes); } else { _buffer = (byte *)buffer; } _size = sizeInBytes; _canRead = canRead; _canWrite = canWrite; _ownsBuffer = makeCopy; }
/// <summary> /// Writes a range of bytes to the current stream, and advances the current position /// within this stream by the number of bytes written. /// </summary> /// <remarks> /// In order to provide faster read/write, this operation doesn't check stream bound. /// A client must carefully not read/write above the size of this datastream. /// </remarks> /// <param name = "source">A pointer to the location to start copying from.</param> /// <param name = "count">The number of bytes to copy from source to the current stream.</param> /// <exception cref = "T:System.NotSupportedException">This stream does not support writing.</exception> public void WriteRange(IntPtr source, long count) { unsafe { if (!_canWrite) { throw new NotSupportedException(); } Debug.Assert(_canWrite); Debug.Assert(source != IntPtr.Zero); Debug.Assert(count > 0); Debug.Assert((_position + count) <= _size); // TODO: use Interop.memcpy SdxUtilities.CopyMemory((IntPtr)(_buffer + _position), source, (int)count); _position += count; } }
/// <summary> /// Writes the content of the specified buffer to the unmanaged memory location of this instance. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="buffer">The buffer to read from.</param> /// <param name="offset">The offset in the array to read from.</param> /// <param name="count">The number of T element to write to the memory location.</param> /// <exception cref="System.ArgumentNullException">buffer</exception> /// <exception cref="System.InvalidOperationException">DataPointer is Zero</exception> /// <exception cref="System.ArgumentOutOfRangeException">buffer;Total buffer size cannot be larger than size of this data pointer</exception> public void CopyFrom <T>(T[] buffer, int offset, int count) where T : struct { if (buffer == null) { throw new ArgumentNullException("buffer"); } if (Pointer == IntPtr.Zero) { throw new InvalidOperationException("DataPointer is Zero"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", "Must be >= 0"); } if (count <= 0) { throw new ArgumentOutOfRangeException("count", "Must be > 0"); } if (count * SdxUtilities.SizeOf <T>() > Size) { throw new ArgumentOutOfRangeException("buffer", "Total buffer size cannot be larger than size of this data pointer"); } SdxUtilities.Write(Pointer, buffer, offset, count); }
/// <summary> /// Clears the buffer. /// </summary> public unsafe void Clear(byte value = 0) { SdxUtilities.ClearMemory((IntPtr)_buffer, value, Size); }