private unsafe void WriteStringUnsafe(string value) { Debug.Assert(value != null); string indentation = null; var pendingIndentation = false; int offset = 0; while (true) { fixed(char *pSrcStart = value) { offset += WriteStringUnsafe(pSrcStart + offset, pSrcStart + value.Length); } if (pendingIndentation) { WriteRawUnsafe(indentation); pendingIndentation = false; } else { break; } } int WriteStringUnsafe(char *pSrcStart, char *pSrcEnd) { fixed(char *pDstStart = _bufChars) { char *pDst = pDstStart + _bufPos; char *pSrc = pSrcStart; int ch = 0; do { char *pDstEnd = pDst + (pSrcEnd - pSrc); if (pDstEnd > pDstStart + _bufLen) { pDstEnd = pDstStart + _bufLen; } while (pDst < pDstEnd) { ch = *pSrc; if (ch == 10 || ch == 13 || Escaper.ShouldBeEscaped((char)ch)) { break; } pSrc++; *pDst = (char)ch; pDst++; Length++; } if (pSrc >= pSrcEnd) { break; } if (pDst >= pDstEnd) { _bufPos = (int)(pDst - pDstStart); FlushBuffer(); pDst = pDstStart; continue; } switch (ch) { case (char)10: { OnBeforeWriteLine(); switch (NewLineHandling) { case NewLineHandling.Replace: { pDst = WriteRaw(NewLineChars, pDst); break; } case NewLineHandling.None: { *pDst = (char)ch; pDst++; Length++; break; } } OnAfterWriteLine(); if (IsPendingIndentation()) { pendingIndentation = true; } break; } case (char)13: { OnBeforeWriteLine(); switch (NewLineHandling) { case NewLineHandling.Replace: { if (pSrc < pSrcEnd && pSrc[1] == '\n') { pSrc++; } pDst = WriteRaw(NewLineChars, pDst); break; } case NewLineHandling.None: { *pDst = (char)ch; pDst++; Length++; break; } } OnAfterWriteLine(); if (IsPendingIndentation()) { pendingIndentation = true; } break; } case '>': case '<': { string escapedChar = EscapeChar(ch); pDst = WriteRaw(escapedChar, pDst); break; } default: { *pDst = MarkdownCharEscaper.DefaultEscapingChar; pDst++; Length++; *pDst = (char)ch; pDst++; Length++; break; } } pSrc++; } while (!pendingIndentation); _bufPos = (int)(pDst - pDstStart); return((int)(pSrc - pSrcStart)); } char *WriteRaw(string text, char *pDst) { fixed(char *pDstStart = _bufChars) { _bufPos = (int)(pDst - pDstStart); WriteRawUnsafe(text); return(pDstStart + _bufPos); } } } bool IsPendingIndentation() { if (indentation == null) { indentation = base.GetIndentation(); } return(indentation.Length > 0); } }
public override void WriteString(string text) { string indentation = null; try { BeforeWriteString(); ThrowIfClosed(); if (string.IsNullOrEmpty(text)) { return; } int length = text.Length; int prev = 0; int i = 0; while (i < length) { char ch = text[i]; switch (ch) { case '\n': { OnBeforeWriteLine(); if (NewLineHandling == NewLineHandling.Replace) { WriteSubstring(text, prev, i - prev); WriteNewLine(); } else if (NewLineHandling == NewLineHandling.None) { WriteSubstring(text, prev, i + 1 - prev); } OnAfterWriteLine(); WriteIndentation(); prev = ++i; continue; } case '\r': { OnBeforeWriteLine(); if (i < length - 1 && text[i + 1] == 10) { if (NewLineHandling == NewLineHandling.Replace) { WriteSubstring(text, prev, i - prev); WriteNewLine(); } else if (NewLineHandling == NewLineHandling.None) { WriteSubstring(text, prev, i + 2 - prev); } i++; } else if (NewLineHandling == NewLineHandling.Replace) { WriteSubstring(text, prev, i - prev); WriteNewLine(); } else if (NewLineHandling == NewLineHandling.None) { WriteSubstring(text, prev, i + 1 - prev); } OnAfterWriteLine(); WriteIndentation(); prev = ++i; continue; } case '<': case '>': { if (Escaper.ShouldBeEscaped(ch)) { WriteSubstring(text, prev, i - prev); WriteString(EscapeChar(ch)); prev = ++i; } else { i++; } continue; } } if (Escaper.ShouldBeEscaped(ch)) { WriteSubstring(text, prev, i - prev); WriteChar(MarkdownCharEscaper.DefaultEscapingChar); WriteChar(ch); prev = ++i; } else { i++; } } WriteSubstring(text, prev, text.Length - prev); } catch { _state = State.Error; throw; } void WriteString(string value) { ThrowIfClosed(); _sb.Append(value); } void WriteSubstring(string value, int startIndex, int count) { ThrowIfClosed(); _sb.Append(value, startIndex, count); } void WriteChar(char ch) { ThrowIfClosed(); _sb.Append(ch); } void WriteNewLine() { ThrowIfClosed(); _sb.Append(NewLineChars); } void WriteIndentation() { if (indentation == null) { indentation = GetIndentation(); } _sb.Append(indentation); } }