From 05e3dfb267204778138ec39dfe555cca001eaf43 Mon Sep 17 00:00:00 2001 From: Joseph Lennox Date: Sun, 18 Sep 2022 12:43:30 -0700 Subject: [PATCH 1/2] Modernize XmlUTF8TextWriter with u8/inline out's. --- .../src/System/Xml/XmlStreamNodeWriter.cs | 18 ++- .../src/System/Xml/XmlUTF8TextWriter.cs | 135 ++++-------------- 2 files changed, 40 insertions(+), 113 deletions(-) diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs index f5c218aa755c8..033b5e568798e 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs @@ -267,8 +267,7 @@ protected void WriteUTF8Chars(byte[] chars, int charOffset, int charCount) { if (charCount < bufferLength) { - int offset; - byte[] buffer = GetBuffer(charCount, out offset); + byte[] buffer = GetBuffer(charCount, out int offset); Buffer.BlockCopy(chars, charOffset, buffer, offset, charCount); Advance(charCount); } @@ -291,6 +290,21 @@ protected unsafe void WriteUTF8Chars(string value) } } + protected unsafe void WriteUTF8Bytes(ReadOnlySpan value) + { + if (value.Length < bufferLength) + { + byte[] buffer = GetBuffer(value.Length, out int offset); + value.CopyTo(new Span(buffer, offset, buffer.Length)); + Advance(value.Length); + } + else + { + FlushBuffer(); + OutputStream.Write(value); + } + } + protected unsafe void UnsafeWriteUTF8Chars(char* chars, int charCount) { const int charChunkSize = bufferLength / maxBytesPerChar; diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs index 16b9b3d61bd7f..01e80b3d15782 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs @@ -57,10 +57,6 @@ internal class XmlUTF8NodeWriter : XmlStreamNodeWriter private Encoding? _encoding; private char[]? _chars; - private static readonly byte[] s_startDecl = ""u8.ToArray(); - private static readonly byte[] s_utf8Decl = ""u8.ToArray(); - private static ReadOnlySpan Digits => "0123456789ABCDEF"u8; private static readonly bool[] s_defaultIsEscapedAttributeChar = new bool[] @@ -126,64 +122,34 @@ public override void WriteDeclaration() { if (_encoding == null) { - WriteUTF8Chars(s_utf8Decl, 0, s_utf8Decl.Length); + WriteUTF8Bytes(""u8); } else { - WriteUTF8Chars(s_startDecl, 0, s_startDecl.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("'; - 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); } public override void WriteComment(string text) @@ -296,15 +262,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; } @@ -527,62 +485,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("<"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(">"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("&"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("'"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("""u8); } private void WriteHexCharEntity(int ch) @@ -637,36 +560,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)); } @@ -687,22 +605,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)); } @@ -737,16 +652,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)); } } From 30d87145dac7e463730a48a637bae3cc266e2b96 Mon Sep 17 00:00:00 2001 From: Steve Molloy Date: Wed, 22 Mar 2023 15:01:51 -0700 Subject: [PATCH 2/2] PR feedback --- .../src/System/Xml/XmlStreamNodeWriter.cs | 19 ++----------------- .../src/System/Xml/XmlUTF8TextWriter.cs | 14 +++++++------- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs index 033b5e568798e..c8e2818f36b6f 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs @@ -263,21 +263,6 @@ protected unsafe void WriteUTF8Char(int ch) } } - protected void WriteUTF8Chars(byte[] chars, int charOffset, int charCount) - { - if (charCount < bufferLength) - { - byte[] buffer = GetBuffer(charCount, out int 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; @@ -290,12 +275,12 @@ protected unsafe void WriteUTF8Chars(string value) } } - protected unsafe void WriteUTF8Bytes(ReadOnlySpan value) + protected void WriteUTF8Bytes(ReadOnlySpan value) { if (value.Length < bufferLength) { byte[] buffer = GetBuffer(value.Length, out int offset); - value.CopyTo(new Span(buffer, offset, buffer.Length)); + value.CopyTo(buffer.AsSpan(offset)); Advance(value.Length); } else diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs index 01e80b3d15782..b3bcc8b072442 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs @@ -360,7 +360,7 @@ private void WritePrefix(byte[] prefixBuffer, int prefixOffset, int prefixLength } else { - WriteUTF8Chars(prefixBuffer, prefixOffset, prefixLength); + WriteUTF8Bytes(prefixBuffer.AsSpan(prefixOffset, prefixLength)); } } @@ -371,7 +371,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) @@ -430,7 +430,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; } @@ -443,13 +443,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) @@ -459,7 +459,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) @@ -517,7 +517,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)