private bool GetRtElement()
{
// Record a start position (which is AFTER the opening tag).
// Record the INDEX of the buffer rather than the buffer itself;
// advancing to the next marker may occasionally involve growing the buffer.
var startBufIndex = m_currentBufIndex;
var startIndex = m_currentIndex;
bool result = AdvanceToMarkerElement();
var startBuffer = m_buffers[startBufIndex];
// By default the end of the element is right before the opening tag we just found in the input.
var endBuffer = m_currentBuffer;
int limit;
if (result)
limit = m_currentIndex - m_openingMarker.Length;
else
{
// we're doing the last element, which ends (with a </openingTag> that we don't detect) just before the
// closing finalClosingTag. Assuming a basically correct file format, to find the end
// of the closing tag of the last element we need to go back by the length of the final closing tag
// (of the enclosing document).
limit = m_currentIndex - m_finalClosingTag.Length;
}
// Further problem: stepping back might have spanned the buffer boundary
if (limit < 0)
{
endBuffer = startBuffer;
limit += startBuffer.Length;
}
// Move back to the closing > (which, again, may be back into the startBuffer).
while (limit > startIndex || endBuffer != startBuffer)
{
if (limit == 0)
{
endBuffer = startBuffer;
limit = startBuffer.Length;
}
if (endBuffer[limit-1] == closeBracket)
break;
limit--;
}
int count = limit - startIndex;
if (startBuffer != endBuffer)
count = startBuffer.Length - startIndex + limit; // end of startBuffer plus start of endBuffer
byte[] xmlBytes = new byte[count + m_openingMarker.Length];
// startIndex is AFTER the previous match of m_openingMarker, so we need to throw that in.
Array.Copy(m_openingMarker, 0, xmlBytes, 0, m_openingMarker.Length);
if (startBuffer == endBuffer)
{
Array.Copy(startBuffer, startIndex, xmlBytes, m_openingMarker.Length, count);
// In at least one pathological case, we may not yet have freed the other buffer.
int otherBufIndex = NextBuffer(m_currentBufIndex);
if (m_states[otherBufIndex] == BufferStatus.kBeingProcessed)
{
m_states[otherBufIndex] = BufferStatus.kNotInUse;
StartReadingBuffer();
}
}
else
{
Array.Copy(startBuffer, startIndex, xmlBytes, m_openingMarker.Length, startBuffer.Length - startIndex);
Array.Copy(endBuffer, 0, xmlBytes, m_openingMarker.Length + startBuffer.Length - startIndex, limit);
// We've now finished processing startBuffer, so it is free to use for more input.
m_states[NextBuffer(m_currentBufIndex)] = BufferStatus.kNotInUse;
StartReadingBuffer();
}
m_outputHandler(xmlBytes);
return result;
}