in src/Microsoft.Diagnostics.Runtime/src/Windows/CacheEntryBase.cs [310:409]
private static unsafe uint ProcessPageForSequenceTerminatingRead(UIntPtr data,
uint dataLength,
uint inPageOffset,
byte[] terminatingSequence,
List<byte> bytesRead,
ref List<byte> trailingBytes,
ref bool sawTerminatingSequence)
{
uint dataRead = 0;
uint availableDataOnPage = dataLength - inPageOffset;
uint startOffsetAdjustment = 0;
if (trailingBytes != null && trailingBytes.Count != 0)
{
// We had trailing bytes on the last page's read, so we need to prepend enough bytes from the start of this read to trailing bytes to check if it forms a terminator
// sequence, and if not copy the bytes over to the output buffer.
// Since we are checking these bytes here make sure if we DON'T form a terminator sequence that the code below doesn't reprocess them. We know that trailingBytes.Count MUST be less
// that terminatingSeqence.Length, if not we would have processed the trailing bytes in the last page and wouldn't see them here.
startOffsetAdjustment = (uint)(terminatingSequence.Length - trailingBytes.Count);
for (int i = 0; i < startOffsetAdjustment; i++)
{
trailingBytes.Add(*((byte*)data + inPageOffset + i));
}
int j = 0;
for (; j < terminatingSequence.Length; j++)
{
if (trailingBytes[j] != terminatingSequence[j])
break;
}
if (j == terminatingSequence.Length)
{
// we matched the whole terminating sequence with the trailing + leading bytes
sawTerminatingSequence = true;
return dataRead;
}
else
{
// We didn't match the terminating sequence
bytesRead.AddRange(trailingBytes);
dataRead += (uint)trailingBytes.Count;
trailingBytes.Clear();
}
}
// If we will have left over bytes (i.e. the amount to read mod the length of the terminating sequence is not 0), then copy then to the trailingBytes buffer so we can
// process them on the next go around if we don't complete the read on this page.
uint leftoverByteCount = ((availableDataOnPage - startOffsetAdjustment) % (uint)terminatingSequence.Length);
if (leftoverByteCount != 0)
{
// We will have straggling bytes if we don't complete the read on this page, so copy them to the trailingBytes list
byte* pDataEnd = ((byte*)data + inPageOffset + availableDataOnPage);
byte* pDataCur = (pDataEnd - leftoverByteCount);
if (trailingBytes == null)
{
trailingBytes = new List<byte>((int)leftoverByteCount);
}
while (pDataCur != pDataEnd)
{
trailingBytes.Add(*pDataCur);
pDataCur++;
}
}
// Account for any bytes we skipped above
availableDataOnPage -= startOffsetAdjustment;
for (uint i = 0 + startOffsetAdjustment; i < availableDataOnPage; i += (uint)terminatingSequence.Length)
{
uint j = 0;
for (; j < terminatingSequence.Length; j++)
{
if (*((byte*)data + inPageOffset + i + j) != terminatingSequence[j])
break;
}
if (j == terminatingSequence.Length)
{
sawTerminatingSequence = true;
break;
}
else
{
for (j = 0; j < terminatingSequence.Length; j++)
{
bytesRead.Add(*((byte*)data + inPageOffset + i + j));
}
dataRead += (uint)terminatingSequence.Length;
}
}
return dataRead;
}