< Summary

Information
Class: SwiftCollections.Query.QueryKeyIndexMap<T>
Assembly: SwiftCollections
File(s): /home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Query/Shared/QueryKeyIndexMap.cs
Line coverage
96%
Covered lines: 48
Uncovered lines: 2
Coverable lines: 50
Total lines: 127
Line coverage: 96%
Branch coverage
96%
Covered branches: 27
Total branches: 28
Branch coverage: 96.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%44100%
get_Capacity()100%210%
Insert(...)100%22100%
Find(...)100%44100%
Remove(...)75%4488.88%
ResizeAndRehash(...)100%66100%
Clear()100%22100%
GetStartBucket(...)100%11100%
NormalizeBucketCapacity(...)100%22100%
RehashBucketCluster(...)100%44100%

File(s)

/home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Query/Shared/QueryKeyIndexMap.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Runtime.CompilerServices;
 4
 5namespace SwiftCollections.Query;
 6
 7internal sealed class QueryKeyIndexMap<TKey> where TKey : notnull
 8{
 9    private readonly IEqualityComparer<TKey> _comparer;
 10    private int[] _buckets;
 11    private int _bucketMask;
 12
 7113    public QueryKeyIndexMap(int capacity, IEqualityComparer<TKey>? comparer = null)
 14    {
 7115        _comparer = comparer ?? SwiftHashTools.GetDeterministicEqualityComparer<TKey>();
 7116        capacity = NormalizeBucketCapacity(capacity);
 3801717        _buckets = new int[capacity].Populate(() => -1);
 7118        _bucketMask = capacity - 1;
 7119    }
 20
 021    public int Capacity => _buckets.Length;
 22
 23    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 24    public void Insert(TKey key, int index)
 25    {
 3191926        int bucketIndex = GetStartBucket(key);
 27
 3244128        while (_buckets[bucketIndex] != -1)
 52229            bucketIndex = (bucketIndex + 1) & _bucketMask;
 30
 3191931        _buckets[bucketIndex] = index;
 3191932    }
 33
 34    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 35    public int Find(TKey key, Func<int, TKey, bool> isMatch)
 36    {
 28137        int bucketIndex = GetStartBucket(key);
 38
 30939        while (_buckets[bucketIndex] != -1)
 40        {
 19141            int candidate = _buckets[bucketIndex];
 19142            if (isMatch(candidate, key))
 16343                return candidate;
 44
 2845            bucketIndex = (bucketIndex + 1) & _bucketMask;
 46        }
 47
 11848        return -1;
 49    }
 50
 51    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 52    public bool Remove(
 53        TKey key,
 54        Func<int, TKey, bool> isMatch,
 55        Func<int, bool> canRehash,
 56        Func<int, TKey> getKey)
 57    {
 13558        int bucketIndex = GetStartBucket(key);
 59
 13660        while (_buckets[bucketIndex] != -1)
 61        {
 13662            int candidate = _buckets[bucketIndex];
 13663            if (isMatch(candidate, key))
 64            {
 13565                _buckets[bucketIndex] = -1;
 13566                RehashBucketCluster((bucketIndex + 1) & _bucketMask, canRehash, getKey);
 13567                return true;
 68            }
 69
 170            bucketIndex = (bucketIndex + 1) & _bucketMask;
 71        }
 72
 073        return false;
 74    }
 75
 76    public void ResizeAndRehash(int capacity, int entryCount, Func<int, bool> shouldRehash, Func<int, TKey> getKey)
 77    {
 3478        capacity = NormalizeBucketCapacity(capacity);
 14087879        _buckets = new int[capacity].Populate(() => -1);
 3480        _bucketMask = capacity - 1;
 81
 7043282        for (int i = 0; i < entryCount; i++)
 83        {
 3518284            if (!shouldRehash(i))
 85                continue;
 86
 1762887            Insert(getKey(i), i);
 88        }
 3489    }
 90
 91    public void Clear()
 92    {
 67493        for (int i = 0; i < _buckets.Length; i++)
 33294            _buckets[i] = -1;
 595    }
 96
 97    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 98    private int GetStartBucket(TKey key)
 99    {
 32335100        int hash = _comparer.GetHashCode(key) & 0x7FFFFFFF;
 32335101        return hash & _bucketMask;
 102    }
 103
 104    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 105    private static int NormalizeBucketCapacity(int capacity)
 106    {
 105107        capacity = SwiftHashTools.NextPowerOfTwo(capacity);
 105108        return capacity <= 1 ? 2 : capacity * 2;
 109    }
 110
 111    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 112    private void RehashBucketCluster(int startIndex, Func<int, bool> canRehash, Func<int, TKey> getKey)
 113    {
 135114        int bucketIndex = startIndex;
 115
 1087116        while (_buckets[bucketIndex] != -1)
 117        {
 952118            int candidate = _buckets[bucketIndex];
 952119            _buckets[bucketIndex] = -1;
 120
 952121            if (canRehash(candidate))
 952122                Insert(getKey(candidate), candidate);
 123
 952124            bucketIndex = (bucketIndex + 1) & _bucketMask;
 125        }
 135126    }
 127}