Skip to content

Commit b75f238

Browse files
committed
Added more comments, minor code refactoring
1 parent 67ec240 commit b75f238

File tree

3 files changed

+19
-40
lines changed

3 files changed

+19
-40
lines changed

Microsoft.Toolkit.HighPerformance/Extensions/ReadOnlySpanExtensions.cs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -221,34 +221,20 @@ public static ReadOnlySpan2D<T> AsSpan2D<T>(this ReadOnlySpan<T> span, int offse
221221
/// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="value"/> does not belong to <paramref name="span"/>.</exception>
222222
[Pure]
223223
[MethodImpl(MethodImplOptions.AggressiveInlining)]
224-
public static unsafe int IndexOf<T>(this ReadOnlySpan<T> span, in T value)
224+
public static int IndexOf<T>(this ReadOnlySpan<T> span, in T value)
225225
{
226226
ref T r0 = ref MemoryMarshal.GetReference(span);
227227
ref T r1 = ref Unsafe.AsRef(value);
228228
IntPtr byteOffset = Unsafe.ByteOffset(ref r0, ref r1);
229229

230-
if (sizeof(IntPtr) == sizeof(long))
231-
{
232-
long elementOffset = (long)byteOffset / Unsafe.SizeOf<T>();
233-
234-
if ((ulong)elementOffset >= (ulong)span.Length)
235-
{
236-
SpanExtensions.ThrowArgumentOutOfRangeExceptionForInvalidReference();
237-
}
230+
nint elementOffset = byteOffset / (nint)(uint)Unsafe.SizeOf<T>();
238231

239-
return unchecked((int)elementOffset);
240-
}
241-
else
232+
if ((nuint)elementOffset >= (uint)span.Length)
242233
{
243-
int elementOffset = (int)byteOffset / Unsafe.SizeOf<T>();
244-
245-
if ((uint)elementOffset >= (uint)span.Length)
246-
{
247-
SpanExtensions.ThrowArgumentOutOfRangeExceptionForInvalidReference();
248-
}
249-
250-
return elementOffset;
234+
SpanExtensions.ThrowArgumentOutOfRangeExceptionForInvalidReference();
251235
}
236+
237+
return (int)elementOffset;
252238
}
253239

254240
/// <summary>

Microsoft.Toolkit.HighPerformance/Extensions/SpanExtensions.cs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -167,33 +167,19 @@ public static Span<TTo> Cast<TFrom, TTo>(this Span<TFrom> span)
167167
/// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="value"/> does not belong to <paramref name="span"/>.</exception>
168168
[Pure]
169169
[MethodImpl(MethodImplOptions.AggressiveInlining)]
170-
public static unsafe int IndexOf<T>(this Span<T> span, ref T value)
170+
public static int IndexOf<T>(this Span<T> span, ref T value)
171171
{
172172
ref T r0 = ref MemoryMarshal.GetReference(span);
173173
IntPtr byteOffset = Unsafe.ByteOffset(ref r0, ref value);
174174

175-
if (sizeof(IntPtr) == sizeof(long))
176-
{
177-
long elementOffset = (long)byteOffset / Unsafe.SizeOf<T>();
178-
179-
if ((ulong)elementOffset >= (ulong)span.Length)
180-
{
181-
ThrowArgumentOutOfRangeExceptionForInvalidReference();
182-
}
175+
nint elementOffset = byteOffset / (nint)(uint)Unsafe.SizeOf<T>();
183176

184-
return unchecked((int)elementOffset);
185-
}
186-
else
177+
if ((nuint)elementOffset >= (uint)span.Length)
187178
{
188-
int elementOffset = (int)byteOffset / Unsafe.SizeOf<T>();
189-
190-
if ((uint)elementOffset >= (uint)span.Length)
191-
{
192-
ThrowArgumentOutOfRangeExceptionForInvalidReference();
193-
}
194-
195-
return elementOffset;
179+
ThrowArgumentOutOfRangeExceptionForInvalidReference();
196180
}
181+
182+
return (int)elementOffset;
197183
}
198184

199185
/// <summary>

Microsoft.Toolkit.HighPerformance/Memory/ReadOnlyMemory2D{T}.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,13 @@ public bool TryGetMemory(out ReadOnlyMemory<T> memory)
830830
}
831831
else if (typeof(T) == typeof(char) && this.instance.GetType() == typeof(string))
832832
{
833+
// Here we need to create a Memory<char> from the wrapped string, and to do so we need to do an inverse
834+
// lookup to find the initial index of the string with respect to the byte offset we're currently using,
835+
// which refers to the raw string object data. This can include variable padding or other additional
836+
// fields on different runtimes. The lookup operation is still O(1) and just computes the byte offset
837+
// difference between the start of the Span<char> (which directly wraps just the actual character data
838+
// within the string), and the input reference, which we can get from the byte offset in use. The result
839+
// is the character index which we can use to create the final Memory<char> instance.
833840
string text = Unsafe.As<string>(this.instance);
834841
int index = text.AsSpan().IndexOf(in text.DangerousGetObjectDataReferenceAt<char>(this.offset));
835842
ReadOnlyMemory<char> temp = text.AsMemory(index, (int)Length);

0 commit comments

Comments
 (0)