Files
DotNetAlpm/Alpm/Detail.cs

134 lines
4.4 KiB
C#

using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
namespace Foodsoft.Alpm
{
[SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")]
internal static class Detail
{
internal static unsafe IntPtr ListNext(IntPtr list)
{
return ((alpm_list_t*) list)->next;
}
internal static unsafe IntPtr ListData(IntPtr list)
{
return ((alpm_list_t*) list)->data;
}
internal static TResult UseHandle<TResult>(this SafeHandle handle, IntPtr ptr, Func<IntPtr, TResult> op)
{
var release = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
handle.DangerousAddRef(ref release);
if (!release) throw new ObjectDisposedException(handle.GetType().FullName);
return op(ptr);
}
finally
{
if (release)
handle.DangerousRelease();
}
}
internal static TResult UseHandle<TResult>(this SafeHandle handle, Func<IntPtr, TResult> op)
{
return handle.UseHandle(handle.DangerousGetHandle(), op);
}
internal static void SetStringCollection(IEnumerable<string> value, SafeAlpmHandle safeAlpmHandle,
Func<string, int> op)
{
foreach (var s in value)
if (op(s) < 0)
throw new AlpmException(safeAlpmHandle);
}
internal static unsafe TResult UseStringList<TResult>(IEnumerable<string> strings, Func<IntPtr, TResult> op)
{
var listPtr = IntPtr.Zero;
var strArray = strings as string[] ?? strings.ToArray();
var numBytes = 0;
foreach (var s in strArray) numBytes += Encoding.UTF8.GetMaxByteCount(s.Length) + 1;
var pool = ArrayPool<byte>.Shared;
byte[] poolBuffer = pool.Rent(numBytes);
try
{
fixed (byte* pBuf = poolBuffer)
{
RuntimeHelpers.PrepareConstrainedRegions();
try
{
var start = 0;
foreach (var s in strArray)
fixed (char* pSrc = s)
{
var pDest = &pBuf[start];
var nbWritten =
Encoding.UTF8.GetBytes(pSrc, s.Length, pDest, poolBuffer.Length - start);
pDest[nbWritten] = 0;
if (alpm.alpm_list_append(ref listPtr, (IntPtr) pDest) == IntPtr.Zero)
throw new AlpmException(ErrorCode.Memory);
start += nbWritten + 1;
}
return op(listPtr);
}
finally
{
alpm.alpm_list_free(listPtr);
}
}
}
finally
{
pool.Return(poolBuffer);
}
}
internal static void WrapError(SafeAlpmHandle alpmHandle, Func<int> f)
{
var err = f();
if (err != 0)
throw new AlpmException(alpmHandle);
}
internal static T WrapErrorOut<THandle, T>(SafeAlpmHandle alpmHandle, THandle handle, OutFunc<THandle, T> f)
{
var err = f(handle, out var result);
if (err != 0)
throw new AlpmException(alpmHandle);
return result;
}
internal static void WrapErrorIn<THandle, T>(SafeAlpmHandle alpmHandle, THandle handle, T value,
Func<THandle, T, int> f)
{
var err = f(handle, value);
if (err != 0)
throw new AlpmException(alpmHandle);
}
internal static bool WrapErrorBool(SafeAlpmHandle h, Func<int> f)
{
var err = f();
if (err < 0) throw new AlpmException(h);
return err == 0;
}
internal delegate int OutFunc<in THandle, T>(THandle handle, out T result);
}
}