using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using Vanara.Extensions;
using Vanara.InteropServices;
namespace Vanara.PInvoke;
public static partial class Kernel32
{
/// A for memory allocated as moveable HGLOBAL.
///
public class SafeMoveableHGlobalHandle : SafeMemoryHandleExt
{
/// Initializes a new instance of the class.
/// The handle.
/// if set to true if this class is responsible for freeing the memory on disposal.
public SafeMoveableHGlobalHandle(IntPtr handle, bool ownsHandle = true) : base(handle, handle == default ? 0 : GlobalSize(handle), ownsHandle) { }
/// Initializes a new instance of the class.
/// The size of memory to allocate, in bytes.
/// size - The value of this argument must be non-negative
public SafeMoveableHGlobalHandle(SizeT size) : base(size) { }
///
/// Allocates from unmanaged memory to represent an array of pointers and marshals the unmanaged pointers (IntPtr) to the native
/// array equivalent.
///
/// Array of unmanaged pointers
/// SafeMoveableHGlobalHandle object to an native (unmanaged) array of pointers
public SafeMoveableHGlobalHandle(byte[] bytes) : base(bytes?.Length ?? 0)
{
if (Size == 0) return;
CallLocked(p => Marshal.Copy(bytes, 0, p, sz));
}
///
/// Initializes a new instance of the class from a
/// instance, copying all the memory.
///
/// The source memory block.
public SafeMoveableHGlobalHandle(SafeAllocatedMemoryHandle source) : base(source) { }
/// Initializes a new instance of the class.
[ExcludeFromCodeCoverage]
internal SafeMoveableHGlobalHandle() : base(0) { }
/// Represents a NULL memory pointer.
public static SafeMoveableHGlobalHandle Null { get; } = new SafeMoveableHGlobalHandle(IntPtr.Zero, false);
///
/// Allocates from unmanaged memory to represent a structure with a variable length array at the end and marshal these structure
/// elements. It is the callers responsibility to marshal what precedes the trailing array into the unmanaged memory. ONLY
/// structures with attribute StructLayout of LayoutKind.Sequential are supported.
///
/// Type of the trailing array of structures
/// Collection of structure objects
/// Number of bytes preceding the trailing array of structures
/// object to an native (unmanaged) structure with a trail array of structures
public static SafeMoveableHGlobalHandle CreateFromList(IEnumerable values, int prefixBytes = 0) =>
new(InteropExtensions.MarshalToPtr(values, mm.AllocMem, out _, prefixBytes, mm.LockMem, mm.UnlockMem), true);
/// Allocates from unmanaged memory sufficient memory to hold an array of strings.
/// The list of strings.
/// The packing type for the strings.
/// The character set to use for the strings.
/// Number of bytes preceding the trailing strings.
///
/// object to an native (unmanaged) array of strings stored using the model and the character set defined by .
///
public static SafeMoveableHGlobalHandle CreateFromStringList(IEnumerable values, StringListPackMethod packing = StringListPackMethod.Concatenated,
CharSet charSet = CharSet.Auto, int prefixBytes = 0) => new(InteropExtensions.MarshalToPtr(values, packing, mm.AllocMem, out _, charSet, prefixBytes, mm.LockMem, mm.UnlockMem), true);
/// Allocates from unmanaged memory sufficient memory to hold an object of type T.
/// Native type
/// The value.
/// object to an native (unmanaged) memory block the size of T.
public static SafeMoveableHGlobalHandle CreateFromStructure(in T value = default) =>
new(InteropExtensions.MarshalToPtr(value, mm.AllocMem, out _, 0, mm.LockMem, mm.UnlockMem), true);
/// Converts an to a where it owns the reference.
/// The .
/// The result of the conversion.
public static implicit operator HGLOBAL(SafeMoveableHGlobalHandle ptr) => ptr.handle;
/// Converts an to a where it owns the reference.
/// The .
/// The result of the conversion.
public static implicit operator SafeMoveableHGlobalHandle(IntPtr ptr) => new(ptr, true);
/// Runs a delegate method while locking the memory.
/// The output type.
/// The action to perform while memory is locked.
/// The output from the action.
public new T CallLocked(Func action) => base.CallLocked(action);
}
}