Untitled diff

作成日 差分は期限切れになりません
11 削除
67 行
14 追加
69 行
private ReadOnlyMemory<T> GetFirstBuffer()
private ReadOnlySpan<T> GetFirstSpan()
{
{
object startObject = _sequenceStart.GetObject();
object startObject = _sequenceStart.GetObject();


if (startObject == null)
if (startObject == null)
return default;
return default;


int startIndex = _sequenceStart.GetInteger();
int startIndex = _sequenceStart.GetInteger();
int endIndex = _sequenceEnd.GetInteger();
int endIndex = _sequenceEnd.GetInteger();


bool isMultiSegment = startObject != _sequenceEnd.GetObject();
bool isMultiSegment = startObject != _sequenceEnd.GetObject();


// The highest bit of startIndex and endIndex are used to infer the sequence type
// The highest bit of startIndex and endIndex are used to infer the sequence type
// The code below is structured this way for performance reasons and is equivalent to the following:
// The code below is structured this way for performance reasons and is equivalent to the following:
// SequenceType type = GetSequenceType();
// SequenceType type = GetSequenceType();
// if (type == SequenceType.MultiSegment) { ... }
// if (type == SequenceType.MultiSegment) { ... }
// else if (type == SequenceType.Array) { ... }
// else if (type == SequenceType.Array) { ... }
// else if (type == SequenceType.String){ ... }
// else if (type == SequenceType.String){ ... }
// else if (type == SequenceType.MemoryManager) { ... }
// else if (type == SequenceType.MemoryManager) { ... }


// Highest bit of startIndex: A = startIndex >> 31
// Highest bit of startIndex: A = startIndex >> 31
// Highest bit of endIndex: B = endIndex >> 31
// Highest bit of endIndex: B = endIndex >> 31


if (startIndex >= 0)
if (startIndex >= 0)
{
{
// A == 0 && B == 0 means SequenceType.MultiSegment
// A == 0 && B == 0 means SequenceType.MultiSegment
// A == 0 && B == 1 means SequenceType.Array
// A == 0 && B == 1 means SequenceType.Array


if (endIndex >= 0) // SequenceType.MultiSegment
if (endIndex >= 0) // SequenceType.MultiSegment
{
{
ReadOnlyMemory<T> memory = ((ReadOnlySequenceSegment<T>)startObject).Memory;
ReadOnlySpan<T> span = ((ReadOnlySequenceSegment<T>)startObject).Memory.Span;
if (isMultiSegment)
if (isMultiSegment)
{
{
return memory.Slice(startIndex);
return span.Slice(startIndex);
}
}
return memory.Slice(startIndex, endIndex - startIndex);
return span.Slice(startIndex, endIndex - startIndex);
}
}
else // endIndex < 0, SequenceType.Array
else // endIndex < 0, SequenceType.Array
{
{
if (isMultiSegment)
if (isMultiSegment)
ThrowHelper.ThrowInvalidOperationException_EndPositionNotReached();
ThrowHelper.ThrowInvalidOperationException_EndPositionNotReached();


return new ReadOnlyMemory<T>((T[])startObject, startIndex, (endIndex & ReadOnlySequence.IndexBitMask) - startIndex);
ReadOnlySpan<T> span = (T[])startObject;
return span.Slice(startIndex, (endIndex & ReadOnlySequence.IndexBitMask) - startIndex);
}
}
}
}
else // startIndex < 0
else // startIndex < 0
{
{
if (isMultiSegment)
if (isMultiSegment)
ThrowHelper.ThrowInvalidOperationException_EndPositionNotReached();
ThrowHelper.ThrowInvalidOperationException_EndPositionNotReached();


// A == 1 && B == 1 means SequenceType.String
// A == 1 && B == 1 means SequenceType.String
// A == 1 && B == 0 means SequenceType.MemoryManager
// A == 1 && B == 0 means SequenceType.MemoryManager


// The type == char check here is redundant. However, we still have it to allow
// The type == char check here is redundant. However, we still have it to allow
// the JIT to see when that the code is unreachable and eliminate it.
// the JIT to see when that the code is unreachable and eliminate it.
if (typeof(T) == typeof(char) && endIndex < 0) // SequenceType.String
if (typeof(T) == typeof(char) && endIndex < 0) // SequenceType.String
{
{
var memory = (ReadOnlyMemory<T>)(object)((string)startObject).AsMemory();
// No need to remove the FlagBitMask since (endIndex - startIndex) == (endIndex & ReadOnlySequence.IndexBitMask) - (startIndex & ReadOnlySequence.IndexBitMask)
// No need to remove the FlagBitMask since (endIndex - startIndex) == (endIndex & ReadOnlySequence.IndexBitMask) - (startIndex & ReadOnlySequence.IndexBitMask)
return (ReadOnlyMemory<T>)(object)((string)startObject).AsMemory((startIndex & ReadOnlySequence.IndexBitMask), endIndex - startIndex);
return memory.Span.Slice(startIndex & ReadOnlySequence.IndexBitMask, endIndex - startIndex);
}
}
else // endIndex >= 0, SequenceType.MemoryManager
else // endIndex >= 0, SequenceType.MemoryManager
{
{
startIndex &= ReadOnlySequence.IndexBitMask;
startIndex &= ReadOnlySequence.IndexBitMask;
return ((MemoryManager<T>)startObject).Memory.Slice(startIndex, endIndex - startIndex);
return ((MemoryManager<T>)startObject).Memory.Span.Slice(startIndex, endIndex - startIndex);
}
}
}
}
}
}