using System; using System.Collections.Generic; using System.Linq; using Vanara.Extensions; using Vanara.PInvoke; namespace Vanara.InteropServices { /// A safe unmanaged linked list of structures allocated on the global heap. /// The type of the list elements. /// The type of memory allocation to use. public class SafeNativeLinkedList : SafeNativeListBase where TElem : struct where TMem : IMemoryMethods, new() { /// Initializes a new instance of the class. /// The handle. /// The size of memory allocated to the handle, in bytes. /// if set to true if this class is responsible for freeing the memory on disposal. /// The method to use to get the next item in the list. public SafeNativeLinkedList(IntPtr ptr, SizeT size, bool ownsHandle, Func getNextMethod) : base(ptr, size, ownsHandle) { GetNextMethod = getNextMethod; } /// Initializes a new instance of the class. /// The number of bytes to allocate for this new array. /// The method to use to get the next item in the list. public SafeNativeLinkedList(SizeT byteCount, Func getNextMethod) : base(byteCount) { GetNextMethod = getNextMethod; } /// Initializes a new instance of the class. /// The handle. /// The size of memory allocated to the handle, in bytes. /// if set to true if this class is responsible for freeing the memory on disposal. public SafeNativeLinkedList(IntPtr ptr, SizeT size, bool ownsHandle) : base(ptr, size, ownsHandle) { } /// Initializes a new instance of the class. /// The number of bytes to allocate for this new array. public SafeNativeLinkedList(SizeT byteCount) : base(byteCount) { } /// Gets or sets the method to use to get the next item in the list. /// The method to get the next value. It should return if there are no more items. public Func GetNextMethod { get; set; } /// Gets or sets the method to use to get the next item in the list. /// The method to get the next value. It should return if there are no more items. public Func GetNextSizeMethod { get; set; } /// Enumerates the elements. /// An enumeration of values from the pointer. protected override IEnumerable Items => GetNextMethod != null ? handle.LinkedListToIEnum(GetNextMethod) : (GetNextSizeMethod != null ? handle.LinkedListToIEnum(GetNextSizeMethod, Size) : Enumerable.Empty()); /* /// /// Gets the pointers to the items in the linked list. This is useful when marshaling those values may invalidate internal pointers. /// /// An array of pointers to the items. public unsafe TElem*[] GetUnsafeItems() { var ret = new List(); for (byte* pCurrent = (byte*)handle, pEnd = pCurrent + Size; pCurrent < pEnd && pCurrent != null;) { ret.Add((IntPtr)pCurrent); pCurrent = GetNextMethod != null ? (byte*)GetNextMethod(*(TElem*)pCurrent) : (GetNextSizeMethod != null ? pCurrent + GetNextSizeMethod(*(TElem*)pCurrent) : null); } var arr = new TElem*[ret.Count]; for (int i = 0; i < ret.Count; i++) arr[i] = (TElem*)ret[i]; return arr; } */ } }