Skip to content

Commit

Permalink
Modernize XmlUTF8TextWriter with u8/inline out's. (#75812)
Browse files Browse the repository at this point in the history
* Modernize XmlUTF8TextWriter with u8/inline out's.

* PR feedback

---------

Co-authored-by: Steve Molloy <smolloy@microsoft.com>
  • Loading branch information
jlennox and StephenMolloy committed Mar 27, 2023
1 parent b1fbb80 commit 47cd24e
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 134 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -263,22 +263,6 @@ protected unsafe void WriteUTF8Char(int ch)
}
}

protected void WriteUTF8Chars(byte[] chars, int charOffset, int charCount)
{
if (charCount < bufferLength)
{
int offset;
byte[] buffer = GetBuffer(charCount, out offset);
Buffer.BlockCopy(chars, charOffset, buffer, offset, charCount);
Advance(charCount);
}
else
{
FlushBuffer();
OutputStream.Write(chars, charOffset, charCount);
}
}

protected unsafe void WriteUTF8Chars(string value)
{
int count = value.Length;
Expand All @@ -291,6 +275,21 @@ protected unsafe void WriteUTF8Chars(string value)
}
}

protected void WriteUTF8Bytes(ReadOnlySpan<byte> value)
{
if (value.Length < bufferLength)
{
byte[] buffer = GetBuffer(value.Length, out int offset);
value.CopyTo(buffer.AsSpan(offset));
Advance(value.Length);
}
else
{
FlushBuffer();
OutputStream.Write(value);
}
}

protected unsafe void UnsafeWriteUTF8Chars(char* chars, int charCount)
{
const int charChunkSize = bufferLength / maxBytesPerChar;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,6 @@ internal class XmlUTF8NodeWriter : XmlStreamNodeWriter
private Encoding? _encoding;
private char[]? _chars;

private static readonly byte[] s_startDecl = "<?xml version=\"1.0\" encoding=\""u8.ToArray();
private static readonly byte[] s_endDecl = "\"?>"u8.ToArray();
private static readonly byte[] s_utf8Decl = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"u8.ToArray();

private static ReadOnlySpan<byte> Digits => "0123456789ABCDEF"u8;

private static readonly bool[] s_defaultIsEscapedAttributeChar = new bool[]
Expand Down Expand Up @@ -127,64 +123,34 @@ public override void WriteDeclaration()
{
if (_encoding == null)
{
WriteUTF8Chars(s_utf8Decl, 0, s_utf8Decl.Length);
WriteUTF8Bytes("<?xml version=\"1.0\" encoding=\"utf-8\"?>"u8);
}
else
{
WriteUTF8Chars(s_startDecl, 0, s_startDecl.Length);
WriteUTF8Bytes("<?xml version=\"1.0\" encoding=\""u8);
if (_encoding.WebName == Encoding.BigEndianUnicode.WebName)
WriteUTF8Chars("utf-16BE");
WriteUTF8Bytes("utf-16BE"u8);
else
WriteUTF8Chars(_encoding.WebName);
WriteUTF8Chars(s_endDecl, 0, s_endDecl.Length);
WriteUTF8Bytes("\"?>"u8);
}
}

public override void WriteCData(string text)
{
byte[] buffer;
int offset;

buffer = GetBuffer(9, out offset);
buffer[offset + 0] = (byte)'<';
buffer[offset + 1] = (byte)'!';
buffer[offset + 2] = (byte)'[';
buffer[offset + 3] = (byte)'C';
buffer[offset + 4] = (byte)'D';
buffer[offset + 5] = (byte)'A';
buffer[offset + 6] = (byte)'T';
buffer[offset + 7] = (byte)'A';
buffer[offset + 8] = (byte)'[';
Advance(9);

WriteUTF8Bytes("<![CDATA["u8);
WriteUTF8Chars(text);

buffer = GetBuffer(3, out offset);
buffer[offset + 0] = (byte)']';
buffer[offset + 1] = (byte)']';
buffer[offset + 2] = (byte)'>';
Advance(3);
WriteUTF8Bytes("]]>"u8);
}

private void WriteStartComment()
{
int offset;
byte[] buffer = GetBuffer(4, out offset);
buffer[offset + 0] = (byte)'<';
buffer[offset + 1] = (byte)'!';
buffer[offset + 2] = (byte)'-';
buffer[offset + 3] = (byte)'-';
Advance(4);
WriteUTF8Bytes("<!--"u8);
}

private void WriteEndComment()
{
int offset;
byte[] buffer = GetBuffer(3, out offset);
buffer[offset + 0] = (byte)'-';
buffer[offset + 1] = (byte)'-';
buffer[offset + 2] = (byte)'>';
Advance(3);
WriteUTF8Bytes("-->"u8);
}

public override void WriteComment(string text)
Expand Down Expand Up @@ -297,15 +263,7 @@ public override void WriteEndElement(byte[] prefixBuffer, int prefixOffset, int

private void WriteStartXmlnsAttribute()
{
int offset;
byte[] buffer = GetBuffer(6, out offset);
buffer[offset + 0] = (byte)' ';
buffer[offset + 1] = (byte)'x';
buffer[offset + 2] = (byte)'m';
buffer[offset + 3] = (byte)'l';
buffer[offset + 4] = (byte)'n';
buffer[offset + 5] = (byte)'s';
Advance(6);
WriteUTF8Bytes(" xmlns"u8);
_inAttribute = true;
}

Expand Down Expand Up @@ -403,7 +361,7 @@ private void WritePrefix(byte[] prefixBuffer, int prefixOffset, int prefixLength
}
else
{
WriteUTF8Chars(prefixBuffer, prefixOffset, prefixLength);
WriteUTF8Bytes(prefixBuffer.AsSpan(prefixOffset, prefixLength));
}
}

Expand All @@ -414,7 +372,7 @@ private void WriteLocalName(string localName)

private void WriteLocalName(byte[] localNameBuffer, int localNameOffset, int localNameLength)
{
WriteUTF8Chars(localNameBuffer, localNameOffset, localNameLength);
WriteUTF8Bytes(localNameBuffer.AsSpan(localNameOffset, localNameLength));
}

public override void WriteEscapedText(XmlDictionaryString s)
Expand Down Expand Up @@ -473,7 +431,7 @@ public override void WriteEscapedText(byte[] chars, int offset, int count)
byte ch = chars[offset + j];
if (ch < isEscapedCharLength && isEscapedChar[ch])
{
WriteUTF8Chars(chars, offset + i, j - i);
WriteUTF8Bytes(chars.AsSpan(offset + i, j - i));
WriteCharEntity(ch);
i = j + 1;
}
Expand All @@ -486,13 +444,13 @@ public override void WriteEscapedText(byte[] chars, int offset, int count)
byte ch3 = chars[offset + j + 2];
if (ch2 == 191 && (ch3 == 190 || ch3 == 191))
{
WriteUTF8Chars(chars, offset + i, j - i);
WriteUTF8Bytes(chars.AsSpan(offset + i, j - i));
WriteCharEntity(ch3 == 190 ? (char)0xFFFE : (char)0xFFFF);
i = j + 3;
}
}
}
WriteUTF8Chars(chars, offset + i, count - i);
WriteUTF8Bytes(chars.AsSpan(offset + i, count - i));
}

