public static void WriteEscapedJavaScriptString(TextWriter writer, string?s, char delimiter, bool appendDelimiters,
                                                        bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, IArrayPool <char>?bufferPool, ref char[]?writeBuffer
                                                        )
        {
            // leading delimiter
            if (appendDelimiters)
            {
                writer.Write(delimiter);
            }

            if (!StringUtils.IsNullOrEmpty(s))
            {
                var lastWritePosition = FirstCharToEscape(s, charEscapeFlags, stringEscapeHandling);
                if (lastWritePosition == -1)
                {
                    writer.Write(s);
                }
                else
                {
                    if (lastWritePosition != 0)
                    {
                        if (writeBuffer == null || writeBuffer.Length < lastWritePosition)
                        {
                            writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, lastWritePosition, writeBuffer);
                        }

                        // write unchanged chars at start of text.
                        s.CopyTo(0, writeBuffer, 0, lastWritePosition);
                        writer.Write(writeBuffer, 0, lastWritePosition);
                    }

                    int length;
                    for (var i = lastWritePosition; i < s.Length; i++)
                    {
                        var c = s[i];

                        if (c < charEscapeFlags.Length && !charEscapeFlags[c])
                        {
                            continue;
                        }

                        string?escapedValue;

                        switch (c)
                        {
                        case '\t':
                            escapedValue = @"\t";
                            break;

                        case '\n':
                            escapedValue = @"\n";
                            break;

                        case '\r':
                            escapedValue = @"\r";
                            break;

                        case '\f':
                            escapedValue = @"\f";
                            break;

                        case '\b':
                            escapedValue = @"\b";
                            break;

                        case '\\':
                            escapedValue = @"\\";
                            break;

                        case '\u0085':                                 // Next Line
                            escapedValue = @"\u0085";
                            break;

                        case '\u2028':                                 // Line Separator
                            escapedValue = @"\u2028";
                            break;

                        case '\u2029':                                 // Paragraph Separator
                            escapedValue = @"\u2029";
                            break;

                        default:
                            if (c < charEscapeFlags.Length || stringEscapeHandling == StringEscapeHandling.EscapeNonAscii)
                            {
                                if (c == '\'' && stringEscapeHandling != StringEscapeHandling.EscapeHtml)
                                {
                                    escapedValue = @"\'";
                                }
                                else if (c == '"' && stringEscapeHandling != StringEscapeHandling.EscapeHtml)
                                {
                                    escapedValue = @"\""";
                                }
                                else
                                {
                                    if (writeBuffer == null || writeBuffer.Length < UnicodeTextLength)
                                    {
                                        writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, UnicodeTextLength, writeBuffer);
                                    }

                                    StringUtils.ToCharAsUnicode(c, writeBuffer !);

                                    // slightly hacky but it saves multiple conditions in if test
                                    escapedValue = EscapedUnicodeText;
                                }
                            }
                            else
                            {
                                escapedValue = null;
                            }
                            break;
                        }

                        if (escapedValue == null)
                        {
                            continue;
                        }

                        var isEscapedUnicodeText = string.Equals(escapedValue, EscapedUnicodeText, StringComparison.Ordinal);

                        if (i > lastWritePosition)
                        {
                            length = i - lastWritePosition + (isEscapedUnicodeText ? UnicodeTextLength : 0);
                            var start = isEscapedUnicodeText ? UnicodeTextLength : 0;

                            if (writeBuffer == null || writeBuffer.Length < length)
                            {
                                var newBuffer = BufferUtils.RentBuffer(bufferPool, length);

                                // the unicode text is already in the buffer
                                // copy it over when creating new buffer
                                if (isEscapedUnicodeText)
                                {
                                    MiscellaneousUtils.Assert(writeBuffer != null,
                                                              "Write buffer should never be null because it is set when the escaped unicode text is encountered.");

                                    Array.Copy(writeBuffer, newBuffer, UnicodeTextLength);
                                }

                                BufferUtils.ReturnBuffer(bufferPool, writeBuffer);

                                writeBuffer = newBuffer;
                            }

                            s.CopyTo(lastWritePosition, writeBuffer, start, length - start);

                            // write unchanged chars before writing escaped text
                            writer.Write(writeBuffer, start, length - start);
                        }

                        lastWritePosition = i + 1;
                        if (!isEscapedUnicodeText)
                        {
                            writer.Write(escapedValue);
                        }
                        else
                        {
                            writer.Write(writeBuffer, 0, UnicodeTextLength);
                        }
                    }

                    MiscellaneousUtils.Assert(lastWritePosition != 0);
                    length = s.Length - lastWritePosition;
                    if (length > 0)
                    {
                        if (writeBuffer == null || writeBuffer.Length < length)
                        {
                            writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, length, writeBuffer);
                        }

                        s.CopyTo(lastWritePosition, writeBuffer, 0, length);

                        // write remaining text
                        writer.Write(writeBuffer, 0, length);
                    }
                }
            }

            // trailing delimiter
            if (appendDelimiters)
            {
                writer.Write(delimiter);
            }
        }
Example #2
0
 public StringBuffer(IArrayPool <char>?bufferPool, int initalSize) : this(BufferUtils.RentBuffer(bufferPool, initalSize))
 {
 }