Skip to content

Commit 4e37145

Browse files
author
LoneWandererProductions
committed
comment and cleanup
1 parent 72dc01d commit 4e37145

3 files changed

Lines changed: 91 additions & 15 deletions

File tree

ExtendedSystemObjects/Helper/SharedRessources.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ internal static class SharedResources
3838
/// </summary>
3939
internal const string ErrorValueExists = "Value already exists: ";
4040

41+
/// <summary>
42+
/// The error duplicate key (const). "Duplicate key detected: {key}".
43+
/// </summary>
44+
internal const string ErrorDuplicateKey = "Duplicate key detected: {key}";
45+
4146
/// <summary>
4247
/// Separator(const). Value: " , ".
4348
/// </summary>

ExtendedSystemObjects/ImmutableLookupMap.cs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,17 @@ public ImmutableLookupMap(IDictionary<TKey, TValue> data)
7676

7777
if (_keys[hash].Equals(key))
7878
{
79-
throw new InvalidOperationException($"Duplicate key detected: {key}");
79+
throw new InvalidOperationException(string.Format(SharedResources.ErrorDuplicateKey, key));
8080
}
8181
}
8282
}
8383
}
8484

8585
/// <inheritdoc />
8686
/// <summary>
87-
/// Returns an enumerator for iterating over the key-value pairs in the map.
87+
/// Returns an enumerator that iterates through the key-value pairs in the map.
8888
/// </summary>
89+
/// <returns>An enumerator for the map.</returns>
8990
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
9091
{
9192
for (var i = 0; i < _keys.Length; i++)
@@ -110,11 +111,11 @@ IEnumerator IEnumerable.GetEnumerator()
110111
}
111112

112113
/// <summary>
113-
/// Retrieves the value associated with the specified key.
114+
/// Gets the value associated with the specified key.
114115
/// </summary>
115-
/// <param name="key">The key.</param>
116-
/// <returns>Requested Value from Key</returns>
117-
/// <exception cref="KeyNotFoundException">The key {key} was not found in the lookup map.</exception>
116+
/// <param name="key">The key to lookup.</param>
117+
/// <returns>The value associated with the key.</returns>
118+
/// <exception cref="KeyNotFoundException">Thrown if the key is not found in the map.</exception>
118119
public TValue Get(TKey key)
119120
{
120121
var hash = GetHash(key, _keys.Length);
@@ -138,11 +139,11 @@ public TValue Get(TKey key)
138139
}
139140