public void WriteText(int ch)
Expand All @@ -502,7 +460,7 @@ public void WriteText(int ch)

public override void WriteText(byte[] chars, int offset, int count)
{
WriteUTF8Chars(chars, offset, count);
WriteUTF8Bytes(chars.AsSpan(offset, count));
}

public override unsafe void WriteText(char[] chars, int offset, int count)
Expand All @@ -528,62 +486,27 @@ public override void WriteText(XmlDictionaryString value)

public void WriteLessThanCharEntity()
{
int offset;
byte[] buffer = GetBuffer(4, out offset);
buffer[offset + 0] = (byte)'&';
buffer[offset + 1] = (byte)'l';
buffer[offset + 2] = (byte)'t';
buffer[offset + 3] = (byte)';';
Advance(4);
WriteUTF8Bytes("&lt;"u8);
}

public void WriteGreaterThanCharEntity()
{
int offset;
byte[] buffer = GetBuffer(4, out offset);
buffer[offset + 0] = (byte)'&';
buffer[offset + 1] = (byte)'g';
buffer[offset + 2] = (byte)'t';
buffer[offset + 3] = (byte)';';
Advance(4);
WriteUTF8Bytes("&gt;"u8);
}

public void WriteAmpersandCharEntity()
{
int offset;
byte[] buffer = GetBuffer(5, out offset);
buffer[offset + 0] = (byte)'&';
buffer[offset + 1] = (byte)'a';
buffer[offset + 2] = (byte)'m';
buffer[offset + 3] = (byte)'p';
buffer[offset + 4] = (byte)';';
Advance(5);
WriteUTF8Bytes("&amp;"u8);
}

public void WriteApostropheCharEntity()
{
int offset;
byte[] buffer = GetBuffer(6, out offset);
buffer[offset + 0] = (byte)'&';
buffer[offset + 1] = (byte)'a';
buffer[offset + 2] = (byte)'p';
buffer[offset + 3] = (byte)'o';
buffer[offset + 4] = (byte)'s';
buffer[offset + 5] = (byte)';';
Advance(6);
WriteUTF8Bytes("&apos;"u8);
}

