Files
2026-08-27 10:56:38 -06:00

1308 lines
31 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis.Collections.Internal;
namespace Microsoft.CodeAnalysis.Collections;
[DebuggerTypeProxy(typeof(IDictionaryDebugView<, >))]
[DebuggerDisplay("Count = {Count}")]
internal sealed class SegmentedDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary, ICollection, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>> where TKey : notnull
{
private struct Entry
{
public uint _hashCode;
public int _next;
public TKey _key;
public TValue _value;
}
public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>, IEnumerator, IDisposable, IDictionaryEnumerator
{
private readonly SegmentedDictionary<TKey, TValue> _dictionary;
private readonly int _version;
private int _index;
private KeyValuePair<TKey, TValue> _current;
private readonly int _getEnumeratorRetType;
internal const int DictEntry = 1;
internal const int KeyValuePair = 2;
public readonly KeyValuePair<TKey, TValue> Current => _current;
readonly object? IEnumerator.Current
{
get
{
if (_index == 0 || _index == _dictionary._count + 1)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen();
}
KeyValuePair<TKey, TValue> current;
if (_getEnumeratorRetType == 1)
{
current = _current;
object key = current.Key;
current = _current;
return new DictionaryEntry(key, current.Value);
}
current = _current;
TKey key2 = current.Key;
current = _current;
return new KeyValuePair<TKey, TValue>(key2, current.Value);
}
}
readonly DictionaryEntry IDictionaryEnumerator.Entry
{
get
{
if (_index == 0 || _index == _dictionary._count + 1)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen();
}
KeyValuePair<TKey, TValue> current = _current;
object key = current.Key;
current = _current;
return new DictionaryEntry(key, current.Value);
}
}
readonly object IDictionaryEnumerator.Key
{
get
{
if (_index == 0 || _index == _dictionary._count + 1)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen();
}
KeyValuePair<TKey, TValue> current = _current;
return current.Key;
}
}
readonly object? IDictionaryEnumerator.Value
{
get
{
if (_index == 0 || _index == _dictionary._count + 1)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen();
}
KeyValuePair<TKey, TValue> current = _current;
return current.Value;
}
}
internal Enumerator(SegmentedDictionary<TKey, TValue> dictionary, int getEnumeratorRetType)
{
_dictionary = dictionary;
_version = dictionary._version;
_index = 0;
_getEnumeratorRetType = getEnumeratorRetType;
_current = default(KeyValuePair<TKey, TValue>);
}
public bool MoveNext()
{
if (_version != _dictionary._version)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
}
while ((uint)_index < (uint)_dictionary._count)
{
ref Entry reference = ref _dictionary._entries[_index++];
if (reference._next >= -1)
{
_current = new KeyValuePair<TKey, TValue>(reference._key, reference._value);
return true;
}
}
_index = _dictionary._count + 1;
_current = default(KeyValuePair<TKey, TValue>);
return false;
}
public readonly void Dispose()
{
}
void IEnumerator.Reset()
{
if (_version != _dictionary._version)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
}
_index = 0;
_current = default(KeyValuePair<TKey, TValue>);
}
}
[DebuggerTypeProxy(typeof(DictionaryKeyCollectionDebugView<, >))]
[DebuggerDisplay("Count = {Count}")]
public sealed class KeyCollection : ICollection<TKey>, IEnumerable<TKey>, IEnumerable, ICollection, IReadOnlyCollection<TKey>
{
public struct Enumerator : IEnumerator<TKey>, IEnumerator, IDisposable
{
private readonly SegmentedDictionary<TKey, TValue> _dictionary;
private int _index;
private readonly int _version;
private TKey? _currentKey;
public readonly TKey Current => _currentKey;
readonly object? IEnumerator.Current
{
get
{
if (_index == 0 || _index == _dictionary._count + 1)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen();
}
return _currentKey;
}
}
internal Enumerator(SegmentedDictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
_version = dictionary._version;
_index = 0;
_currentKey = default(TKey);
}
public readonly void Dispose()
{
}
public bool MoveNext()
{
if (_version != _dictionary._version)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
}
while ((uint)_index < (uint)_dictionary._count)
{
ref Entry reference = ref _dictionary._entries[_index++];
if (reference._next >= -1)
{
_currentKey = reference._key;
return true;
}
}
_index = _dictionary._count + 1;
_currentKey = default(TKey);
return false;
}
void IEnumerator.Reset()
{
if (_version != _dictionary._version)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
}
_index = 0;
_currentKey = default(TKey);
}
}
private readonly SegmentedDictionary<TKey, TValue> _dictionary;
public int Count => _dictionary.Count;
bool ICollection<TKey>.IsReadOnly => true;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot;
public KeyCollection(SegmentedDictionary<TKey, TValue> dictionary)
{
if (dictionary == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
}
_dictionary = dictionary;
}
public Enumerator GetEnumerator()
{
return new Enumerator(_dictionary);
}
public void CopyTo(TKey[] array, int index)
{
if (array == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
}
if (index < 0 || index > array.Length)
{
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
}
if (array.Length - index < _dictionary.Count)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
int count = _dictionary._count;
SegmentedArray<Entry> entries = _dictionary._entries;
for (int i = 0; i < count; i++)
{
if (entries[i]._next >= -1)
{
array[index++] = entries[i]._key;
}
}
}
void ICollection<TKey>.Add(TKey item)
{
ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
}
void ICollection<TKey>.Clear()
{
ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
}
bool ICollection<TKey>.Contains(TKey item)
{
return _dictionary.ContainsKey(item);
}
bool ICollection<TKey>.Remove(TKey item)
{
ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
return false;
}
IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()
{
return new Enumerator(_dictionary);
}
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(_dictionary);
}
void ICollection.CopyTo(Array array, int index)
{
if (array == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
}
if (array.Rank != 1)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
}
if (array.GetLowerBound(0) != 0)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
}
if ((uint)index > (uint)array.Length)
{
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
}
if (array.Length - index < _dictionary.Count)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
if (array is TKey[] array2)
{
CopyTo(array2, index);
return;
}
object[] array3 = array as object[];
if (array3 == null)
{
ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
}
int count = _dictionary._count;
SegmentedArray<Entry> entries = _dictionary._entries;
try
{
for (int i = 0; i < count; i++)
{
if (entries[i]._next >= -1)
{
array3[index++] = entries[i]._key;
}
}
}
catch (ArrayTypeMismatchException)
{
ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
}
}
}
[DebuggerTypeProxy(typeof(DictionaryValueCollectionDebugView<, >))]
[DebuggerDisplay("Count = {Count}")]
public sealed class ValueCollection : ICollection<TValue>, IEnumerable<TValue>, IEnumerable, ICollection, IReadOnlyCollection<TValue>
{
public struct Enumerator : IEnumerator<TValue>, IEnumerator, IDisposable
{
private readonly SegmentedDictionary<TKey, TValue> _dictionary;
private int _index;
private readonly int _version;
private TValue? _currentValue;
public readonly TValue Current => _currentValue;
readonly object? IEnumerator.Current
{
get
{
if (_index == 0 || _index == _dictionary._count + 1)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen();
}
return _currentValue;
}
}
internal Enumerator(SegmentedDictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
_version = dictionary._version;
_index = 0;
_currentValue = default(TValue);
}
public readonly void Dispose()
{
}
public bool MoveNext()
{
if (_version != _dictionary._version)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
}
while ((uint)_index < (uint)_dictionary._count)
{
ref Entry reference = ref _dictionary._entries[_index++];
if (reference._next >= -1)
{
_currentValue = reference._value;
return true;
}
}
_index = _dictionary._count + 1;
_currentValue = default(TValue);
return false;
}
void IEnumerator.Reset()
{
if (_version != _dictionary._version)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
}
_index = 0;
_currentValue = default(TValue);
}
}
private readonly SegmentedDictionary<TKey, TValue> _dictionary;
public int Count => _dictionary.Count;
bool ICollection<TValue>.IsReadOnly => true;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot;
public ValueCollection(SegmentedDictionary<TKey, TValue> dictionary)
{
if (dictionary == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
}
_dictionary = dictionary;
}
public Enumerator GetEnumerator()
{
return new Enumerator(_dictionary);
}
public void CopyTo(TValue[] array, int index)
{
if (array == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
}
if ((uint)index > array.Length)
{
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
}
if (array.Length - index < _dictionary.Count)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
int count = _dictionary._count;
SegmentedArray<Entry> entries = _dictionary._entries;
for (int i = 0; i < count; i++)
{
if (entries[i]._next >= -1)
{
array[index++] = entries[i]._value;
}
}
}
void ICollection<TValue>.Add(TValue item)
{
ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
}
bool ICollection<TValue>.Remove(TValue item)
{
ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
return false;
}
void ICollection<TValue>.Clear()
{
ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
}
bool ICollection<TValue>.Contains(TValue item)
{
return _dictionary.ContainsValue(item);
}
IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator()
{
return new Enumerator(_dictionary);
}
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(_dictionary);
}
void ICollection.CopyTo(Array array, int index)
{
if (array == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
}
if (array.Rank != 1)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
}
if (array.GetLowerBound(0) != 0)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
}
if ((uint)index > (uint)array.Length)
{
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
}
if (array.Length - index < _dictionary.Count)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
if (array is TValue[] array2)
{
CopyTo(array2, index);
return;
}
object[] array3 = array as object[];
if (array3 == null)
{
ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
}
int count = _dictionary._count;
SegmentedArray<Entry> entries = _dictionary._entries;
try
{
for (int i = 0; i < count; i++)
{
if (entries[i]._next >= -1)
{
array3[index++] = entries[i]._value;
}
}
}
catch (ArrayTypeMismatchException)
{
ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
}
}
}
private const bool SupportsComparerDevirtualization = false;
private SegmentedArray<int> _buckets;
private SegmentedArray<Entry> _entries;
private ulong _fastModMultiplier;
private int _count;
private int _freeList;
private int _freeCount;
private int _version;
private readonly IEqualityComparer<TKey> _comparer;
private KeyCollection? _keys;
private ValueCollection? _values;
private const int StartOfFreeList = -3;
public IEqualityComparer<TKey> Comparer => _comparer ?? EqualityComparer<TKey>.Default;
public int Count => _count - _freeCount;
public KeyCollection Keys => _keys ?? (_keys = new KeyCollection(this));
ICollection<TKey> IDictionary<TKey, TValue>.Keys => Keys;
IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => Keys;
public ValueCollection Values => _values ?? (_values = new ValueCollection(this));
ICollection<TValue> IDictionary<TKey, TValue>.Values => Values;
IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values;
public TValue this[TKey key]
{
get
{
ref TValue reference = ref FindValue(key);
if (!RoslynUnsafe.IsNullRef(ref reference))
{
return reference;
}
ThrowHelper.ThrowKeyNotFoundException(key);
return default(TValue);
}
set
{
TryInsert(key, value, InsertionBehavior.OverwriteExisting);
}
}
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => this;
bool IDictionary.IsFixedSize => false;
bool IDictionary.IsReadOnly => false;
ICollection IDictionary.Keys => Keys;
ICollection IDictionary.Values => Values;
object? IDictionary.this[object key]
{
get
{
if (IsCompatibleKey(key))
{
ref TValue reference = ref FindValue((TKey)key);
if (!RoslynUnsafe.IsNullRef(ref reference))
{
return reference;
}
}
return null;
}
set
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
ThrowHelper.IfNullAndNullsAreIllegalThenThrow<TValue>(value, ExceptionArgument.value);
try
{
TKey key2 = (TKey)key;
try
{
this[key2] = (TValue)value;
}
catch (InvalidCastException)
{
ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue));
}
}
catch (InvalidCastException)
{
ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey));
}
}
}
public SegmentedDictionary()
: this(0, (IEqualityComparer<TKey>?)null)
{
}
public SegmentedDictionary(int capacity)
: this(capacity, (IEqualityComparer<TKey>?)null)
{
}
public SegmentedDictionary(IEqualityComparer<TKey>? comparer)
: this(0, comparer)
{
}
public SegmentedDictionary(int capacity, IEqualityComparer<TKey>? comparer)
{
if (capacity < 0)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity);
}
if (capacity > 0)
{
Initialize(capacity);
}
if (comparer != null && comparer != EqualityComparer<TKey>.Default)
{
_comparer = comparer;
}
if (_comparer == null)
{
_comparer = EqualityComparer<TKey>.Default;
}
}
public SegmentedDictionary(IDictionary<TKey, TValue> dictionary)
: this(dictionary, (IEqualityComparer<TKey>?)null)
{
}
public SegmentedDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey>? comparer)
: this(dictionary?.Count ?? 0, comparer)
{
if (dictionary == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
}
if (dictionary.GetType() == typeof(SegmentedDictionary<TKey, TValue>))
{
SegmentedDictionary<TKey, TValue> obj = (SegmentedDictionary<TKey, TValue>)dictionary;
int count = obj._count;
SegmentedArray<Entry> entries = obj._entries;
for (int i = 0; i < count; i++)
{
if (entries[i]._next >= -1)
{
Add(entries[i]._key, entries[i]._value);
}
}
return;
}
foreach (KeyValuePair<TKey, TValue> item in dictionary)
{
Add(item.Key, item.Value);
}
}
public SegmentedDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection)
: this(collection, (IEqualityComparer<TKey>?)null)
{
}
public SegmentedDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey>? comparer)
: this((collection as ICollection<KeyValuePair<TKey, TValue>>)?.Count ?? 0, comparer)
{
if (collection == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
}
foreach (KeyValuePair<TKey, TValue> item in collection)
{
Add(item.Key, item.Value);
}
}
public void Add(TKey key, TValue value)
{
TryInsert(key, value, InsertionBehavior.ThrowOnExisting);
}
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair)
{
Add(keyValuePair.Key, keyValuePair.Value);
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair)
{
ref TValue reference = ref FindValue(keyValuePair.Key);
if (!RoslynUnsafe.IsNullRef(ref reference) && EqualityComparer<TValue>.Default.Equals(reference, keyValuePair.Value))
{
return true;
}
return false;
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> keyValuePair)
{
ref TValue reference = ref FindValue(keyValuePair.Key);
if (!RoslynUnsafe.IsNullRef(ref reference) && EqualityComparer<TValue>.Default.Equals(reference, keyValuePair.Value))
{
Remove(keyValuePair.Key);
return true;
}
return false;
}
public void Clear()
{
int count = _count;
if (count > 0)
{
SegmentedArray.Clear(_buckets, 0, _buckets.Length);
_count = 0;
_freeList = -1;
_freeCount = 0;
SegmentedArray.Clear(_entries, 0, count);
}
}
public bool ContainsKey(TKey key)
{
return !RoslynUnsafe.IsNullRef(ref FindValue(key));
}
public bool ContainsValue(TValue value)
{
SegmentedArray<Entry> entries = _entries;
if (value == null)
{
for (int i = 0; i < _count; i++)
{
if (entries[i]._next >= -1 && entries[i]._value == null)
{
return true;
}
}
}
else
{
EqualityComparer<TValue> equalityComparer = EqualityComparer<TValue>.Default;
for (int j = 0; j < _count; j++)
{
if (entries[j]._next >= -1 && equalityComparer.Equals(entries[j]._value, value))
{
return true;
}
}
}
return false;
}
private void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
{
if (array == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
}
if ((uint)index > (uint)array.Length)
{
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
}
if (array.Length - index < Count)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
int count = _count;
SegmentedArray<Entry> entries = _entries;
for (int i = 0; i < count; i++)
{
if (entries[i]._next >= -1)
{
array[index++] = new KeyValuePair<TKey, TValue>(entries[i]._key, entries[i]._value);
}
}
}
public Enumerator GetEnumerator()
{
return new Enumerator(this, 2);
}
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
return new Enumerator(this, 2);
}
private ref TValue FindValue(TKey key)
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
ref Entry reference = ref RoslynUnsafe.NullRef<Entry>();
if (_buckets.Length > 0)
{
IEqualityComparer<TKey> comparer = _comparer;
uint hashCode = (uint)comparer.GetHashCode(key);
int bucket = GetBucket(hashCode);
SegmentedArray<Entry> entries = _entries;
uint num = 0u;
bucket--;
while ((uint)bucket < (uint)entries.Length)
{
reference = ref entries[bucket];
if (reference._hashCode != hashCode || !comparer.Equals(reference._key, key))
{
bucket = reference._next;
num++;
if (num <= (uint)entries.Length)
{
continue;
}
ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
}
return ref reference._value;
}
}
return ref RoslynUnsafe.NullRef<TValue>();
}
private int Initialize(int capacity)
{
int prime = HashHelpers.GetPrime(capacity);
SegmentedArray<int> buckets = new SegmentedArray<int>(prime);
SegmentedArray<Entry> entries = new SegmentedArray<Entry>(prime);
_freeList = -1;
_fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)prime);
_buckets = buckets;
_entries = entries;
return prime;
}
private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior)
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (_buckets.Length == 0)
{
Initialize(0);
}
SegmentedArray<Entry> entries = _entries;
IEqualityComparer<TKey> comparer = _comparer;
uint hashCode = (uint)comparer.GetHashCode(key);
uint num = 0u;
ref int bucket = ref GetBucket(hashCode);
int num2 = bucket - 1;
while ((uint)num2 < (uint)entries.Length)
{
if (entries[num2]._hashCode == hashCode && comparer.Equals(entries[num2]._key, key))
{
switch (behavior)
{
case InsertionBehavior.OverwriteExisting:
entries[num2]._value = value;
return true;
case InsertionBehavior.ThrowOnExisting:
ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key);
break;
}
return false;
}
num2 = entries[num2]._next;
num++;
if (num > (uint)entries.Length)
{
ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
}
}
int num3;
if (_freeCount > 0)
{
num3 = _freeList;
_freeList = -3 - entries[_freeList]._next;
_freeCount--;
}
else
{
int count = _count;
if (count == entries.Length)
{
Resize();
bucket = ref GetBucket(hashCode);
}
num3 = count;
_count = count + 1;
entries = _entries;
}
ref Entry reference = ref entries[num3];
reference._hashCode = hashCode;
reference._next = bucket - 1;
reference._key = key;
reference._value = value;
bucket = num3 + 1;
_version++;
return true;
}
private void Resize()
{
Resize(HashHelpers.ExpandPrime(_count));
}
private void Resize(int newSize)
{
SegmentedArray<Entry> segmentedArray = new SegmentedArray<Entry>(newSize);
int count = _count;
SegmentedArray.Copy(_entries, segmentedArray, count);
_buckets = new SegmentedArray<int>(newSize);
_fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)newSize);
for (int i = 0; i < count; i++)
{
if (segmentedArray[i]._next >= -1)
{
ref int bucket = ref GetBucket(segmentedArray[i]._hashCode);
segmentedArray[i]._next = bucket - 1;
bucket = i + 1;
}
}
_entries = segmentedArray;
}
public bool Remove(TKey key)
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (_buckets.Length > 0)
{
uint num = 0u;
uint num2 = (uint)(_comparer?.GetHashCode(key) ?? key.GetHashCode());
ref int bucket = ref GetBucket(num2);
SegmentedArray<Entry> entries = _entries;
int num3 = -1;
int num4 = bucket - 1;
while (num4 >= 0)
{
ref Entry reference = ref entries[num4];
if (reference._hashCode == num2 && (_comparer?.Equals(reference._key, key) ?? EqualityComparer<TKey>.Default.Equals(reference._key, key)))
{
if (num3 < 0)
{
bucket = reference._next + 1;
}
else
{
entries[num3]._next = reference._next;
}
reference._next = -3 - _freeList;
reference._key = default(TKey);
reference._value = default(TValue);
_freeList = num4;
_freeCount++;
return true;
}
num3 = num4;
num4 = reference._next;
num++;
if (num > (uint)entries.Length)
{
ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
}
}
}
return false;
}
public bool Remove(TKey key, [MaybeNullWhen(false)] out TValue value)
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (_buckets.Length > 0)
{
uint num = 0u;
uint num2 = (uint)(_comparer?.GetHashCode(key) ?? key.GetHashCode());
ref int bucket = ref GetBucket(num2);
SegmentedArray<Entry> entries = _entries;
int num3 = -1;
int num4 = bucket - 1;
while (num4 >= 0)
{
ref Entry reference = ref entries[num4];
if (reference._hashCode == num2 && (_comparer?.Equals(reference._key, key) ?? EqualityComparer<TKey>.Default.Equals(reference._key, key)))
{
if (num3 < 0)
{
bucket = reference._next + 1;
}
else
{
entries[num3]._next = reference._next;
}
value = reference._value;
reference._next = -3 - _freeList;
reference._key = default(TKey);
reference._value = default(TValue);
_freeList = num4;
_freeCount++;
return true;
}
num3 = num4;
num4 = reference._next;
num++;
if (num > (uint)entries.Length)
{
ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
}
}
}
value = default(TValue);
return false;
}
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
{
ref TValue reference = ref FindValue(key);
if (!RoslynUnsafe.IsNullRef(ref reference))
{
value = reference;
return true;
}
value = default(TValue);
return false;
}
public bool TryAdd(TKey key, TValue value)
{
return TryInsert(key, value, InsertionBehavior.None);
}
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
{
CopyTo(array, index);
}
void ICollection.CopyTo(Array array, int index)
{
if (array == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
}
if (array.Rank != 1)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
}
if (array.GetLowerBound(0) != 0)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
}
if ((uint)index > (uint)array.Length)
{
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
}
if (array.Length - index < Count)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
if (array is KeyValuePair<TKey, TValue>[] array2)
{
CopyTo(array2, index);
return;
}
if (array is DictionaryEntry[] array3)
{
SegmentedArray<Entry> entries = _entries;
for (int i = 0; i < _count; i++)
{
if (entries[i]._next >= -1)
{
array3[index++] = new DictionaryEntry(entries[i]._key, entries[i]._value);
}
}
return;
}
object[] array4 = array as object[];
if (array4 == null)
{
ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
}
try
{
int count = _count;
SegmentedArray<Entry> entries2 = _entries;
for (int j = 0; j < count; j++)
{
if (entries2[j]._next >= -1)
{
array4[index++] = new KeyValuePair<TKey, TValue>(entries2[j]._key, entries2[j]._value);
}
}
}
catch (ArrayTypeMismatchException)
{
ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(this, 2);
}
public int EnsureCapacity(int capacity)
{
if (capacity < 0)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity);
}
int length = _entries.Length;
if (length >= capacity)
{
return length;
}
_version++;
if (_buckets.Length == 0)
{
return Initialize(capacity);
}
int prime = HashHelpers.GetPrime(capacity);
Resize(prime);
return prime;
}
public void TrimExcess()
{
TrimExcess(Count);
}
public void TrimExcess(int capacity)
{
if (capacity < Count)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity);
}
int prime = HashHelpers.GetPrime(capacity);
SegmentedArray<Entry> entries = _entries;
int length = entries.Length;
if (prime >= length)
{
return;
}
int count = _count;
_version++;
Initialize(prime);
SegmentedArray<Entry> entries2 = _entries;
int num = 0;
for (int i = 0; i < count; i++)
{
uint hashCode = entries[i]._hashCode;
if (entries[i]._next >= -1)
{
ref Entry reference = ref entries2[num];
reference = entries[i];
ref int bucket = ref GetBucket(hashCode);
reference._next = bucket - 1;
bucket = num + 1;
num++;
}
}
_count = num;
_freeCount = 0;
}
private static bool IsCompatibleKey(object key)
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
return key is TKey;
}
void IDictionary.Add(object key, object? value)
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
ThrowHelper.IfNullAndNullsAreIllegalThenThrow<TValue>(value, ExceptionArgument.value);
try
{
TKey key2 = (TKey)key;
try
{
Add(key2, (TValue)value);
}
catch (InvalidCastException)
{
ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue));
}
}
catch (InvalidCastException)
{
ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey));
}
}
bool IDictionary.Contains(object key)
{
if (IsCompatibleKey(key))
{
return ContainsKey((TKey)key);
}
return false;
}
IDictionaryEnumerator IDictionary.GetEnumerator()
{
return new Enumerator(this, 1);
}
void IDictionary.Remove(object key)
{
if (IsCompatibleKey(key))
{
Remove((TKey)key);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private ref int GetBucket(uint hashCode)
{
SegmentedArray<int> buckets = _buckets;
return ref buckets[(int)HashHelpers.FastMod(hashCode, (uint)buckets.Length, _fastModMultiplier)];
}
}