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(this SafeHandle handle, IntPtr ptr, Func 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(this SafeHandle handle, Func op) { return handle.UseHandle(handle.DangerousGetHandle(), op); } internal static void SetStringCollection(IEnumerable value, SafeAlpmHandle safeAlpmHandle, Func op) { foreach (var s in value) if (op(s) < 0) throw new AlpmException(safeAlpmHandle); } internal static unsafe TResult UseStringList(IEnumerable strings, Func 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.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 f) { var err = f(); if (err != 0) throw new AlpmException(alpmHandle); } internal static T WrapErrorOut(SafeAlpmHandle alpmHandle, THandle handle, OutFunc f) { var err = f(handle, out var result); if (err != 0) throw new AlpmException(alpmHandle); return result; } internal static void WrapErrorIn(SafeAlpmHandle alpmHandle, THandle handle, T value, Func f) { var err = f(handle, value); if (err != 0) throw new AlpmException(alpmHandle); } internal static bool WrapErrorBool(SafeAlpmHandle h, Func f) { var err = f(); if (err < 0) throw new AlpmException(h); return err == 0; } internal delegate int OutFunc(THandle handle, out T result); } }