public void WriteQuoteCharEntity()
{
int offset;
byte[] buffer = GetBuffer(6, out offset);
buffer[offset + 0] = (byte)'&';
buffer[offset + 1] = (byte)'q';
buffer[offset + 2] = (byte)'u';
buffer[offset + 3] = (byte)'o';
buffer[offset + 4] = (byte)'t';
buffer[offset + 5] = (byte)';';
Advance(6);
WriteUTF8Bytes("&quot;"u8);
}

private void WriteHexCharEntity(int ch)
Expand All @@ -595,7 +518,7 @@ private void WriteHexCharEntity(int ch)
chars[--offset] = (byte)'x';
chars[--offset] = (byte)'#';
chars[--offset] = (byte)'&';
WriteUTF8Chars(chars, offset, maxEntityLength - offset);
WriteUTF8Bytes(chars.AsSpan(offset, maxEntityLength - offset));
}

public override void WriteCharEntity(int ch)
Expand Down Expand Up @@ -638,36 +561,31 @@ private static int ToBase16(byte[] chars, int offset, uint value)

public override void WriteBoolText(bool value)
{
int offset;
byte[] buffer = GetBuffer(XmlConverter.MaxBoolChars, out offset);
byte[] buffer = GetBuffer(XmlConverter.MaxBoolChars, out int offset);
Advance(XmlConverter.ToChars(value, buffer, offset));
}

public override void WriteDecimalText(decimal value)
{
int offset;
byte[] buffer = GetBuffer(XmlConverter.MaxDecimalChars, out offset);
byte[] buffer = GetBuffer(XmlConverter.MaxDecimalChars, out int offset);
Advance(XmlConverter.ToChars(value, buffer, offset));
}

public override void WriteDoubleText(double value)
{
int offset;
byte[] buffer = GetBuffer(XmlConverter.MaxDoubleChars, out offset);
byte[] buffer = GetBuffer(XmlConverter.MaxDoubleChars, out int offset);
Advance(XmlConverter.ToChars(value, buffer, offset));
}

public override void WriteFloatText(float value)
{
int offset;
byte[] buffer = GetBuffer(XmlConverter.MaxFloatChars, out offset);
byte[] buffer = GetBuffer(XmlConverter.MaxFloatChars, out int offset);
Advance(XmlConverter.ToChars(value, buffer, offset));
}

public override void WriteDateTimeText(DateTime value)
{
int offset;
byte[] buffer = GetBuffer(XmlConverter.MaxDateTimeChars, out offset);
byte[] buffer = GetBuffer(XmlConverter.MaxDateTimeChars, out int offset);
Advance(XmlConverter.ToChars(value, buffer, offset));
}

Expand All @@ -688,22 +606,19 @@ public override void WriteUniqueIdText(UniqueId value)

public override void WriteInt32Text(int value)
{
int offset;
byte[] buffer = GetBuffer(XmlConverter.MaxInt32Chars, out offset);
byte[] buffer = GetBuffer(XmlConverter.MaxInt32Chars, out int offset);
Advance(XmlConverter.ToChars(value, buffer, offset));
}

public override void WriteInt64Text(long value)
{
int offset;
byte[] buffer = GetBuffer(XmlConverter.MaxInt64Chars, out offset);
byte[] buffer = GetBuffer(XmlConverter.MaxInt64Chars, out int offset);
Advance(XmlConverter.ToChars(value, buffer, offset));
}

public override void WriteUInt64Text(ulong value)
{
int offset;
byte[] buffer = GetBuffer(XmlConverter.MaxUInt64Chars, out offset);
byte[] buffer = GetBuffer(XmlConverter.MaxUInt64Chars, out int offset);
Advance(XmlConverter.ToChars(value, buffer, offset));
}

Expand Down Expand Up @@ -738,16 +653,14 @@ private void InternalWriteBase64Text(byte[] buffer, int offset, int count)
{
int byteCount = Math.Min(bufferLength / 4 * 3, count - count % 3);
int charCount = byteCount / 3 * 4;
int charOffset;
byte[] chars = GetBuffer(charCount, out charOffset);
byte[] chars = GetBuffer(charCount, out int charOffset);
Advance(encoding.GetChars(buffer, offset, byteCount, chars, charOffset));
offset += byteCount;
count -= byteCount;
}
if (count > 0)
{
int charOffset;
byte[] chars = GetBuffer(4, out charOffset);
byte[] chars = GetBuffer(4, out int charOffset);
Advance(encoding.GetChars(buffer, offset, count, chars, charOffset));
}
}
Expand Down

0 comments on commit 47cd24e

Please sign in to comment.