51d352d24650a09538e985db6b390116daa28592
[platform/upstream/dotnet/runtime.git] /
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3
4 using System.Collections.Generic;
5 using System.Diagnostics;
6 using System.Linq;
7 using System.Numerics;
8 using System.Runtime.CompilerServices;
9
10 namespace System.Collections.Frozen
11 {
12     /// <summary>Provides a frozen dictionary to use when the key is an integer, the default comparer is used, and the item count is small.</summary>
13     /// <remarks>
14     /// No hashing here, just a straight-up linear scan through the items.
15     /// </remarks>
16     internal sealed class SmallIntegerFrozenDictionary<TKey, TValue> : FrozenDictionary<TKey, TValue>
17         where TKey : struct, IBinaryInteger<TKey>
18     {
19         private readonly TKey[] _keys;
20         private readonly TValue[] _values;
21         private readonly TKey _max;
22
23         internal SmallIntegerFrozenDictionary(Dictionary<TKey, TValue> source) : base(EqualityComparer<TKey>.Default)
24         {
25             Debug.Assert(source.Count != 0);
26             Debug.Assert(ReferenceEquals(source.Comparer, EqualityComparer<TKey>.Default));
27
28             _keys = source.Keys.ToArray();
29             _values = source.Values.ToArray();
30             Array.Sort(_keys, _values);
31
32             _max = _keys[^1];
33         }
34
35         private protected override TKey[] KeysCore => _keys;
36         private protected override TValue[] ValuesCore => _values;
37         private protected override Enumerator GetEnumeratorCore() => new Enumerator(_keys, _values);
38         private protected override int CountCore => _keys.Length;
39
40         [MethodImpl(MethodImplOptions.AggressiveInlining)]
41         private protected override ref readonly TValue GetValueRefOrNullRefCore(TKey key)
42         {
43             if (key <= _max)
44             {
45                 TKey[] keys = _keys;
46                 for (int i = 0; i < keys.Length; i++)
47                 {
48                     if (key <= keys[i])
49                     {
50                         if (key < keys[i])
51                         {
52                             break;
53                         }
54
55                         return ref _values[i];
56                     }
57                 }
58             }
59
60             return ref Unsafe.NullRef<TValue>();
61         }
62     }
63 }