Moved Dump, GetBytes and IntPtr operator to SafeAllocatedMemory base class. Added byte* and SafeBuffer operators to SafeAllocatedMemory.

pull/60/head
David Hall 2019-03-25 17:38:42 -07:00
parent 8281580a28
commit dc83d5d0b4
1 changed files with 46 additions and 28 deletions

View File

@ -132,8 +132,11 @@ namespace Vanara.InteropServices
/// <value>The size in bytes of the allocated memory block.</value>
public abstract int Size { get; set; }
/// <summary>Zero out all allocated memory.</summary>
public virtual void Zero() => Fill(0, Size);
#if DEBUG
/// <summary>Dumps memory to byte string.</summary>
[ExcludeFromCodeCoverage]
public string Dump => Size == 0 ? "" : string.Join(" ", GetBytes(0, Size).Select(b => b.ToString("X2")).ToArray());
#endif
/// <summary>Fills the allocated memory with a specific byte value.</summary>
/// <param name="value">The byte value.</param>
@ -145,7 +148,44 @@ namespace Vanara.InteropServices
public virtual void Fill(byte value, int length)
{
if (length > Size) throw new ArgumentOutOfRangeException(nameof(length));
Vanara.Extensions.InteropExtensions.FillMemory(handle, value, length);
handle.FillMemory(value, length);
}
/// <summary>Zero out all allocated memory.</summary>
public virtual void Zero() => Fill(0, Size);
/// <summary>Gets a copy of bytes from the allocated memory block.</summary>
/// <param name="startIndex">The start index.</param>
/// <param name="count">The number of bytes to retrieve.</param>
/// <returns>A byte array with the copied bytes.</returns>
protected byte[] GetBytes(int startIndex, int count)
{
if (startIndex < 0 || startIndex + count > Size) throw new ArgumentOutOfRangeException();
var ret = new byte[count];
Marshal.Copy(handle, ret, startIndex, count);
return ret;
}
/// <summary>Performs an explicit conversion from <see cref="SafeAllocatedMemoryHandle"/> to <see cref="SafeBuffer"/>.</summary>
/// <param name="hMem">The <see cref="SafeAllocatedMemoryHandle"/> instance.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator SafeBuffer(SafeAllocatedMemoryHandle hMem) => new SafeBufferImpl(hMem);
/// <summary>Performs an explicit conversion from <see cref="SafeAllocatedMemoryHandle"/> to <see cref="System.Byte*"/>.</summary>
/// <param name="hMem">The <see cref="SafeAllocatedMemoryHandle"/> instance.</param>
/// <returns>The result of the conversion.</returns>
public static unsafe explicit operator byte* (SafeAllocatedMemoryHandle hMem) => (byte*)hMem.handle;
/// <summary>Performs an explicit conversion from <see cref="SafeAllocatedMemoryHandle"/> to <see cref="System.IntPtr"/>.</summary>
/// <param name="hMem">The <see cref="SafeAllocatedMemoryHandle"/> instance.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(SafeAllocatedMemoryHandle hMem) => hMem.handle;
private class SafeBufferImpl : SafeBuffer
{
public SafeBufferImpl(SafeAllocatedMemoryHandle hMem) : base(false) => Initialize((ulong)hMem.Size);
protected override bool ReleaseHandle() => true;
}
}
@ -205,23 +245,6 @@ namespace Vanara.InteropServices
}
}
/// <summary>Returns the <see cref="SafeMemoryHandle{T}"/> as an <see cref="IntPtr"/>. This is a dangerous call as the value is mutable.</summary>
/// <param name="h">The <see cref="SafeMemoryHandle{T}"/> instance.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(SafeMemoryHandle<TMem> h) => h.DangerousGetHandle();
/// <summary>Gets a copy of bytes from the allocated memory block.</summary>
/// <param name="startIndex">The start index.</param>
/// <param name="count">The number of bytes to retrieve.</param>
/// <returns>A byte array with the copied bytes.</returns>
protected byte[] GetBytes(int startIndex, int count)
{
if (startIndex < 0 || startIndex + count > Size) throw new ArgumentOutOfRangeException();
var ret = new byte[count];
Marshal.Copy(handle, ret, startIndex, count);
return ret;
}
/// <summary>When overridden in a derived class, executes the code required to free the handle.</summary>
/// <returns>
/// true if the handle is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a
@ -271,7 +294,7 @@ namespace Vanara.InteropServices
/// <param name="s">The string value.</param>
/// <param name="charSet">The character set of the string.</param>
/// <returns>SafeMemoryHandleExt object to an native (unmanaged) string</returns>
protected SafeMemoryHandleExt(string s, CharSet charSet = CharSet.Unicode) : base(IntPtr.Zero, StringHelper.GetByteCount(s, true, charSet), true)
protected SafeMemoryHandleExt(string s, CharSet charSet = CharSet.Unicode) : base(IntPtr.Zero, s.GetByteCount(true, charSet), true)
{
RuntimeHelpers.PrepareConstrainedRegions();
SetHandle(StringHelper.GetCharSize(charSet) == 2 ? mm.AllocStringUni(s) : mm.AllocStringAnsi(s));
@ -334,7 +357,7 @@ namespace Vanara.InteropServices
/// <param name="charSet">The character set of the strings.</param>
/// <param name="prefixBytes">Number of bytes preceding the array of string pointers.</param>
/// <returns>Enumeration of strings.</returns>
public IEnumerable<string> ToStringEnum(int count, CharSet charSet = CharSet.Auto, int prefixBytes = 0) => IsInvalid ? new string[0] : InteropExtensions.ToStringEnum(handle, count, charSet, prefixBytes);
public IEnumerable<string> ToStringEnum(int count, CharSet charSet = CharSet.Auto, int prefixBytes = 0) => IsInvalid ? new string[0] : handle.ToStringEnum(count, charSet, prefixBytes);
/// <summary>
/// Gets an enumerated list of strings from a block of unmanaged memory where each string is separated by a single '\0' character and is terminated by
@ -343,7 +366,7 @@ namespace Vanara.InteropServices
/// <param name="charSet">The character set of the strings.</param>
/// <param name="prefixBytes">Number of bytes preceding the array of string pointers.</param>
/// <returns>An enumerated list of strings.</returns>
public IEnumerable<string> ToStringEnum(CharSet charSet = CharSet.Auto, int prefixBytes = 0) => IsInvalid ? new string[0] : InteropExtensions.ToStringEnum(handle, charSet, prefixBytes);
public IEnumerable<string> ToStringEnum(CharSet charSet = CharSet.Auto, int prefixBytes = 0) => IsInvalid ? new string[0] : handle.ToStringEnum(charSet, prefixBytes);
/// <summary>Marshals data from this block of memory to a newly allocated managed object of the type specified by a generic type parameter.</summary>
/// <typeparam name="T">The type of the object to which the data is to be copied. This must be a structure.</typeparam>
@ -356,11 +379,6 @@ namespace Vanara.InteropServices
return handle.ToStructure<T>();
}
#if DEBUG
[ExcludeFromCodeCoverage]
public string Dump => Size == 0 ? "" : string.Join(" ", ToEnumerable<byte>(Size).Select(b => b.ToString("X2")).ToArray());
#endif
/// <summary>When overridden in a derived class, executes the code required to free the handle.</summary>
/// <returns>
/// true if the handle is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a