// --------------------------------------------------------------------------------------------------------------------
//
// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
//
//
// Helper utilities for native interop.
//
// --------------------------------------------------------------------------------------------------------------------
namespace HandBrake.Interop.Interop.Helpers
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using HandBrake.Interop.Interop.HbLib;
using HandBrake.Interop.Interop.HbLib.Wrappers.Interfaces;
using HandBrake.Interop.Interop.Providers;
using HandBrake.Interop.Interop.Providers.Interfaces;
///
/// Helper utilities for native interop.
///
internal static class InteropUtilities
{
private static IHbFunctions hbFunctions;
static InteropUtilities()
{
IHbFunctionsProvider hbFunctionsProvider = new HbFunctionsProvider();
hbFunctions = hbFunctionsProvider.GetHbFunctionsWrapper();
}
///
/// Reads the given native structure pointer.
///
/// The type to convert the structure to.
/// The pointer to the native structure.
/// The converted structure.
public static T ToStructureFromPtr(IntPtr structPtr)
{
return (T)Marshal.PtrToStructure(structPtr, typeof(T));
}
///
/// Reads the given native UTF-8 string.
///
/// The pointer to the string.
/// The resulting string.
public static string ToStringFromUtf8Ptr(IntPtr stringPtr)
{
var data = new List();
var ptr = stringPtr;
var offset = 0;
while (true)
{
byte ch = Marshal.ReadByte(ptr, offset++);
if (ch == 0)
{
break;
}
data.Add(ch);
}
return Encoding.UTF8.GetString(data.ToArray());
}
///
/// Creates a pointer to a UTF-8 null-terminated string.
///
///
/// The string to encode.
///
///
/// The .
///
public static IntPtr ToUtf8PtrFromString(string str)
{
byte[] bytes = Encoding.UTF8.GetBytes(str);
IntPtr stringPtr = Marshal.AllocHGlobal(bytes.Length + 1);
var offset = 0;
foreach (byte b in bytes)
{
Marshal.WriteByte(stringPtr, offset, b);
offset++;
}
Marshal.WriteByte(stringPtr, offset, 0);
return stringPtr;
}
///
/// Converts the given native HandBrake list to a managed list.
///
/// The type of structure in the list.
/// The pointer to the native list.
/// The converted managed list.
public static List ToListFromHandBrakeList(this IntPtr listPtr)
{
List returnList = new List();
NativeList nativeList = new NativeList(listPtr);
for (int i = 0; i < nativeList.Count; i++)
{
IntPtr itemPtr = nativeList[i];
returnList.Add(ToStructureFromPtr(itemPtr));
}
return returnList;
}
///
/// Converts the HB list to a managed list of pointers.
///
/// The list to convert.
/// The managed list of pointers.
public static List ToIntPtrList(this IntPtr listPtr)
{
var returnList = new List();
NativeList nativeList = new NativeList(listPtr);
for (int i = 0; i < nativeList.Count; i++)
{
IntPtr itemPtr = nativeList[i];
returnList.Add(itemPtr);
}
return returnList;
}
///
/// Converts the given native array to a managed collection.
///
/// The type of item in the list.
/// The pointer to the array.
/// The number of items in the array.
/// The converted collection.
public static List ToListFromNativeArray(IntPtr arrayPtr, int count)
{
IntPtr currentItem = arrayPtr;
var result = new List();
for (int i = 0; i < count; i++)
{
T nativeEncoder = ToStructureFromPtr(currentItem);
result.Add(nativeEncoder);
currentItem = IntPtr.Add(currentItem, Marshal.SizeOf(typeof(T)));
}
return result;
}
///
/// Takes an array pointer and converts it into a list of strings.
///
/// A pointer to a raw list of strings.
/// The list of strings.
public static List ToStringListFromArrayPtr(IntPtr arrayPtr)
{
if (arrayPtr == IntPtr.Zero)
{
return null;
}
return ToPtrListFromPtr(arrayPtr).Select(ptr => Marshal.PtrToStringAnsi(ptr)).ToList();
}
///
/// Finds all the pointers starting at the given location and puts them in a list. Stops when it finds zero for a pointer.
///
/// The address of the list of pointers.
/// The list of pointers.
public static List ToPtrListFromPtr(IntPtr arrayPtr)
{
var result = new List();
int ptrSize = Marshal.SizeOf(typeof(IntPtr));
IntPtr currentPtr = Marshal.ReadIntPtr(arrayPtr);
for (int i = 0; currentPtr != IntPtr.Zero; i++)
{
result.Add(currentPtr);
currentPtr = Marshal.ReadIntPtr(arrayPtr, (i + 1) * ptrSize);
}
return result;
}
///
/// Creates a native HandBrake list from the given managed list of pointers.
///
/// The managed list to convert.
/// The converted native list.
public static NativeList ToHandBrakeListFromPtrList(List list)
{
NativeList returnList = NativeList.CreateList();
foreach (IntPtr ptr in list)
{
returnList.Add(ptr);
}
return returnList;
}
///
/// Creates a native HandBrake list from the given managed list of structures.
///
/// The type of structures in the list.
/// The managed list to convert.
/// The converted native list.
public static NativeList ToHandBrakeListFromList(List list)
{
NativeList returnList = NativeList.CreateList();
foreach (T item in list)
{
IntPtr itemPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T)));
returnList.AllocatedMemory.Add(itemPtr);
Marshal.StructureToPtr(item, itemPtr, false);
returnList.Add(itemPtr);
}
return returnList;
}
///
/// Reads in a list of objects given an iterator and a conversion function.
///
/// The type of the struct given by the iterator.
/// The object type to convert to.
/// The iterator to use to build the list.
/// The converter to convert from the struct to the object.
/// The list of objects.
public static List ToListFromIterator(Func iterator, Func converter)
{
return ToListFromIterator(iterator).Select(converter).ToList();
}
///
/// Reads in a list of structs given an iterator.
///
/// The type of the struct.
/// The iterator to use to build the list.
/// The list of structs.
public static List ToListFromIterator(Func iterator)
{
var structureList = new List();
IntPtr current = IntPtr.Zero;
current = iterator(current);
while (current != IntPtr.Zero)
{
T encoder = ToStructureFromPtr(current);
structureList.Add(encoder);
current = iterator(current);
}
return structureList;
}
///
/// Closes the given job.
///
/// The pointer to the job.
public static void CloseJob(IntPtr nativeJobPtr)
{
// Create a point to the job pointer first.
IntPtr nativeJobPtrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
// Assign the new pointer to the job pointer and tell HB to clean the job up.
Marshal.WriteIntPtr(nativeJobPtrPtr, nativeJobPtr);
hbFunctions.hb_job_close(nativeJobPtrPtr);
// Free the pointer we used.
Marshal.FreeHGlobal(nativeJobPtrPtr);
}
///
/// Frees all the memory locations in the given list.
///
/// The list of memory locations to free.
public static void FreeMemory(List memoryList)
{
foreach (IntPtr memoryLocation in memoryList)
{
Marshal.FreeHGlobal(memoryLocation);
}
}
}
}