示例#1
0
        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);
            }
        }