140141
/// <summary>
141-
/// Attempts to retrieve the value associated with the specified key.
142+
/// Attempts to retrieve the value associated with the specified key.
142143
/// </summary>
143-
/// <param name="key">The key.</param>
144-
/// <param name="value">The value.</param>
145-
/// <returns>The value amd bool check if it exists.</returns>
144+
/// <param name="key">The key to lookup.</param>
145+
/// <param name="value">When this method returns, contains the value associated with the key, if found; otherwise, the default value.</param>
146+
/// <returns><c>true</c> if the key was found; otherwise, <c>false</c>.</returns>
146147
public bool TryGetValue(TKey key, out TValue value)
147148
{
148149
var hash = GetHash(key, _keys.Length);

ExtendedSystemObjects/ImmutableLookupMapUnmanaged.cs

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
* COPYRIGHT: See COPYING in the top level directory
33
* PROJECT: ExtendedSystemObjects
44
* FILE: ExtendedSystemObjects/ImmutableLookupMap.cs
5-
* PURPOSE: A high-performance, immutable lookup map that uses an array-based internal structure for fast key-value lookups. Tis one is for unmanaged only. It uses my UnmanagedArray.
6-
* PROGRAMER: Peter Geinitz (Wayfarer)
5+
* PURPOSE: A high-performance, immutable lookup map that uses an array-based internal structure for fast key-value lookups.
6+
* This version is limited to unmanaged types and uses UnmanagedArray<T>.
7+
* PROGRAMMER: Peter Geinitz (Wayfarer)
78
*/
89

910
// ReSharper disable UnusedMember.Global
@@ -19,19 +20,45 @@ namespace ExtendedSystemObjects
1920
{
2021
/// <summary>
2122
/// A high-performance, immutable lookup map using unmanaged arrays.
23+
/// Suitable for value types only. Keys must be unique.
2224
/// </summary>
2325
public sealed unsafe class ImmutableLookupMapUnmanaged<TKey, TValue> : IDisposable, IEnumerable<KeyValuePair<TKey, TValue>>
2426
where TKey : unmanaged, IEquatable<TKey>
2527
where TValue : unmanaged
2628
{
29+
/// <summary>
30+
/// The keys
31+
/// </summary>
2732
private readonly UnmanagedArray<TKey> _keys;
33+
34+
/// <summary>
35+
/// The values
36+
/// </summary>
2837
private readonly UnmanagedArray<TValue> _values;
38+
39+
/// <summary>
40+
/// Indicates whether a key is present at the given hash slot.
41+
/// </summary>
2942
private readonly UnmanagedArray<byte> _keyPresence;
3043

44+
/// <summary>
45+
/// The capacity
46+
/// </summary>
3147
private readonly int _capacity;
3248

49+
/// <summary>
50+
/// Gets the number of entries in the map.
51+
/// </summary>
3352
public int Count { get; }
3453

54+
/// <summary>
55+
/// Initializes a new instance of the <see cref="ImmutableLookupMapUnmanaged{TKey, TValue}"/> class
56+
/// with the specified key-value data.
57+
/// </summary>
58+
/// <param name="data">A dictionary containing the initial key-value pairs.</param>
59+
/// <exception cref="ArgumentNullException">Thrown when <paramref name="data"/> is null.</exception>
60+
/// <exception cref="InvalidOperationException">Thrown when a duplicate key is found.</exception>
61+
3562
public ImmutableLookupMapUnmanaged(IDictionary<TKey, TValue> data)
3663
{
3764
if (data == null)
@@ -48,7 +75,7 @@ public ImmutableLookupMapUnmanaged(IDictionary<TKey, TValue> data)
4875
{
4976
for (var i = 0; i < _capacity; i++)
5077
{
51-
var hash = (GetHash(key, _capacity) + i * i) % _capacity;
78+
var hash = (GetHash(key, _capacity) + (i * i)) % _capacity;
5279

5380
if (_keyPresence[hash] == 0)
5481
{
@@ -59,11 +86,17 @@ public ImmutableLookupMapUnmanaged(IDictionary<TKey, TValue> data)
5986
}
6087

6188
if (_keys[hash].Equals(key))
62-
throw new InvalidOperationException($"Duplicate key detected: {key}");
89+
throw new InvalidOperationException(string.Format(SharedResources.ErrorDuplicateKey, key));
6390
}
6491
}
6592
}
6693

94+
/// <summary>
95+
/// Gets the value associated with the specified key.
96+
/// </summary>
97+
/// <param name="key">The key to lookup.</param>
98+
/// <returns>The value associated with the key.</returns>
99+
/// <exception cref="KeyNotFoundException">Thrown if the key is not found in the map.</exception>
67100
public TValue Get(TKey key)
68101
{
69102
var hash = GetHash(key, _capacity);
@@ -79,9 +112,15 @@ public TValue Get(TKey key)
79112
break;
80113
}
81114

82-
throw new KeyNotFoundException($"Key '{key}' not found in lookup.");
115+
throw new KeyNotFoundException(SharedResources.ErrorValueNotFound);
83116
}
84117

118+
/// <summary>
119+
/// Attempts to retrieve the value associated with the specified key.
120+
/// </summary>
121+
/// <param name="key">The key to lookup.</param>
122+
/// <param name="value">When this method returns, contains the value associated with the key, if found; otherwise, the default value.</param>
123+
/// <returns><c>true</c> if the key was found; otherwise, <c>false</c>.</returns>
85124
public bool TryGetValue(TKey key, out TValue value)
86125
{
87126
var hash = GetHash(key, _capacity);
@@ -104,6 +143,10 @@ public bool TryGetValue(TKey key, out TValue value)
104143
return false;
105144
}
106145

146+
/// <inheritdoc />
147+
/// <summary>
148+
/// Returns an enumerator for iterating over the key-value pairs in the map.
149+
/// </summary>
107150
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
108151
{
109152
for (var i = 0; i < _capacity; i++)
@@ -113,28 +156,55 @@ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
113156
}
114157
}
115158

159+
/// <inheritdoc />
160+
/// <summary>
161+
/// Returns an enumerator that iterates through a collection.
162+
/// </summary>
163+
/// <returns>
164+
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
165+
/// </returns>
116166
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
117167

168+
/// <summary>
169+
/// Releases the unmanaged memory used by the lookup map.
170+
/// </summary>
118171
public void Dispose()
119172
{
120173
_keys.Dispose();
121174
_values.Dispose();
122175
_keyPresence.Dispose();
123176
}
124177

178+
/// <summary>
179+
/// Computes the hash code of a key and reduces it to fit the map's capacity.
180+
/// </summary>
181+
/// <param name="key">The key.</param>
182+
/// <param name="capacity">The internal array size.</param>
183+
/// <returns>A non-negative integer hash.</returns>
125184
[MethodImpl(MethodImplOptions.AggressiveInlining)]
126185
private static int GetHash(TKey key, int capacity)
127186
{
128187
return Math.Abs(key.GetHashCode() % capacity);
129188
}
130189

190+
/// <summary>
191+
/// Finds the next prime number greater than or equal to the specified number.
192+
/// </summary>
193+
/// <param name="number">The minimum value.</param>
194+
/// <returns>The next prime number ≥ <paramref name="number"/>.</returns>
131195
private static int FindNextPrime(int number)
132196
{
133197
while (!IsPrime(number))
134198
number++;
135199
return number;
136200
}
137201

202+
/// <summary>
203+
/// Determines whether a number is prime.
204+
/// Uses precomputed small primes for optimization.
205+
/// </summary>
206+
/// <param name="number">The number to check.</param>
207+
/// <returns><c>true</c> if prime; otherwise, <c>false</c>.</returns>
138208
private static bool IsPrime(int number)
139209
{
140210
if (number < 2) return false;

0 commit comments

Comments
 (0)