using System.Collections;
using System.Collections.Generic;
namespace Vanara.PInvoke.Collections;
/// Provides a generic enumerator over native memory.
/// The type of the element to extract from memory.
///
///
public class NativeMemoryEnumerator : UntypedNativeMemoryEnumerator, IEnumerator, IEnumerable
{
/// Initializes a new instance of the class.
/// A pointer to the starting address of a specified number of elements in memory.
/// The number of elements to be included in the enumeration.
/// Bytes to skip before reading the first element.
/// If known, the total number of bytes allocated to the native memory in .
/// count
///
public NativeMemoryEnumerator(IntPtr ptr, int length, int prefixBytes = 0, SizeT allocatedBytes = default) : base(ptr, typeof(T), length, prefixBytes, allocatedBytes) { }
/// Gets the element in the collection at the current position of the enumerator.
public new T? Current => (T?)base.Current;
/// Returns an enumerator that iterates through the collection.
/// A that can be used to iterate through the collection.
public new IEnumerator GetEnumerator() => this;
}
/// Provides an enumerator over native memory.
///
///
public class UntypedNativeMemoryEnumerator : IEnumerator, IEnumerable
{
/// The number of allocated bytes.
protected SizeT allocated;
/// The number of elements in the enumeration.
protected int count;
/// The index of the current item. (-2) signifies an error. (-1) means MoveNext has not been called..
protected int index = -1;
/// The number of bytes to skip before reading the first element.
protected int prefix;
/// A pointer to the starting address of a specified number of elements in memory.
protected IntPtr ptr;
/// The size of .
protected SizeT stSize;
/// The type of the element to extract from memory.
protected Type type;
/// Initializes a new instance of the class.
/// A pointer to the starting address of a specified number of elements in memory.
/// The type of the element to extract from memory.
/// The number of elements to be included in the enumeration.
/// Bytes to skip before reading the first element.
/// If known, the total number of bytes allocated to the native memory in .
/// count
/// type
///
public UntypedNativeMemoryEnumerator(IntPtr ptr, Type type, int length, int prefixBytes = 0, SizeT allocatedBytes = default)
{
if (length < 0 || ptr == IntPtr.Zero && length != 0)
throw new ArgumentOutOfRangeException(nameof(length));
if (type is null)
throw new ArgumentNullException(nameof(type));
this.type = type;
this.ptr = ptr;
count = length;
prefix = prefixBytes;
allocated = allocatedBytes == default ? (SizeT)uint.MaxValue : allocatedBytes;
stSize = InteropExtensions.SizeOf(type);
if (allocatedBytes > 0 && stSize * length + prefixBytes > allocatedBytes)
throw new InsufficientMemoryException();
}
/// Gets the element in the collection at the current position of the enumerator.
public virtual object? Current => index >= 0 && index < count
? ptr.ToStructure(type, allocated, prefix + index * stSize, out _)
: throw new ArgumentOutOfRangeException(nameof(index));
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
public virtual void Dispose() { }
/// Returns an enumerator that iterates through a collection.
/// An object that can be used to iterate through the collection.
public IEnumerator GetEnumerator() => this;
/// Advances the enumerator to the next element of the collection.
///
/// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
///
public bool MoveNext()
{
if (++index >= count)
index = -2;
return index >= 0;
}
/// Sets the enumerator to its initial position, which is before the first element in the collection.
public void Reset() => index = -1;
}