diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Base64Decoder.cs b/src/libraries/System.Private.Xml/src/System/Xml/Base64Decoder.cs index 96375e646f274..d21d89e9e6ae7 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Base64Decoder.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Base64Decoder.cs @@ -42,7 +42,7 @@ internal override bool IsFull } } - internal override unsafe int Decode(char[] chars, int startPos, int len) + internal override int Decode(char[] chars, int startPos, int len) { if (chars == null) { @@ -65,19 +65,14 @@ internal override unsafe int Decode(char[] chars, int startPos, int len) { return 0; } - int bytesDecoded, charsDecoded; - fixed (char* pChars = &chars[startPos]) - { - fixed (byte* pBytes = &_buffer![_curIndex]) - { - Decode(pChars, pChars + len, pBytes, pBytes + (_endIndex - _curIndex), out charsDecoded, out bytesDecoded); - } - } + + Decode(chars.AsSpan(startPos, len), _buffer.AsSpan(_curIndex, _endIndex - _curIndex), out int charsDecoded, out int bytesDecoded); + _curIndex += bytesDecoded; return charsDecoded; } - internal override unsafe int Decode(string str, int startPos, int len) + internal override int Decode(string str, int startPos, int len) { if (str == null) { @@ -101,14 +96,7 @@ internal override unsafe int Decode(string str, int startPos, int len) return 0; } - int bytesDecoded, charsDecoded; - fixed (char* pChars = str) - { - fixed (byte* pBytes = &_buffer![_curIndex]) - { - Decode(pChars + startPos, pChars + startPos + len, pBytes, pBytes + (_endIndex - _curIndex), out charsDecoded, out bytesDecoded); - } - } + Decode(str.AsSpan(startPos, len), _buffer.AsSpan(_curIndex, _endIndex - _curIndex), out int charsDecoded, out int bytesDecoded); _curIndex += bytesDecoded; return charsDecoded; @@ -151,29 +139,28 @@ private static byte[] ConstructMapBase64() return mapBase64; } - private unsafe void Decode(char* pChars, char* pCharsEndPos, - byte* pBytes, byte* pBytesEndPos, - out int charsDecoded, out int bytesDecoded) + private void Decode(ReadOnlySpan chars, Span bytes, out int charsDecoded, out int bytesDecoded) { -#if DEBUG - Debug.Assert(pCharsEndPos - pChars >= 0); - Debug.Assert(pBytesEndPos - pBytes >= 0); -#endif - // walk hex digits pairing them up and shoving the value of each pair into a byte - byte* pByte = pBytes; - char* pChar = pChars; + int iByte = 0; + int iChar = 0; int b = _bits; int bFilled = _bitsFilled; - while (pChar < pCharsEndPos && pByte < pBytesEndPos) + + while ((uint)iChar < (uint)chars.Length) { - char ch = *pChar; + if ((uint)iByte >= (uint)bytes.Length) + { + break; // ran out of space in the destination buffer + } + + char ch = chars[iChar]; // end? if (ch == '=') { break; } - pChar++; + iChar++; // ignore whitespace if (XmlCharType.IsWhiteSpace(ch)) @@ -184,7 +171,7 @@ private unsafe void Decode(char* pChars, char* pCharsEndPos, int digit; if (ch > 122 || (digit = s_mapBase64[ch]) == Invalid) { - throw new XmlException(SR.Xml_InvalidBase64Value, new string(pChars, 0, (int)(pCharsEndPos - pChars))); + throw new XmlException(SR.Xml_InvalidBase64Value, chars.ToString()); } b = (b << 6) | digit; @@ -193,35 +180,32 @@ private unsafe void Decode(char* pChars, char* pCharsEndPos, if (bFilled >= 8) { // get top eight valid bits - *pByte++ = (byte)((b >> (bFilled - 8)) & 0xFF); + bytes[iByte++] = (byte)((b >> (bFilled - 8)) & 0xFF); bFilled -= 8; - if (pByte == pBytesEndPos) + if (iByte == bytes.Length) { goto Return; } } } - if (pChar < pCharsEndPos && *pChar == '=') + if ((uint)iChar < (uint)chars.Length && chars[iChar] == '=') { bFilled = 0; // ignore padding chars do { - pChar++; - } while (pChar < pCharsEndPos && *pChar == '='); + iChar++; + } while ((uint)iChar < (uint)chars.Length && chars[iChar] == '='); // ignore whitespace after the padding chars - if (pChar < pCharsEndPos) + while ((uint)iChar < (uint)chars.Length) { - do + if (!XmlCharType.IsWhiteSpace(chars[iChar++])) { - if (!XmlCharType.IsWhiteSpace(*pChar++)) - { - throw new XmlException(SR.Xml_InvalidBase64Value, new string(pChars, 0, (int)(pCharsEndPos - pChars))); - } - } while (pChar < pCharsEndPos); + throw new XmlException(SR.Xml_InvalidBase64Value, chars.ToString()); + } } } @@ -229,8 +213,8 @@ private unsafe void Decode(char* pChars, char* pCharsEndPos, _bits = b; _bitsFilled = bFilled; - bytesDecoded = (int)(pByte - pBytes); - charsDecoded = (int)(pChar - pChars); + bytesDecoded = iByte; + charsDecoded = iChar; } } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/BinHexDecoder.cs b/src/libraries/System.Private.Xml/src/System/Xml/BinHexDecoder.cs index 058621d26563d..32ca96a647d6e 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/BinHexDecoder.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/BinHexDecoder.cs @@ -37,7 +37,7 @@ internal override bool IsFull } } - internal override unsafe int Decode(char[] chars, int startPos, int len) + internal override int Decode(char[] chars, int startPos, int len) { if (chars == null) { @@ -61,20 +61,15 @@ internal override unsafe int Decode(char[] chars, int startPos, int len) return 0; } - int bytesDecoded, charsDecoded; - fixed (char* pChars = &chars[startPos]) - { - fixed (byte* pBytes = &_buffer![_curIndex]) - { - Decode(pChars, pChars + len, pBytes, pBytes + (_endIndex - _curIndex), - ref _hasHalfByteCached, ref _cachedHalfByte, out charsDecoded, out bytesDecoded); - } - } + Decode(chars.AsSpan(startPos, len), _buffer.AsSpan(_curIndex, _endIndex - _curIndex), + ref _hasHalfByteCached, ref _cachedHalfByte, + out int charsDecoded, out int bytesDecoded); + _curIndex += bytesDecoded; return charsDecoded; } - internal override unsafe int Decode(string str, int startPos, int len) + internal override int Decode(string str, int startPos, int len) { if (str == null) { @@ -98,15 +93,9 @@ internal override unsafe int Decode(string str, int startPos, int len) return 0; } - int bytesDecoded, charsDecoded; - fixed (char* pChars = str) - { - fixed (byte* pBytes = &_buffer![_curIndex]) - { - Decode(pChars + startPos, pChars + startPos + len, pBytes, pBytes + (_endIndex - _curIndex), - ref _hasHalfByteCached, ref _cachedHalfByte, out charsDecoded, out bytesDecoded); - } - } + Decode(str.AsSpan(startPos, len), _buffer.AsSpan(_curIndex, _endIndex - _curIndex), + ref _hasHalfByteCached, ref _cachedHalfByte, + out int charsDecoded, out int bytesDecoded); _curIndex += bytesDecoded; return charsDecoded; @@ -135,7 +124,7 @@ internal override void SetNextOutputBuffer(Array buffer, int index, int count) // // Static methods // - public static unsafe byte[] Decode(char[] chars, bool allowOddChars) + public static byte[] Decode(char[] chars, bool allowOddChars) { if (chars == null) { @@ -149,17 +138,10 @@ public static unsafe byte[] Decode(char[] chars, bool allowOddChars) } byte[] bytes = new byte[(len + 1) / 2]; - int bytesDecoded, charsDecoded; bool hasHalfByteCached = false; byte cachedHalfByte = 0; - fixed (char* pChars = &chars[0]) - { - fixed (byte* pBytes = &bytes[0]) - { - Decode(pChars, pChars + len, pBytes, pBytes + bytes.Length, ref hasHalfByteCached, ref cachedHalfByte, out charsDecoded, out bytesDecoded); - } - } + Decode(chars, bytes, ref hasHalfByteCached, ref cachedHalfByte, out int charsDecoded, out int bytesDecoded); if (hasHalfByteCached && !allowOddChars) { @@ -168,9 +150,7 @@ public static unsafe byte[] Decode(char[] chars, bool allowOddChars) if (bytesDecoded < bytes.Length) { - byte[] tmp = new byte[bytesDecoded]; - Buffer.BlockCopy(bytes, 0, tmp, 0, bytesDecoded); - bytes = tmp; + Array.Resize(ref bytes, bytesDecoded); } return bytes; @@ -180,22 +160,23 @@ public static unsafe byte[] Decode(char[] chars, bool allowOddChars) // Private methods // - private static unsafe void Decode(char* pChars, char* pCharsEndPos, - byte* pBytes, byte* pBytesEndPos, - ref bool hasHalfByteCached, ref byte cachedHalfByte, - out int charsDecoded, out int bytesDecoded) + private static void Decode(ReadOnlySpan chars, + Span bytes, + ref bool hasHalfByteCached, ref byte cachedHalfByte, + out int charsDecoded, out int bytesDecoded) { -#if DEBUG - Debug.Assert(pCharsEndPos - pChars >= 0); - Debug.Assert(pBytesEndPos - pBytes >= 0); -#endif + int iByte = 0; + int iChar = 0; - char* pChar = pChars; - byte* pByte = pBytes; - while (pChar < pCharsEndPos && pByte < pBytesEndPos) + for (; iChar < chars.Length; iChar++) { + if ((uint)iByte >= (uint)bytes.Length) + { + break; // ran out of space in the destination buffer + } + byte halfByte; - char ch = *pChar++; + char ch = chars[iChar]; int val = HexConverter.FromChar(ch); if (val != 0xFF) @@ -208,12 +189,12 @@ private static unsafe void Decode(char* pChars, char* pCharsEndPos, } else { - throw new XmlException(SR.Xml_InvalidBinHexValue, new string(pChars, 0, (int)(pCharsEndPos - pChars))); + throw new XmlException(SR.Xml_InvalidBinHexValue, chars.ToString()); } if (hasHalfByteCached) { - *pByte++ = (byte)((cachedHalfByte << 4) + halfByte); + bytes[iByte++] = (byte)((cachedHalfByte << 4) + halfByte); hasHalfByteCached = false; } else @@ -223,8 +204,8 @@ private static unsafe void Decode(char* pChars, char* pCharsEndPos, } } - bytesDecoded = (int)(pByte - pBytes); - charsDecoded = (int)(pChar - pChars); + bytesDecoded = iByte; + charsDecoded = iChar; } } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs b/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs index b71e205b6d08e..eab6cb679f3da 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs @@ -3,12 +3,12 @@ using System; using System.Buffers.Binary; -using System.Collections; using System.Collections.Generic; -using System.IO; -using System.Text; using System.Diagnostics; using System.Globalization; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; using System.Xml.Schema; namespace System.Xml @@ -334,15 +334,11 @@ public NestedBinXml(SymbolTables symbolTables, int docState, NestedBinXml? next) private readonly bool _ignoreComments; private readonly DtdProcessing _dtdProcessing; - private readonly Encoding _unicode; - // current version of the protocol private byte _version; public XmlSqlBinaryReader(Stream stream, byte[] data, int len, string baseUri, bool closeInput, XmlReaderSettings settings) { - _unicode = System.Text.Encoding.Unicode; - _xnt = settings.NameTable!; if (_xnt == null) { @@ -2350,28 +2346,21 @@ private int ScanText(out int start) private string GetString(int pos, int cch) { Debug.Assert(pos >= 0 && cch >= 0); - if (checked(pos + (cch * 2)) > _end) + if (checked(pos + (cch * sizeof(char))) > _end) throw new XmlException(SR.Xml_UnexpectedEOF1, (string[]?)null); if (cch == 0) return string.Empty; - // GetStringUnaligned is _significantly_ faster than unicode.GetString() - // but since IA64 doesn't support unaligned reads, we can't do it if - // the address is not aligned properly. Since the byte[] will be aligned, - // we can detect address alignment my just looking at the offset - if ((pos & 1) == 0) - return GetStringAligned(_data, pos, cch); - else - return _unicode.GetString(_data, pos, checked(cch * 2)); - } - private unsafe string GetStringAligned(byte[] data, int offset, int cch) - { - Debug.Assert((offset & 1) == 0); - fixed (byte* pb = data) + return string.Create(cch, (_data, pos), static (dstChars, state) => { - char* p = (char*)(pb + offset); - return new string(p, 0, cch); - } + // bitblt source bytes directly into the destination char span + // n.b. source buffer assumed to be well-formed UTF-16 machine endian + + int cch = dstChars.Length; + ReadOnlySpan srcBytes = state._data.AsSpan(state.pos, checked(cch * sizeof(char))); + Span dstBytes = MemoryMarshal.AsBytes(dstChars); + srcBytes.CopyTo(dstBytes); + }); } private string GetAttributeText(int i) @@ -3524,63 +3513,55 @@ private XmlNodeType ScanOverAnyValue(BinXmlToken token, bool attr, bool checkCha return XmlNodeType.Text; } - private unsafe XmlNodeType CheckText(bool attr) + private XmlNodeType CheckText(bool attr) { Debug.Assert(_checkCharacters, "this.checkCharacters"); - // assert that size is an even number - Debug.Assert(0 == ((_pos - _tokDataPos) & 1), "Data size should not be odd"); // grab local copy (perf) - fixed (byte* pb = _data) - { - int end = _pos; - int pos = _tokDataPos; + ReadOnlySpan data = _data.AsSpan(_tokDataPos, _end - _tokDataPos); + Debug.Assert(data.Length % 2 == 0, "Data size should not be odd"); - if (!attr) + if (!attr) + { + // scan if this is whitespace + while (true) { - // scan if this is whitespace - while (true) - { - int posNext = pos + 2; - if (posNext > end) - return _xmlspacePreserve ? XmlNodeType.SignificantWhitespace : XmlNodeType.Whitespace; - if (pb[pos + 1] != 0 || !XmlCharType.IsWhiteSpace((char)pb[pos])) - break; - pos = posNext; - } + if (!BinaryPrimitives.TryReadUInt16LittleEndian(data, out ushort value)) + return _xmlspacePreserve ? XmlNodeType.SignificantWhitespace : XmlNodeType.Whitespace; + if (value > byte.MaxValue || !XmlCharType.IsWhiteSpace((char)value)) + break; + data = data.Slice(2); // we consumed one ANSI whitespace char } + } + while (true) + { + char ch; while (true) { - char ch; - while (true) - { - int posNext = pos + 2; - if (posNext > end) - return XmlNodeType.Text; - ch = (char)(pb[pos] | ((int)(pb[pos + 1]) << 8)); - if (!XmlCharType.IsCharData(ch)) - break; - pos = posNext; - } + if (!BinaryPrimitives.TryReadUInt16LittleEndian(data, out ushort value)) + return XmlNodeType.Text; + data = data.Slice(2); // we consumed one char (possibly a high surrogate) + ch = (char)value; + if (!XmlCharType.IsCharData(ch)) + break; + } - if (!XmlCharType.IsHighSurrogate(ch)) + if (!XmlCharType.IsHighSurrogate(ch)) + { + throw XmlConvert.CreateInvalidCharException(ch, '\0', ExceptionType.XmlException); + } + else + { + if (!BinaryPrimitives.TryReadUInt16LittleEndian(data, out ushort lowSurr)) { - throw XmlConvert.CreateInvalidCharException(ch, '\0', ExceptionType.XmlException); + throw ThrowXmlException(SR.Xml_InvalidSurrogateMissingLowChar); } - else + if (!XmlCharType.IsLowSurrogate((char)lowSurr)) { - if ((pos + 4) > end) - { - throw ThrowXmlException(SR.Xml_InvalidSurrogateMissingLowChar); - } - char chNext = (char)(pb[pos + 2] | ((int)(pb[pos + 3]) << 8)); - if (!XmlCharType.IsLowSurrogate(chNext)) - { - throw XmlConvert.CreateInvalidSurrogatePairException(ch, chNext); - } + throw XmlConvert.CreateInvalidSurrogatePairException(ch, (char)lowSurr); } - pos += 4; + data = data.Slice(2); //consumed a low surrogate char } } } @@ -4434,35 +4415,9 @@ private object ValueAs(BinXmlToken token, Type returnType, IXmlNamespaceResolver private ulong GetUInt64(int pos) => BinaryPrimitives.ReadUInt64LittleEndian(_data.AsSpan(pos)); - private float GetSingle(int offset) - { - byte[] data = _data; - uint tmp = (uint)(data[offset] - | data[offset + 1] << 8 - | data[offset + 2] << 16 - | data[offset + 3] << 24); - unsafe - { - return *((float*)&tmp); - } - } + private float GetSingle(int offset) => BinaryPrimitives.ReadSingleLittleEndian(_data.AsSpan(offset)); - private double GetDouble(int offset) - { - uint lo = (uint)(_data[offset + 0] - | _data[offset + 1] << 8 - | _data[offset + 2] << 16 - | _data[offset + 3] << 24); - uint hi = (uint)(_data[offset + 4] - | _data[offset + 5] << 8 - | _data[offset + 6] << 16 - | _data[offset + 7] << 24); - ulong tmp = ((ulong)hi) << 32 | lo; - unsafe - { - return *((double*)&tmp); - } - } + private double GetDouble(int offset) => BinaryPrimitives.ReadDoubleLittleEndian(_data.AsSpan(offset)); private Exception ThrowUnexpectedToken(BinXmlToken token) { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs index eefbba970c17f..5cf5caa51ec1c 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs @@ -9732,36 +9732,30 @@ private void RegisterConsumedCharacters(long characters, bool inEntityReference) } } - internal static unsafe void AdjustLineInfo(char[] chars, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo) + internal static void AdjustLineInfo(char[] chars, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo) { Debug.Assert(startPos >= 0); Debug.Assert(endPos < chars.Length); Debug.Assert(startPos <= endPos); - fixed (char* pChars = &chars[startPos]) - { - AdjustLineInfo(pChars, endPos - startPos, isNormalized, ref lineInfo); - } + AdjustLineInfo(chars.AsSpan(startPos, endPos - startPos), isNormalized, ref lineInfo); } - internal static unsafe void AdjustLineInfo(string str, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo) + internal static void AdjustLineInfo(string str, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo) { Debug.Assert(startPos >= 0); Debug.Assert(endPos < str.Length); Debug.Assert(startPos <= endPos); - fixed (char* pChars = str) - { - AdjustLineInfo(pChars + startPos, endPos - startPos, isNormalized, ref lineInfo); - } + AdjustLineInfo(str.AsSpan(startPos, endPos - startPos), isNormalized, ref lineInfo); } - internal static unsafe void AdjustLineInfo(char* pChars, int length, bool isNormalized, ref LineInfo lineInfo) + private static void AdjustLineInfo(ReadOnlySpan chars, bool isNormalized, ref LineInfo lineInfo) { int lastNewLinePos = -1; - for (int i = 0; i < length; i++) + for (int i = 0; i < chars.Length; i++) { - switch (pChars[i]) + switch (chars[i]) { case '\n': lineInfo.lineNo++; @@ -9774,7 +9768,8 @@ internal static unsafe void AdjustLineInfo(char* pChars, int length, bool isNorm } lineInfo.lineNo++; lastNewLinePos = i; - if (i + 1 < length && pChars[i + 1] == '\n') + int nextIdx = i + 1; + if ((uint)nextIdx < (uint)chars.Length && chars[nextIdx] == '\n') { i++; lastNewLinePos++; @@ -9784,7 +9779,7 @@ internal static unsafe void AdjustLineInfo(char* pChars, int length, bool isNorm } if (lastNewLinePos >= 0) { - lineInfo.linePos = length - lastNewLinePos; + lineInfo.linePos = chars.Length - lastNewLinePos; } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/CodeIdentifier.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/CodeIdentifier.cs index 0b4240a1a03e9..edfddffb6b782 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/CodeIdentifier.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/CodeIdentifier.cs @@ -1,15 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Text; -using System.Collections; -using System.IO; -using System.Globalization; using System.Diagnostics; -using System.Reflection; -using System.Runtime.InteropServices; using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Text; namespace System.Xml.Serialization { @@ -38,8 +33,11 @@ public static string MakePascal(string identifier) } else if (char.IsLower(identifier[0])) { - char upper = char.ToUpperInvariant(identifier[0]); - return string.Concat(MemoryMarshal.CreateReadOnlySpan(ref upper, 1), identifier.AsSpan(1)); + return string.Create(identifier.Length, identifier, static (buffer, identifier) => + { + identifier.AsSpan().CopyTo(buffer); + buffer[0] = char.ToUpperInvariant(buffer[0]); // convert only first char to uppercase; leave all else as-is + }); } else { @@ -59,8 +57,11 @@ public static string MakeCamel(string identifier) } else if (char.IsUpper(identifier[0])) { - char lower = char.ToLowerInvariant(identifier[0]); - return string.Concat(MemoryMarshal.CreateReadOnlySpan(ref lower, 1), identifier.AsSpan(1)); + return string.Create(identifier.Length, identifier, static (buffer, identifier) => + { + identifier.AsSpan().CopyTo(buffer); + buffer[0] = char.ToLowerInvariant(buffer[0]); // convert only first char to lowercase; leave all else as-is + }); } else { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs b/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs index 8c413290a91c1..b28f0d6eb8bb7 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs @@ -1459,19 +1459,13 @@ internal static string[] SplitString(string value, StringSplitOptions splitStrin internal static bool IsNegativeZero(double value) { // Simple equals function will report that -0 is equal to +0, so compare bits instead - if (value == 0 && DoubleToInt64Bits(value) == DoubleToInt64Bits(-0e0)) + if (value == 0 && BitConverter.DoubleToInt64Bits(value) == BitConverter.DoubleToInt64Bits(-0e0)) { return true; } return false; } - private static unsafe long DoubleToInt64Bits(double value) - { - // NOTE: BitConverter.DoubleToInt64Bits is missing in Silverlight - return *((long*)&value); - } - internal static void VerifyCharData(string? data, ExceptionType exceptionType) { VerifyCharData(data, exceptionType, exceptionType); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs index b23f0a37223a7..3e0daa1336abc 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs @@ -2846,37 +2846,6 @@ private void InitFromDouble(double dbl) } }; - /* ---------------------------------------------------------------------------- - IntToString() - - Converts an integer to a string according to XPath rules. - */ - private static unsafe string IntToString(int val) - { - // The maximum number of characters needed to represent any int value is 11 - const int BufSize = 12; - char* pBuf = stackalloc char[BufSize]; - char* pch = pBuf += BufSize; - uint u = (uint)(val < 0 ? -val : val); - - while (u >= 10) - { - // Fast division by 10 - uint quot = (uint)((0x66666667L * u) >> 32) >> 2; - *(--pch) = (char)((u - quot * 10) + '0'); - u = quot; - } - - *(--pch) = (char)(u + '0'); - - if (val < 0) - { - *(--pch) = '-'; - } - - return new string(pch, 0, (int)(pBuf - pch)); - } - /* ---------------------------------------------------------------------------- DoubleToString() @@ -2890,7 +2859,7 @@ public static string DoubleToString(double dbl) if (IsInteger(dbl, out iVal)) { - return IntToString(iVal); + return iVal.ToString(CultureInfo.InvariantCulture); } // Handle NaN and infinity