134 lines
4.4 KiB
C#
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);
|
|
}
|
|
} |