305 lines
8.0 KiB
C#
305 lines
8.0 KiB
C#
// Copyright (c) 2023 bradson
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq;
|
|
using Mono.Collections.Generic;
|
|
|
|
namespace PerformanceFish.Utility;
|
|
|
|
public static class CollectionExtensions
|
|
{
|
|
public static bool Any<T>(this T[] array, Predicate<T> predicate)
|
|
{
|
|
var length = array.Length;
|
|
return length != 0 && Any(ref array[0], predicate, (nuint)length);
|
|
}
|
|
|
|
// overlaps with method in GenCollection
|
|
// public static bool Any<T>(this List<T> list, Predicate<T> predicate)
|
|
// {
|
|
// var count = list.Count;
|
|
// return count != 0 && Any(ref list._items[0], predicate, count);
|
|
// }
|
|
|
|
public static bool Any<T>(this IList<T> iList, Predicate<T> predicate)
|
|
{
|
|
var count = iList.Count;
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
if (predicate(iList[i]))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static unsafe bool Any<T>(this T[] array, delegate*<T, bool> predicate)
|
|
{
|
|
var length = array.Length;
|
|
return length != 0 && Any(ref array[0], predicate, (nuint)length);
|
|
}
|
|
|
|
public static unsafe bool Any<T>(this List<T> list, delegate*<T, bool> predicate)
|
|
{
|
|
var count = list.Count;
|
|
return count != 0 && Any(ref list._items[0], predicate, (nuint)count);
|
|
}
|
|
|
|
public static bool ExistsAndNotNull<T>(this List<T>? list, Predicate<T> match)
|
|
{
|
|
if (list is null)
|
|
return false;
|
|
|
|
var count = list.Count;
|
|
return count != 0 && Any(ref list._items[0], match, (nuint)count);
|
|
}
|
|
|
|
public static bool Contains<T>(this T[] array, T item)
|
|
{
|
|
var length = array.Length;
|
|
return length != 0 && Contains(ref array[0], item, (nuint)length);
|
|
}
|
|
|
|
public static bool Contains<T>(this IList<T> iList, T item)
|
|
{
|
|
var count = iList.Count;
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
if (iList[i].Equals<T>(item))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static T? FirstOrDefault<T>(this T[] array, Predicate<T> predicate)
|
|
{
|
|
var length = array.Length;
|
|
return length == 0 ? default : FirstOrDefault(ref array[0], predicate, (nuint)length);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static T? FirstOrDefaultFast<T>(this List<T> list, Predicate<T> predicate)
|
|
{
|
|
var count = list.Count;
|
|
return count == 0 ? default : FirstOrDefault(ref list._items[0], predicate, (nuint)count);
|
|
}
|
|
|
|
public static T? FirstOrDefault<T>(this IList<T> iList, Predicate<T> predicate)
|
|
{
|
|
var count = iList.Count;
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
if (predicate(iList[i]))
|
|
return iList[i];
|
|
}
|
|
|
|
return default;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static unsafe T? FirstOrDefault<T>(this T[] array, delegate*<T, bool> predicate)
|
|
{
|
|
var length = array.Length;
|
|
return length == 0 ? default : FirstOrDefault(ref array[0], predicate, (nuint)length);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static unsafe T? FirstOrDefault<T>(this List<T> list, delegate*<T, bool> predicate)
|
|
{
|
|
var count = list.Count;
|
|
return count == 0 ? default : FirstOrDefault(ref list._items[0], predicate, (nuint)count);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static T? FirstOrDefault<T>(this T[] array) => array.Length != 0 ? array[0] : default;
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static T? FirstOrDefault<T>(this List<T> list) => list.Count != 0 ? list[0] : default;
|
|
|
|
public static T? FirstOrDefault<T>(this IList<T> iList) => iList.Count != 0 ? iList[0] : default;
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static T First<T>(this T[] array, Predicate<T> predicate)
|
|
{
|
|
var length = array.Length;
|
|
return length == 0 ? ThrowForNoElements<T>() : First(ref array[0], predicate, (nuint)length);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static T First<T>(this List<T> list, Predicate<T> predicate)
|
|
{
|
|
var count = list.Count;
|
|
return count == 0 ? ThrowForNoElements<T>() : First(ref list._items[0], predicate, (nuint)count);
|
|
}
|
|
|
|
public static T First<T>(this IList<T> iList, Predicate<T> predicate)
|
|
{
|
|
var count = iList.Count;
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
if (predicate(iList[i]))
|
|
return iList[i];
|
|
}
|
|
|
|
return ThrowForNoElements<T>();
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static unsafe T First<T>(this T[] array, delegate*<T, bool> predicate)
|
|
{
|
|
var length = array.Length;
|
|
return length == 0 ? ThrowForNoElements<T>() : First(ref array[0], predicate, (nuint)length);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static unsafe T First<T>(this List<T> list, delegate*<T, bool> predicate)
|
|
{
|
|
var count = list.Count;
|
|
return count == 0 ? ThrowForNoElements<T>() : First(ref list._items[0], predicate, (nuint)count);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static T First<T>(this T[] array) => array.Length != 0 ? array[0] : ThrowForNoElements<T>();
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static T First<T>(this List<T> list) => list.Count != 0 ? list[0] : ThrowForNoElements<T>();
|
|
|
|
public static T First<T>(this IList<T> iList) => iList.Count != 0 ? iList[0] : ThrowForNoElements<T>();
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static unsafe bool Any<T>(ref T reference, Predicate<T> predicate, nuint length)
|
|
{
|
|
nuint i = 0;
|
|
length *= (nuint)sizeof(T);
|
|
|
|
do
|
|
{
|
|
if (predicate(Unsafe.AddByteOffset(ref reference, i)))
|
|
return true;
|
|
|
|
i += (nuint)sizeof(T);
|
|
}
|
|
while (i < length);
|
|
|
|
return false;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static unsafe bool Any<T>(ref T reference, delegate*<T, bool> predicate, nuint length)
|
|
{
|
|
nuint i = 0;
|
|
length *= (nuint)sizeof(T);
|
|
|
|
do
|
|
{
|
|
if (predicate(Unsafe.AddByteOffset(ref reference, i)))
|
|
return true;
|
|
|
|
i += (nuint)sizeof(T);
|
|
}
|
|
while (i < length);
|
|
|
|
return false;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static unsafe bool Contains<T>(ref T reference, T item, nuint length)
|
|
{
|
|
nuint i = 0;
|
|
length *= (nuint)sizeof(T);
|
|
|
|
do
|
|
{
|
|
if (Unsafe.AddByteOffset(ref reference, i).Equals<T>(item))
|
|
return true;
|
|
|
|
i += (nuint)sizeof(T);
|
|
}
|
|
while (i < length);
|
|
|
|
return false;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static unsafe T? FirstOrDefault<T>(ref T reference, Predicate<T> predicate, nuint length)
|
|
{
|
|
nuint i = 0;
|
|
length *= (nuint)sizeof(T);
|
|
|
|
do
|
|
{
|
|
if (predicate(Unsafe.AddByteOffset(ref reference, i)))
|
|
return Unsafe.AddByteOffset(ref reference, i);
|
|
|
|
i += (nuint)sizeof(T);
|
|
}
|
|
while (i < length);
|
|
|
|
return default;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static unsafe T First<T>(ref T reference, Predicate<T> predicate, nuint length)
|
|
{
|
|
nuint i = 0;
|
|
length *= (nuint)sizeof(T);
|
|
|
|
do
|
|
{
|
|
if (predicate(Unsafe.AddByteOffset(ref reference, i)))
|
|
return Unsafe.AddByteOffset(ref reference, i);
|
|
|
|
i += (nuint)sizeof(T);
|
|
}
|
|
while (i < length);
|
|
|
|
return ThrowForNoElements<T>();
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static unsafe T? FirstOrDefault<T>(ref T reference, delegate*<T, bool> predicate, nuint length)
|
|
{
|
|
nuint i = 0;
|
|
length *= (nuint)sizeof(T);
|
|
|
|
do
|
|
{
|
|
if (predicate(Unsafe.AddByteOffset(ref reference, i)))
|
|
return Unsafe.AddByteOffset(ref reference, i);
|
|
|
|
i += (nuint)sizeof(T);
|
|
}
|
|
while (i < length);
|
|
|
|
return default;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static unsafe T First<T>(ref T reference, delegate*<T, bool> predicate, nuint length)
|
|
{
|
|
nuint i = 0;
|
|
length *= (nuint)sizeof(T);
|
|
|
|
do
|
|
{
|
|
if (predicate(Unsafe.AddByteOffset(ref reference, i)))
|
|
return Unsafe.AddByteOffset(ref reference, i);
|
|
|
|
i += (nuint)sizeof(T);
|
|
}
|
|
while (i < length);
|
|
|
|
return ThrowForNoElements<T>();
|
|
}
|
|
|
|
public static List<T> AsOrToList<T>(this IEnumerable<T> enumerable) => enumerable as List<T> ?? enumerable.ToList();
|
|
|
|
[DoesNotReturn]
|
|
private static T ThrowForNoElements<T>()
|
|
=> throw new InvalidOperationException("Sequence contains no elements");
|
|
} |