private static unsafe uint ProcessPageForSequenceTerminatingRead()

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;
        }