1.6 to main #1
@@ -0,0 +1 @@
|
|||||||
|
[Oo]bj/
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -7,6 +7,7 @@
|
|||||||
<li>1.3</li>
|
<li>1.3</li>
|
||||||
<li>1.4</li>
|
<li>1.4</li>
|
||||||
<li>1.5</li>
|
<li>1.5</li>
|
||||||
|
<li>1.6</li>
|
||||||
</supportedVersions>
|
</supportedVersions>
|
||||||
<author>bradson</author>
|
<author>bradson</author>
|
||||||
<modIconPath IgnoreIfNoMatchingField="True">FisheryLib/ModIcon</modIconPath>
|
<modIconPath IgnoreIfNoMatchingField="True">FisheryLib/ModIcon</modIconPath>
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutDir>..\..\1.6\Assemblies\</OutDir>
|
||||||
|
<Copyright>Copyright (c) 2026 Bradson</Copyright>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DefineConstants>DEBUG;V1_5;V1_6</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DefineConstants>V1_5;V1_6</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Krafs.Rimworld.Ref" Version="1.6.*" />
|
||||||
|
<PackageReference Include="Lib.Harmony" Version="2.3.*" ExcludeAssets="runtime" />
|
||||||
|
<Publicize Include="mscorlib:System.Collections.Generic.Dictionary`2._buckets" />
|
||||||
|
<Publicize Include="mscorlib:System.Collections.Generic.Dictionary`2._entries" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -140,21 +140,54 @@ public static class CollectionExtensions
|
|||||||
array.FillUsingEnumerable(enumerable, startIndex, count);
|
array.FillUsingEnumerable(enumerable, startIndex, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static int[]? GetBuckets<TKey, TValue>(Dictionary<TKey, TValue> dictionary)
|
||||||
|
#if V1_6
|
||||||
|
=> dictionary._buckets;
|
||||||
|
#else
|
||||||
|
=> dictionary.buckets;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static Dictionary<TKey, TValue>.Entry[]? GetEntries<TKey, TValue>(Dictionary<TKey, TValue> dictionary)
|
||||||
|
#if V1_6
|
||||||
|
=> dictionary._entries;
|
||||||
|
#else
|
||||||
|
=> dictionary.entries;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static int GetBucketEntryIndex(int[] buckets, int hashCode)
|
||||||
|
#if V1_6
|
||||||
|
=> buckets[hashCode % buckets.Length] - 1;
|
||||||
|
#else
|
||||||
|
=> buckets[hashCode % buckets.Length];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static bool IsValidEntryIndex<T>(int index, T[] entries)
|
||||||
|
=> (uint)index < (uint)entries.Length;
|
||||||
|
|
||||||
public static ref TValue GetReference<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
|
public static ref TValue GetReference<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
|
||||||
{
|
{
|
||||||
if (dictionary.buckets != null)
|
var buckets = GetBuckets(dictionary);
|
||||||
|
if (buckets != null)
|
||||||
{
|
{
|
||||||
|
var entries = GetEntries(dictionary)!;
|
||||||
var keyCode = HashCode.Get(key) & int.MaxValue;
|
var keyCode = HashCode.Get(key) & int.MaxValue;
|
||||||
// HashCode.Get can handle null, & int.MaxValue removes any sign
|
// HashCode.Get can handle null, & int.MaxValue removes any sign
|
||||||
|
|
||||||
var bucket = dictionary.buckets[keyCode % dictionary.buckets.Length];
|
var bucket = GetBucketEntryIndex(buckets, keyCode);
|
||||||
while (bucket >= 0)
|
var collisionCount = 0;
|
||||||
|
while (IsValidEntryIndex(bucket, entries))
|
||||||
{
|
{
|
||||||
ref var entry = ref dictionary.entries[bucket];
|
ref var entry = ref entries[bucket];
|
||||||
if (entry.hashCode == keyCode && entry.key.Equals<TKey>(key))
|
if (entry.hashCode == keyCode && entry.key.Equals<TKey>(key))
|
||||||
return ref entry.value;
|
return ref entry.value;
|
||||||
|
|
||||||
bucket = entry.next;
|
bucket = entry.next;
|
||||||
|
if (collisionCount++ >= entries.Length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,18 +196,23 @@ public static class CollectionExtensions
|
|||||||
|
|
||||||
public static ref TValue GetReference<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, ref TKey key)
|
public static ref TValue GetReference<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, ref TKey key)
|
||||||
{
|
{
|
||||||
if (dictionary.buckets != null)
|
var buckets = GetBuckets(dictionary);
|
||||||
|
if (buckets != null)
|
||||||
{
|
{
|
||||||
|
var entries = GetEntries(dictionary)!;
|
||||||
var keyCode = HashCode.Get(ref key) & int.MaxValue;
|
var keyCode = HashCode.Get(ref key) & int.MaxValue;
|
||||||
|
|
||||||
var bucket = dictionary.buckets[keyCode % dictionary.buckets.Length];
|
var bucket = GetBucketEntryIndex(buckets, keyCode);
|
||||||
while (bucket >= 0)
|
var collisionCount = 0;
|
||||||
|
while (IsValidEntryIndex(bucket, entries))
|
||||||
{
|
{
|
||||||
ref var entry = ref dictionary.entries[bucket];
|
ref var entry = ref entries[bucket];
|
||||||
if (entry.hashCode == keyCode && Equality.EqualsByRef(ref entry.key, ref key))
|
if (entry.hashCode == keyCode && Equality.EqualsByRef(ref entry.key, ref key))
|
||||||
return ref entry.value;
|
return ref entry.value;
|
||||||
|
|
||||||
bucket = entry.next;
|
bucket = entry.next;
|
||||||
|
if (collisionCount++ >= entries.Length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,18 +228,23 @@ public static class CollectionExtensions
|
|||||||
/// <returns>ref TValue or Unsafe.NullRef{TValue}</returns>
|
/// <returns>ref TValue or Unsafe.NullRef{TValue}</returns>
|
||||||
public static ref TValue TryGetReferenceUnsafe<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
|
public static ref TValue TryGetReferenceUnsafe<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
|
||||||
{
|
{
|
||||||
if (dictionary.buckets != null)
|
var buckets = GetBuckets(dictionary);
|
||||||
|
if (buckets != null)
|
||||||
{
|
{
|
||||||
|
var entries = GetEntries(dictionary)!;
|
||||||
var keyCode = HashCode.Get(key) & int.MaxValue;
|
var keyCode = HashCode.Get(key) & int.MaxValue;
|
||||||
|
|
||||||
var bucket = dictionary.buckets[keyCode % dictionary.buckets.Length];
|
var bucket = GetBucketEntryIndex(buckets, keyCode);
|
||||||
while (bucket >= 0)
|
var collisionCount = 0;
|
||||||
|
while (IsValidEntryIndex(bucket, entries))
|
||||||
{
|
{
|
||||||
ref var entry = ref dictionary.entries[bucket];
|
ref var entry = ref entries[bucket];
|
||||||
if (entry.hashCode == keyCode && entry.key.Equals<TKey>(key))
|
if (entry.hashCode == keyCode && entry.key.Equals<TKey>(key))
|
||||||
return ref entry.value;
|
return ref entry.value;
|
||||||
|
|
||||||
bucket = entry.next;
|
bucket = entry.next;
|
||||||
|
if (collisionCount++ >= entries.Length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,18 +253,23 @@ public static class CollectionExtensions
|
|||||||
|
|
||||||
public static ref TValue TryGetReferenceUnsafe<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, ref TKey key)
|
public static ref TValue TryGetReferenceUnsafe<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, ref TKey key)
|
||||||
{
|
{
|
||||||
if (dictionary.buckets != null)
|
var buckets = GetBuckets(dictionary);
|
||||||
|
if (buckets != null)
|
||||||
{
|
{
|
||||||
|
var entries = GetEntries(dictionary)!;
|
||||||
var keyCode = HashCode.Get(ref key) & int.MaxValue;
|
var keyCode = HashCode.Get(ref key) & int.MaxValue;
|
||||||
|
|
||||||
var bucket = dictionary.buckets[keyCode % dictionary.buckets.Length];
|
var bucket = GetBucketEntryIndex(buckets, keyCode);
|
||||||
while (bucket >= 0)
|
var collisionCount = 0;
|
||||||
|
while (IsValidEntryIndex(bucket, entries))
|
||||||
{
|
{
|
||||||
ref var entry = ref dictionary.entries[bucket];
|
ref var entry = ref entries[bucket];
|
||||||
if (entry.hashCode == keyCode && Equality.EqualsByRef(ref entry.key, ref key))
|
if (entry.hashCode == keyCode && Equality.EqualsByRef(ref entry.key, ref key))
|
||||||
return ref entry.value;
|
return ref entry.value;
|
||||||
|
|
||||||
bucket = entry.next;
|
bucket = entry.next;
|
||||||
|
if (collisionCount++ >= entries.Length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,18 +278,23 @@ public static class CollectionExtensions
|
|||||||
|
|
||||||
public static TValue? TryGetValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, ref TKey key)
|
public static TValue? TryGetValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, ref TKey key)
|
||||||
{
|
{
|
||||||
if (dictionary.buckets != null)
|
var buckets = GetBuckets(dictionary);
|
||||||
|
if (buckets != null)
|
||||||
{
|
{
|
||||||
|
var entries = GetEntries(dictionary)!;
|
||||||
var keyCode = HashCode.Get(ref key) & int.MaxValue;
|
var keyCode = HashCode.Get(ref key) & int.MaxValue;
|
||||||
|
|
||||||
var bucket = dictionary.buckets[keyCode % dictionary.buckets.Length];
|
var bucket = GetBucketEntryIndex(buckets, keyCode);
|
||||||
while (bucket >= 0)
|
var collisionCount = 0;
|
||||||
|
while (IsValidEntryIndex(bucket, entries))
|
||||||
{
|
{
|
||||||
ref var entry = ref dictionary.entries[bucket];
|
ref var entry = ref entries[bucket];
|
||||||
if (entry.hashCode == keyCode && Equality.EqualsByRef(ref entry.key, ref key))
|
if (entry.hashCode == keyCode && Equality.EqualsByRef(ref entry.key, ref key))
|
||||||
return entry.value;
|
return entry.value;
|
||||||
|
|
||||||
bucket = entry.next;
|
bucket = entry.next;
|
||||||
|
if (collisionCount++ >= entries.Length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,18 +304,23 @@ public static class CollectionExtensions
|
|||||||
[return: MaybeNull]
|
[return: MaybeNull]
|
||||||
public static TValue TryGetValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
|
public static TValue TryGetValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
|
||||||
{
|
{
|
||||||
if (dictionary.buckets != null)
|
var buckets = GetBuckets(dictionary);
|
||||||
|
if (buckets != null)
|
||||||
{
|
{
|
||||||
|
var entries = GetEntries(dictionary)!;
|
||||||
var keyCode = HashCode.Get(key) & int.MaxValue;
|
var keyCode = HashCode.Get(key) & int.MaxValue;
|
||||||
|
|
||||||
var bucket = dictionary.buckets[keyCode % dictionary.buckets.Length];
|
var bucket = GetBucketEntryIndex(buckets, keyCode);
|
||||||
while (bucket >= 0)
|
var collisionCount = 0;
|
||||||
|
while (IsValidEntryIndex(bucket, entries))
|
||||||
{
|
{
|
||||||
ref var entry = ref dictionary.entries[bucket];
|
ref var entry = ref entries[bucket];
|
||||||
if (entry.hashCode == keyCode && entry.key.Equals<TKey>(key))
|
if (entry.hashCode == keyCode && entry.key.Equals<TKey>(key))
|
||||||
return entry.value;
|
return entry.value;
|
||||||
|
|
||||||
bucket = entry.next;
|
bucket = entry.next;
|
||||||
|
if (collisionCount++ >= entries.Length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,16 +334,21 @@ public static class CollectionExtensions
|
|||||||
var keyCode = HashCode.Get(key) & int.MaxValue;
|
var keyCode = HashCode.Get(key) & int.MaxValue;
|
||||||
|
|
||||||
StartOfLookup:
|
StartOfLookup:
|
||||||
if (dictionary.buckets != null)
|
var buckets = GetBuckets(dictionary);
|
||||||
|
if (buckets != null)
|
||||||
{
|
{
|
||||||
var bucket = dictionary.buckets[keyCode % dictionary.buckets.Length];
|
var entries = GetEntries(dictionary)!;
|
||||||
while (bucket >= 0)
|
var bucket = GetBucketEntryIndex(buckets, keyCode);
|
||||||
|
var collisionCount = 0;
|
||||||
|
while (IsValidEntryIndex(bucket, entries))
|
||||||
{
|
{
|
||||||
ref var entry = ref dictionary.entries[bucket];
|
ref var entry = ref entries[bucket];
|
||||||
if (entry.hashCode == keyCode && entry.key.Equals<TKey>(key))
|
if (entry.hashCode == keyCode && entry.key.Equals<TKey>(key))
|
||||||
return ref entry.value;
|
return ref entry.value;
|
||||||
|
|
||||||
bucket = entry.next;
|
bucket = entry.next;
|
||||||
|
if (collisionCount++ >= entries.Length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,16 +363,21 @@ public static class CollectionExtensions
|
|||||||
var keyCode = HashCode.Get(ref key) & int.MaxValue;
|
var keyCode = HashCode.Get(ref key) & int.MaxValue;
|
||||||
|
|
||||||
StartOfLookup:
|
StartOfLookup:
|
||||||
if (dictionary.buckets != null)
|
var buckets = GetBuckets(dictionary);
|
||||||
|
if (buckets != null)
|
||||||
{
|
{
|
||||||
var bucket = dictionary.buckets[keyCode % dictionary.buckets.Length];
|
var entries = GetEntries(dictionary)!;
|
||||||
while (bucket >= 0)
|
var bucket = GetBucketEntryIndex(buckets, keyCode);
|
||||||
|
var collisionCount = 0;
|
||||||
|
while (IsValidEntryIndex(bucket, entries))
|
||||||
{
|
{
|
||||||
ref var entry = ref dictionary.entries[bucket];
|
ref var entry = ref entries[bucket];
|
||||||
if (entry.hashCode == keyCode && Equality.EqualsByRef(ref entry.key, ref key))
|
if (entry.hashCode == keyCode && Equality.EqualsByRef(ref entry.key, ref key))
|
||||||
return ref entry.value;
|
return ref entry.value;
|
||||||
|
|
||||||
bucket = entry.next;
|
bucket = entry.next;
|
||||||
|
if (collisionCount++ >= entries.Length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,16 +420,21 @@ public static class CollectionExtensions
|
|||||||
var keyCode = HashCode.Get(key) & int.MaxValue;
|
var keyCode = HashCode.Get(key) & int.MaxValue;
|
||||||
|
|
||||||
StartOfLookup:
|
StartOfLookup:
|
||||||
if (dictionary.buckets != null)
|
var buckets = GetBuckets(dictionary);
|
||||||
|
if (buckets != null)
|
||||||
{
|
{
|
||||||
var bucket = dictionary.buckets[keyCode % dictionary.buckets.Length];
|
var entries = GetEntries(dictionary)!;
|
||||||
while (bucket >= 0)
|
var bucket = GetBucketEntryIndex(buckets, keyCode);
|
||||||
|
var collisionCount = 0;
|
||||||
|
while (IsValidEntryIndex(bucket, entries))
|
||||||
{
|
{
|
||||||
ref var entry = ref dictionary.entries[bucket];
|
ref var entry = ref entries[bucket];
|
||||||
if (entry.hashCode == keyCode && entry.key.Equals<TKey>(key))
|
if (entry.hashCode == keyCode && entry.key.Equals<TKey>(key))
|
||||||
return entry.value;
|
return entry.value;
|
||||||
|
|
||||||
bucket = entry.next;
|
bucket = entry.next;
|
||||||
|
if (collisionCount++ >= entries.Length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,16 +449,21 @@ public static class CollectionExtensions
|
|||||||
var keyCode = HashCode.Get(ref key) & int.MaxValue;
|
var keyCode = HashCode.Get(ref key) & int.MaxValue;
|
||||||
|
|
||||||
StartOfLookup:
|
StartOfLookup:
|
||||||
if (dictionary.buckets != null)
|
var buckets = GetBuckets(dictionary);
|
||||||
|
if (buckets != null)
|
||||||
{
|
{
|
||||||
var bucket = dictionary.buckets[keyCode % dictionary.buckets.Length];
|
var entries = GetEntries(dictionary)!;
|
||||||
while (bucket >= 0)
|
var bucket = GetBucketEntryIndex(buckets, keyCode);
|
||||||
|
var collisionCount = 0;
|
||||||
|
while (IsValidEntryIndex(bucket, entries))
|
||||||
{
|
{
|
||||||
ref var entry = ref dictionary.entries[bucket];
|
ref var entry = ref entries[bucket];
|
||||||
if (entry.hashCode == keyCode && Equality.EqualsByRef(ref entry.key, ref key))
|
if (entry.hashCode == keyCode && Equality.EqualsByRef(ref entry.key, ref key))
|
||||||
return entry.value;
|
return entry.value;
|
||||||
|
|
||||||
bucket = entry.next;
|
bucket = entry.next;
|
||||||
|
if (collisionCount++ >= entries.Length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,12 +478,15 @@ public static class CollectionExtensions
|
|||||||
var result = true;
|
var result = true;
|
||||||
|
|
||||||
StartOfLookup:
|
StartOfLookup:
|
||||||
if (dictionary.buckets != null)
|
var buckets = GetBuckets(dictionary);
|
||||||
|
if (buckets != null)
|
||||||
{
|
{
|
||||||
var bucket = dictionary.buckets[keyCode % dictionary.buckets.Length];
|
var entries = GetEntries(dictionary)!;
|
||||||
while (bucket >= 0)
|
var bucket = GetBucketEntryIndex(buckets, keyCode);
|
||||||
|
var collisionCount = 0;
|
||||||
|
while (IsValidEntryIndex(bucket, entries))
|
||||||
{
|
{
|
||||||
ref var entry = ref dictionary.entries[bucket];
|
ref var entry = ref entries[bucket];
|
||||||
if (entry.hashCode == keyCode && entry.key.Equals<TKey>(key))
|
if (entry.hashCode == keyCode && entry.key.Equals<TKey>(key))
|
||||||
{
|
{
|
||||||
value = entry.value;
|
value = entry.value;
|
||||||
@@ -413,6 +494,8 @@ public static class CollectionExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
bucket = entry.next;
|
bucket = entry.next;
|
||||||
|
if (collisionCount++ >= entries.Length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,7 +510,7 @@ public static class CollectionExtensions
|
|||||||
Guard.IsNotNull(dictionary);
|
Guard.IsNotNull(dictionary);
|
||||||
Guard.IsNotNull(predicate);
|
Guard.IsNotNull(predicate);
|
||||||
|
|
||||||
var entries = dictionary.entries;
|
var entries = GetEntries(dictionary);
|
||||||
if (entries is null)
|
if (entries is null)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -653,13 +736,13 @@ public static class CollectionExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T UnsafeLoad<T>(this T[] array, int index) => Array.UnsafeLoad(array, index);
|
public static T UnsafeLoad<T>(this T[] array, int index) => array[index];
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void UnsafeStore<T>(this T[] array, int index, T value) => Array.UnsafeStore(array, index, value);
|
public static void UnsafeStore<T>(this T[] array, int index, T value) => array[index] = value;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static TTo UnsafeCast<TFrom, TTo>(this TFrom obj) => Array.UnsafeMov<TFrom, TTo>(obj);
|
public static TTo UnsafeCast<TFrom, TTo>(this TFrom obj) => Unsafe.As<TFrom, TTo>(ref obj);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void AddRangeFast<T>(this List<T> list, T[] range)
|
public static void AddRangeFast<T>(this List<T> list, T[] range)
|
||||||
@@ -687,8 +770,7 @@ public static class CollectionExtensions
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
list.EnsureCapacity(list._size + value.Length);
|
list.EnsureCapacity(list._size + value.Length);
|
||||||
UnsafeBlockCopy(ref value.m_firstChar,
|
value.CopyTo(0, list._items, list._size, value.Length);
|
||||||
ref list._items[list._size], value.Length);
|
|
||||||
|
|
||||||
list._size += value.Length;
|
list._size += value.Length;
|
||||||
list._version++;
|
list._version++;
|
||||||
@@ -764,8 +846,8 @@ public static class CollectionExtensions
|
|||||||
|
|
||||||
public static unsafe uint GetSizeEstimate<TKey, TValue>(this Dictionary<TKey, TValue> dictionary)
|
public static unsafe uint GetSizeEstimate<TKey, TValue>(this Dictionary<TKey, TValue> dictionary)
|
||||||
=> dictionary.GetType().ComputeManagedObjectSizeEstimate()
|
=> dictionary.GetType().ComputeManagedObjectSizeEstimate()
|
||||||
+ ((uint)sizeof(Dictionary<TKey, TValue>.Entry) * (uint)(dictionary.entries?.Length ?? 0))
|
+ ((uint)sizeof(Dictionary<TKey, TValue>.Entry) * (uint)(GetEntries(dictionary)?.Length ?? 0))
|
||||||
+ (sizeof(int) * (uint)(dictionary.buckets?.Length ?? 0));
|
+ (sizeof(int) * (uint)(GetBuckets(dictionary)?.Length ?? 0));
|
||||||
|
|
||||||
internal static unsafe uint ComputeManagedObjectSizeEstimate(this Type type)
|
internal static unsafe uint ComputeManagedObjectSizeEstimate(this Type type)
|
||||||
{
|
{
|
||||||
@@ -857,4 +939,4 @@ public static class CollectionExtensions
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public override IList New(IEnumerable enumerable) => new List<T>((IEnumerable<T>)enumerable);
|
public override IList New(IEnumerable enumerable) => new List<T>((IEnumerable<T>)enumerable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Zetrith.Prepatcher" Version="1.*" />
|
<PackageReference Include="Zetrith.Prepatcher" Version="1.*" />
|
||||||
<PackageReference Include="PolySharp" Version="1.*" />
|
<PackageReference Include="PolySharp" Version="1.*" />
|
||||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.*" />
|
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.2" />
|
||||||
<PackageReference Include="Krafs.Publicizer" Version="2.*" />
|
<PackageReference Include="Krafs.Publicizer" Version="2.*" />
|
||||||
|
|
||||||
<Publicize Include="Assembly-CSharp;0Harmony" IncludeVirtualMembers="false" />
|
<Publicize Include="Assembly-CSharp;0Harmony" IncludeVirtualMembers="false" />
|
||||||
@@ -90,4 +90,4 @@
|
|||||||
<PackagePath />
|
<PackagePath />
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ VisualStudioVersion = 17.1.32120.378
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "1.5", "1.5.csproj", "{B5B38CBB-F8EE-451E-A05B-9ED9B03784D2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "1.5", "1.5.csproj", "{B5B38CBB-F8EE-451E-A05B-9ED9B03784D2}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "1.6", "1.6.csproj", "{87022FD2-7E2D-45E4-BFE2-8E445B46DF08}"
|
||||||
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "1.4", "1.4.csproj", "{BE85EB31-71CD-443C-8C93-20E2B7F3F549}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "1.4", "1.4.csproj", "{BE85EB31-71CD-443C-8C93-20E2B7F3F549}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "1.3", "1.3.csproj", "{FC5FB1F4-626D-4895-AE5E-922DFE1AE120}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "1.3", "1.3.csproj", "{FC5FB1F4-626D-4895-AE5E-922DFE1AE120}"
|
||||||
@@ -21,6 +23,10 @@ Global
|
|||||||
{B5B38CBB-F8EE-451E-A05B-9ED9B03784D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{B5B38CBB-F8EE-451E-A05B-9ED9B03784D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{B5B38CBB-F8EE-451E-A05B-9ED9B03784D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{B5B38CBB-F8EE-451E-A05B-9ED9B03784D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B5B38CBB-F8EE-451E-A05B-9ED9B03784D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
{B5B38CBB-F8EE-451E-A05B-9ED9B03784D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{87022FD2-7E2D-45E4-BFE2-8E445B46DF08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{87022FD2-7E2D-45E4-BFE2-8E445B46DF08}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{87022FD2-7E2D-45E4-BFE2-8E445B46DF08}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{87022FD2-7E2D-45E4-BFE2-8E445B46DF08}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{BE85EB31-71CD-443C-8C93-20E2B7F3F549}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{BE85EB31-71CD-443C-8C93-20E2B7F3F549}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{BE85EB31-71CD-443C-8C93-20E2B7F3F549}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{BE85EB31-71CD-443C-8C93-20E2B7F3F549}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{BE85EB31-71CD-443C-8C93-20E2B7F3F549}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{BE85EB31-71CD-443C-8C93-20E2B7F3F549}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
|||||||
@@ -49,7 +49,13 @@ public abstract class SingletonFactory<T_base> where T_base : notnull
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static T_base GetInternal(Type type)
|
private static T_base GetInternal(Type type)
|
||||||
=> _instances.GetOrAdd(type, static type => (T_base)Activator.CreateInstance(type, true));
|
{
|
||||||
|
if (_instances.TryGetValue(type, out var existing))
|
||||||
|
return existing;
|
||||||
|
|
||||||
|
var instance = _instances.GetOrAdd(type, static type => (T_base)Activator.CreateInstance(type, true));
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly ConcurrentDictionary<Type, T_base> _instances = new();
|
private static readonly ConcurrentDictionary<Type, T_base> _instances = new();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace FisheryLib;
|
||||||
|
|
||||||
|
internal static class SpanCompatExtensions
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref T DangerousGetPinnableReference<T>(this Span<T> span)
|
||||||
|
{
|
||||||
|
if (span.Length == 0)
|
||||||
|
return ref Unsafe.AsRef<T>((void*)1);
|
||||||
|
|
||||||
|
return ref span[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref T DangerousGetPinnableReference<T>(this ReadOnlySpan<T> span)
|
||||||
|
{
|
||||||
|
if (span.Length == 0)
|
||||||
|
return ref Unsafe.AsRef<T>((void*)1);
|
||||||
|
|
||||||
|
return ref Unsafe.AsRef(in MemoryMarshal.GetReference(span));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user