From dc83d5d0b48fdfd51e89c4ec2021b4d6cf47f168 Mon Sep 17 00:00:00 2001 From: David Hall Date: Mon, 25 Mar 2019 17:38:42 -0700 Subject: [PATCH] Moved Dump, GetBytes and IntPtr operator to SafeAllocatedMemory base class. Added byte* and SafeBuffer operators to SafeAllocatedMemory. --- Core/InteropServices/SafeMemoryHandle.cs | 74 ++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/Core/InteropServices/SafeMemoryHandle.cs b/Core/InteropServices/SafeMemoryHandle.cs index c821b6c1..55b8c7ab 100644 --- a/Core/InteropServices/SafeMemoryHandle.cs +++ b/Core/InteropServices/SafeMemoryHandle.cs @@ -132,8 +132,11 @@ namespace Vanara.InteropServices /// The size in bytes of the allocated memory block. public abstract int Size { get; set; } - /// Zero out all allocated memory. - public virtual void Zero() => Fill(0, Size); +#if DEBUG + /// Dumps memory to byte string. + [ExcludeFromCodeCoverage] + public string Dump => Size == 0 ? "" : string.Join(" ", GetBytes(0, Size).Select(b => b.ToString("X2")).ToArray()); +#endif /// Fills the allocated memory with a specific byte value. /// The byte value. @@ -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); + } + + /// Zero out all allocated memory. + public virtual void Zero() => Fill(0, Size); + + /// Gets a copy of bytes from the allocated memory block. + /// The start index. + /// The number of bytes to retrieve. + /// A byte array with the copied bytes. + 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; + } + + /// Performs an explicit conversion from to . + /// The instance. + /// The result of the conversion. + public static explicit operator SafeBuffer(SafeAllocatedMemoryHandle hMem) => new SafeBufferImpl(hMem); + + /// Performs an explicit conversion from to . + /// The instance. + /// The result of the conversion. + public static unsafe explicit operator byte* (SafeAllocatedMemoryHandle hMem) => (byte*)hMem.handle; + + /// Performs an explicit conversion from to . + /// The instance. + /// The result of the conversion. + 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 } } - /// Returns the as an . This is a dangerous call as the value is mutable. - /// The instance. - /// The result of the conversion. - public static explicit operator IntPtr(SafeMemoryHandle h) => h.DangerousGetHandle(); - - /// Gets a copy of bytes from the allocated memory block. - /// The start index. - /// The number of bytes to retrieve. - /// A byte array with the copied bytes. - 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; - } - /// When overridden in a derived class, executes the code required to free the handle. /// /// 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 /// The string value. /// The character set of the string. /// SafeMemoryHandleExt object to an native (unmanaged) string - 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 /// The character set of the strings. /// Number of bytes preceding the array of string pointers. /// Enumeration of strings. - public IEnumerable ToStringEnum(int count, CharSet charSet = CharSet.Auto, int prefixBytes = 0) => IsInvalid ? new string[0] : InteropExtensions.ToStringEnum(handle, count, charSet, prefixBytes); + public IEnumerable ToStringEnum(int count, CharSet charSet = CharSet.Auto, int prefixBytes = 0) => IsInvalid ? new string[0] : handle.ToStringEnum(count, charSet, prefixBytes); /// /// 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 /// The character set of the strings. /// Number of bytes preceding the array of string pointers. /// An enumerated list of strings. - public IEnumerable ToStringEnum(CharSet charSet = CharSet.Auto, int prefixBytes = 0) => IsInvalid ? new string[0] : InteropExtensions.ToStringEnum(handle, charSet, prefixBytes); + public IEnumerable ToStringEnum(CharSet charSet = CharSet.Auto, int prefixBytes = 0) => IsInvalid ? new string[0] : handle.ToStringEnum(charSet, prefixBytes); /// Marshals data from this block of memory to a newly allocated managed object of the type specified by a generic type parameter. /// The type of the object to which the data is to be copied. This must be a structure. @@ -356,11 +379,6 @@ namespace Vanara.InteropServices return handle.ToStructure(); } -#if DEBUG - [ExcludeFromCodeCoverage] - public string Dump => Size == 0 ? "" : string.Join(" ", ToEnumerable(Size).Select(b => b.ToString("X2")).ToArray()); -#endif - /// When overridden in a derived class, executes the code required to free the handle. /// /// true if the handle is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a