using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; namespace Foodsoft.Alpm { public class CachePackageList : IPackageList, ICollection { private readonly Database _db; private readonly IntPtr _listPtr; private readonly SafeDatabaseHandle _parentHandle; internal CachePackageList(IntPtr listPtr, SafeDatabaseHandle parentHandle, Database db) { _parentHandle = parentHandle; _listPtr = listPtr; _db = db; } public bool Contains(CachePackage item) { var name = item.Name; return _parentHandle.UseHandle(_listPtr, list => { for (; list != IntPtr.Zero; list = Detail.ListNext(list)) if (name == alpm.alpm_pkg_get_name(list)) return true; return false; }); } public void CopyTo(CachePackage[] array, int arrayIndex) { _parentHandle.UseHandle(_listPtr, list => { for (; list != IntPtr.Zero; list = Detail.ListNext(list)) array[arrayIndex++] = new CachePackage( new SafeCachePackageHandle(Detail.ListData(list), _parentHandle), _db); return 0; }); } public void Add(CachePackage item) { throw new NotSupportedException(); } public bool Remove(CachePackage item) { throw new NotSupportedException(); } public void Clear() { throw new NotSupportedException(); } public int Count => _listPtr == IntPtr.Zero ? 0 : _parentHandle.UseHandle(_listPtr, list => (int) alpm.alpm_list_count(list)); public bool IsReadOnly => true; [PrePrepareMethod] public IEnumerator GetEnumerator() { if (_listPtr == IntPtr.Zero) yield break; var release = false; RuntimeHelpers.PrepareConstrainedRegions(); try { _parentHandle.DangerousAddRef(ref release); if (!release) throw new ObjectDisposedException(_parentHandle.GetType().FullName); for (var list = _listPtr; list != IntPtr.Zero; list = Detail.ListNext(list)) yield return new CachePackage( new SafeCachePackageHandle(Detail.ListData(list), _parentHandle), _db); } finally { if (release) _parentHandle.DangerousRelease(); } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public CachePackage? FindSatisfier(string depString) { return _parentHandle.UseHandle(_listPtr, list => { var pkgPtr = alpm.alpm_find_satisfier(list, depString); return pkgPtr != IntPtr.Zero ? new CachePackage(new SafeCachePackageHandle(pkgPtr, _parentHandle), _db) : null; }); } } }