129 lines
3.7 KiB
C#
129 lines
3.7 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace Foodsoft.Alpm
|
|
{
|
|
internal class CollectionWrapper<TImpl, TElement> : ICollection<TElement> where TImpl : struct,
|
|
IItemsAccessor<TElement>
|
|
{
|
|
private TImpl _impl;
|
|
|
|
public CollectionWrapper(TImpl impl)
|
|
{
|
|
_impl = impl;
|
|
}
|
|
|
|
private static unsafe IntPtr ListNext(IntPtr list) => ((alpm_list_t*) list)->next;
|
|
private static unsafe IntPtr ListData(IntPtr list) => ((alpm_list_t*) list)->data;
|
|
public IEnumerator<TElement> GetEnumerator()
|
|
{
|
|
var safeAlpmHandle = _impl.SafeAlpmHandle;
|
|
var release = false;
|
|
|
|
RuntimeHelpers.PrepareConstrainedRegions();
|
|
try
|
|
{
|
|
safeAlpmHandle.DangerousAddRef(ref release);
|
|
if (!release) throw new ObjectDisposedException(_impl.GetType().FullName);
|
|
for (var list = _impl.GetItems(); list != IntPtr.Zero; list = ListNext(list))
|
|
{
|
|
yield return _impl.PtrToItem(ListData(list));
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (release)
|
|
safeAlpmHandle.DangerousRelease();
|
|
}
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
|
|
public void Add(TElement item)
|
|
{
|
|
_impl.AddItem(item);
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
_impl.SetItems(IntPtr.Zero);
|
|
}
|
|
|
|
|
|
public bool Contains(TElement item)
|
|
{
|
|
var safeAlpmHandle = _impl.SafeAlpmHandle;
|
|
var release = false;
|
|
RuntimeHelpers.PrepareConstrainedRegions();
|
|
try
|
|
{
|
|
safeAlpmHandle.DangerousAddRef(ref release);
|
|
return _impl.FindItem(item) != IntPtr.Zero;
|
|
}
|
|
finally
|
|
{
|
|
if (release)
|
|
safeAlpmHandle.DangerousRelease();
|
|
}
|
|
}
|
|
|
|
public void CopyTo(TElement[] array, int arrayIndex)
|
|
{
|
|
var safeAlpmHandle = _impl.SafeAlpmHandle;
|
|
var release = false;
|
|
RuntimeHelpers.PrepareConstrainedRegions();
|
|
try
|
|
{
|
|
safeAlpmHandle.DangerousAddRef(ref release);
|
|
var intPtr = _impl.GetItems();
|
|
unsafe
|
|
{
|
|
for (var list = (alpm_list_t*) intPtr; list != null; list = alpm.alpm_list_next(list))
|
|
{
|
|
array[arrayIndex++] = _impl.PtrToItem(list->data);
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (release)
|
|
safeAlpmHandle.DangerousRelease();
|
|
}
|
|
}
|
|
|
|
public bool Remove(TElement item)
|
|
{
|
|
var err = _impl.RemoveItem(item);
|
|
if (err < 0)
|
|
{
|
|
throw new Exception(alpm.alpm_errno(_impl.SafeAlpmHandle));
|
|
}
|
|
|
|
return err == 0;
|
|
}
|
|
|
|
public int Count
|
|
{
|
|
get
|
|
{
|
|
var safeAlpmHandle = _impl.SafeAlpmHandle;
|
|
var release = false;
|
|
RuntimeHelpers.PrepareConstrainedRegions();
|
|
try
|
|
{
|
|
safeAlpmHandle.DangerousAddRef(ref release);
|
|
return (int) alpm.alpm_list_count(_impl.GetItems());
|
|
}
|
|
finally
|
|
{
|
|
if (release)
|
|
safeAlpmHandle.DangerousRelease();
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool IsReadOnly => false;
|
|
}
|
|
} |