From a125ec174f32140972b19584a78447d3532d18e1 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Wed, 9 Jan 2019 21:19:21 -0500 Subject: [PATCH] Use string.Concat(ReadOnlySpan, ...) in a few places across corefx Commit migrated from https://github.com/dotnet/corefx/commit/3f63fe48c9663c1c607a02fe3c78197181d8e74b --- .../src/System.Data.Common.csproj | 1 + .../src/System/Data/XmlToDatasetMap.cs | 2 +- .../Net/Http/Headers/MediaTypeHeaderValue.cs | 10 ++-- .../Net/Http/SocketsHttpHandler/HttpSystemProxy.cs | 6 +- .../src/System.Net.Requests.csproj | 1 + .../src/System/Net/CommandStream.cs | 2 +- .../System/Net/Sockets/UnixDomainSocketEndPoint.cs | 2 +- src/libraries/System.Private.Uri/src/System/Uri.cs | 65 +++++++++++----------- .../src/System/Xml/Schema/XmlSchemaDataType.cs | 2 +- .../src/System/Xml/Serialization/CodeIdentifier.cs | 4 +- .../Xml/Serialization/XmlSerializationReader.cs | 4 +- .../src/System.Web.HttpUtility.csproj | 1 + .../src/System/Web/Util/HttpEncoder.cs | 2 +- 13 files changed, 54 insertions(+), 48 deletions(-) diff --git a/src/libraries/System.Data.Common/src/System.Data.Common.csproj b/src/libraries/System.Data.Common/src/System.Data.Common.csproj index 7295102..c2ccd33 100644 --- a/src/libraries/System.Data.Common/src/System.Data.Common.csproj +++ b/src/libraries/System.Data.Common/src/System.Data.Common.csproj @@ -306,6 +306,7 @@ + diff --git a/src/libraries/System.Data.Common/src/System/Data/XmlToDatasetMap.cs b/src/libraries/System.Data.Common/src/System/Data/XmlToDatasetMap.cs index 54c1aba..aa3edb3 100644 --- a/src/libraries/System.Data.Common/src/System/Data/XmlToDatasetMap.cs +++ b/src/libraries/System.Data.Common/src/System/Data/XmlToDatasetMap.cs @@ -535,7 +535,7 @@ namespace System.Data tempColumnName = "_x0058_"; // upper case Xml... -> _x0058_ml... } - tempColumnName += col.ColumnName.Substring(1); + tempColumnName = string.Concat(tempColumnName, col.ColumnName.AsSpan(1)); if (nameTable.Get(tempColumnName) == null) { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderValue.cs index 3607deb..4791537 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderValue.cs @@ -237,17 +237,17 @@ namespace System.Net.Http.Headers // If there is no whitespace between and in / get the media type using // one Substring call. Otherwise get substrings for and and combine them. - int mediatTypeLength = current + subtypeLength - startIndex; - if (typeLength + subtypeLength + 1 == mediatTypeLength) + int mediaTypeLength = current + subtypeLength - startIndex; + if (typeLength + subtypeLength + 1 == mediaTypeLength) { - mediaType = input.Substring(startIndex, mediatTypeLength); + mediaType = input.Substring(startIndex, mediaTypeLength); } else { - mediaType = input.Substring(startIndex, typeLength) + "/" + input.Substring(current, subtypeLength); + mediaType = string.Concat(input.AsSpan(startIndex, typeLength), "/", input.AsSpan(current, subtypeLength)); } - return mediatTypeLength; + return mediaTypeLength; } private static void CheckMediaTypeFormat(string mediaType, string parameterName) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpSystemProxy.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpSystemProxy.cs index dc73f20..15f6678 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpSystemProxy.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpSystemProxy.cs @@ -240,7 +240,7 @@ namespace System.Net.Http { idx += 5; // Skip "http=" so we can replace it with "http://" int proxyLength = GetProxySubstringLength(value, idx); - Uri.TryCreate("http://" + value.Substring(idx, proxyLength) , UriKind.Absolute, out insecureProxy); + Uri.TryCreate(string.Concat("http://", value.AsSpan(idx, proxyLength)), UriKind.Absolute, out insecureProxy); } } @@ -249,7 +249,7 @@ namespace System.Net.Http { idx += 8; // Skip "https://" so we can replace it with "http://" int proxyLength = GetProxySubstringLength(value, idx); - Uri.TryCreate("http://" + value.Substring(idx, proxyLength) , UriKind.Absolute, out secureProxy); + Uri.TryCreate(string.Concat("http://", value.AsSpan(idx, proxyLength)), UriKind.Absolute, out secureProxy); } if (secureProxy == null) @@ -259,7 +259,7 @@ namespace System.Net.Http { idx += 6; // Skip "https=" so we can replace it with "http://" int proxyLength = GetProxySubstringLength(value, idx); - Uri.TryCreate("http://" + value.Substring(idx, proxyLength) , UriKind.Absolute, out secureProxy); + Uri.TryCreate(string.Concat("http://", value.AsSpan(idx, proxyLength)), UriKind.Absolute, out secureProxy); } } } diff --git a/src/libraries/System.Net.Requests/src/System.Net.Requests.csproj b/src/libraries/System.Net.Requests/src/System.Net.Requests.csproj index 2a3d060..1ad51d8 100644 --- a/src/libraries/System.Net.Requests/src/System.Net.Requests.csproj +++ b/src/libraries/System.Net.Requests/src/System.Net.Requests.csproj @@ -116,6 +116,7 @@ + diff --git a/src/libraries/System.Net.Requests/src/System/Net/CommandStream.cs b/src/libraries/System.Net.Requests/src/System/Net/CommandStream.cs index 436378c..4fca61b 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/CommandStream.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/CommandStream.cs @@ -207,7 +207,7 @@ namespace System.Net { int index = sendCommand.IndexOf(' '); if (index != -1) - sendCommand = sendCommand.Substring(0, index) + " ********"; + sendCommand = string.Concat(sendCommand.AsSpan(0, index), " ********"); } if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Sending command {sendCommand}"); } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs index 534df75..832006d6 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs @@ -125,7 +125,7 @@ namespace System.Net.Sockets bool isAbstract = IsAbstract(_path); if (isAbstract) { - return "@" + _path.Substring(1); + return string.Concat("@", _path.AsSpan(1)); } else { diff --git a/src/libraries/System.Private.Uri/src/System/Uri.cs b/src/libraries/System.Private.Uri/src/System/Uri.cs index 74c6cf0..9c272c8 100644 --- a/src/libraries/System.Private.Uri/src/System/Uri.cs +++ b/src/libraries/System.Private.Uri/src/System/Uri.cs @@ -1192,11 +1192,9 @@ namespace System if (HostType == Flags.IPv6HostType) { - ret = ret.Substring(1, ret.Length - 2); - if ((object)_info.ScopeId != null) - { - ret += _info.ScopeId; - } + ret = _info.ScopeId != null ? + string.Concat(ret.AsSpan(1, ret.Length - 2), _info.ScopeId) : + ret.Substring(1, ret.Length - 2); } // Validate that this basic host qualifies as Dns safe, // It has looser parsing rules that might allow otherwise. @@ -2240,7 +2238,7 @@ namespace System _flags &= ~(Flags.IndexMask); _flags |= (Flags)_string.Length; - _string += _originalUnicodeString.Substring(idx, _originalUnicodeString.Length - idx); + _string = string.Concat(_string, _originalUnicodeString.AsSpan(idx, _originalUnicodeString.Length - idx)); } // Indicate to createuriinfo that offset is in m_originalUnicodeString @@ -3097,8 +3095,9 @@ namespace System if (!InFact(Flags.HasUserInfo)) return _string.Substring(_info.Offset.Scheme, _info.Offset.Path - _info.Offset.Scheme); - return _string.Substring(_info.Offset.Scheme, _info.Offset.User - _info.Offset.Scheme) - + _string.Substring(_info.Offset.Host, _info.Offset.Path - _info.Offset.Host); + return string.Concat( + _string.AsSpan(_info.Offset.Scheme, _info.Offset.User - _info.Offset.Scheme), + _string.AsSpan(_info.Offset.Host, _info.Offset.Path - _info.Offset.Host)); // For HttpWebRequest.ConnectHostAndPort perf case UriComponents.HostAndPort: //Host|StrongPort @@ -3109,8 +3108,8 @@ namespace System if (InFact(Flags.NotDefaultPort) || _syntax.DefaultPort == UriParser.NoDefaultPort) return _string.Substring(_info.Offset.Host, _info.Offset.Path - _info.Offset.Host); - return _string.Substring(_info.Offset.Host, _info.Offset.Path - _info.Offset.Host) - + ':' + _info.Offset.PortValue.ToString(CultureInfo.InvariantCulture); + return string.Concat(_string.AsSpan(_info.Offset.Host, _info.Offset.Path - _info.Offset.Host), + ":", _info.Offset.PortValue.ToString(CultureInfo.InvariantCulture)); // For an obvious common case perf case UriComponents.AbsoluteUri: //Scheme|UserInfo|Host|Port|Path|Query|Fragment, @@ -3123,8 +3122,9 @@ namespace System case UriComponents.HttpRequestUrl: //Scheme|Host|Port|Path|Query, if (InFact(Flags.HasUserInfo)) { - return _string.Substring(_info.Offset.Scheme, _info.Offset.User - _info.Offset.Scheme) - + _string.Substring(_info.Offset.Host, _info.Offset.Fragment - _info.Offset.Host); + return string.Concat( + _string.AsSpan(_info.Offset.Scheme, _info.Offset.User - _info.Offset.Scheme), + _string.AsSpan(_info.Offset.Host, _info.Offset.Fragment - _info.Offset.Host)); } if (_info.Offset.Scheme == 0 && _info.Offset.Fragment == _string.Length) return _string; @@ -3209,8 +3209,8 @@ namespace System if (InFact(Flags.NotDefaultPort) || _syntax.DefaultPort == UriParser.NoDefaultPort) goto case UriComponents.UserInfo | UriComponents.Host | UriComponents.Port; - return _string.Substring(_info.Offset.User, _info.Offset.Path - _info.Offset.User) - + ':' + _info.Offset.PortValue.ToString(CultureInfo.InvariantCulture); + return string.Concat(_string.AsSpan(_info.Offset.User, _info.Offset.Path - _info.Offset.User), + ":", _info.Offset.PortValue.ToString(CultureInfo.InvariantCulture)); case UriComponents.PathAndQuery: //Path|Query, return _string.Substring(_info.Offset.Path, _info.Offset.Fragment - _info.Offset.Path); @@ -3218,8 +3218,9 @@ namespace System case UriComponents.HttpRequestUrl | UriComponents.Fragment: //Scheme|Host|Port|Path|Query|Fragment, if (InFact(Flags.HasUserInfo)) { - return _string.Substring(_info.Offset.Scheme, _info.Offset.User - _info.Offset.Scheme) - + _string.Substring(_info.Offset.Host, _info.Offset.End - _info.Offset.Host); + return string.Concat( + _string.AsSpan(_info.Offset.Scheme, _info.Offset.User - _info.Offset.Scheme), + _string.AsSpan(_info.Offset.Host, _info.Offset.End - _info.Offset.Host)); } if (_info.Offset.Scheme == 0 && _info.Offset.End == _string.Length) return _string; @@ -4170,7 +4171,7 @@ namespace System flags |= Flags.IdnHost; // need to build string for this special scenario - newHost = _originalUnicodeString.Substring(0, startInput) + userInfoString + idnValue; + newHost = string.Concat(_originalUnicodeString.AsSpan(0, startInput), userInfoString, idnValue); flags |= Flags.CanonicalDnsHost; _dnsSafeHost = new string(pString, start, end - start); justNormalized = true; @@ -4398,16 +4399,18 @@ namespace System { // original string location changed lazily _originalUnicodeString = _string; - newHost = _originalUnicodeString.Substring(0, startInput) + - (StaticInFact(flags, Flags.HasUserInfo) ? userInfoString : null); + newHost = StaticInFact(flags, Flags.HasUserInfo) ? + string.Concat(_originalUnicodeString.AsSpan(0, startInput), userInfoString) : + _originalUnicodeString.Substring(0, startInput); justNormalized = true; } else if (!iriParsing && (StaticInFact(flags, Flags.UnicodeHost) || StaticInFact(flags, Flags.IdnHost))) { // original string location changed lazily _originalUnicodeString = _string; - newHost = _originalUnicodeString.Substring(0, startInput) + - (StaticInFact(flags, Flags.HasUserInfo) ? userInfoString : null); + newHost = StaticInFact(flags, Flags.HasUserInfo) ? + string.Concat(_originalUnicodeString.AsSpan(0, startInput), userInfoString) : + _originalUnicodeString.Substring(0, startInput); justNormalized = true; } @@ -5138,11 +5141,12 @@ namespace System int idx = basePart.OriginalString.IndexOf(':'); if (basePart.IsImplicitFile) { - return basePart.OriginalString.Substring(0, idx + 1) + relativePart; + return string.Concat(basePart.OriginalString.AsSpan(0, idx + 1), relativePart); } + // The basePart has explicit scheme (could be not file:), take the DOS drive ':' position idx = basePart.OriginalString.IndexOf(':', idx + 1); - return basePart.OriginalString.Substring(0, idx + 1) + relativePart; + return string.Concat(basePart.OriginalString.AsSpan(0, idx + 1), relativePart); } // Check special case for Unc or absolute path in relativePart when base is FILE @@ -5217,10 +5221,9 @@ namespace System left = basePart.GetParts(UriComponents.SchemeAndServer | UriComponents.UserInfo, uriFormat); } - if (convBackSlashes && c1 == '\\') - relativePart = '/' + relativePart.Substring(1); - - return left + relativePart; + return convBackSlashes && c1 == '\\' ? + string.Concat(left, "/", relativePart.AsSpan(1)) : + left + relativePart; } // Here we got a relative path @@ -5254,7 +5257,7 @@ namespace System // The implicit file check is to avoid a fragment in the implicit file combined uri. char c2 = (!basePart.IsImplicitFile && basePart.Syntax.InFact(UriSyntaxFlags.MayHaveFragment)) ? '#' : c_DummyChar; - string extra = string.Empty; + ReadOnlySpan extra = string.Empty; // assuming c_DummyChar may not happen in an unicode uri string if (!(c1 == c_DummyChar && c2 == c_DummyChar)) @@ -5273,7 +5276,7 @@ namespace System } else if (i < relativePart.Length) { - extra = relativePart.Substring(i); + extra = relativePart.AsSpan(i); } length += i; } @@ -5304,7 +5307,7 @@ namespace System { // The FILE DOS path comes as /c:/path, we have to exclude first 3 chars from compression path = Compress(path, 3, ref length, basePart.Syntax); - return new string(path, 1, length - 1) + extra; + return string.Concat(path.AsSpan(1, length - 1), extra); } else if (!IsWindowsSystem && basePart.IsUnixPath) { @@ -5322,7 +5325,7 @@ namespace System } //compress the path path = Compress(path, basePart.SecuredPathIndex, ref length, basePart.Syntax); - return left + new string(path, 0, length) + extra; + return string.Concat(left, path.AsSpan(0, length), extra); } // diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaDataType.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaDataType.cs index 16d1f80..284021c 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaDataType.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaDataType.cs @@ -313,7 +313,7 @@ namespace System.Xml.Schema if (convert) { - canonicalUri = nameTable.Add(uri.Substring(0, offset) + CultureInfo.InvariantCulture.TextInfo.ToUpper(uri.Substring(offset, uri.Length - offset))); + canonicalUri = nameTable.Add(string.Concat(uri.AsSpan(0, offset), CultureInfo.InvariantCulture.TextInfo.ToUpper(uri.Substring(offset, uri.Length - offset)))); } else { 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 2ef0a5c..7597040 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 @@ -34,7 +34,7 @@ namespace System.Xml.Serialization if (identifier.Length <= 2) return CultureInfo.InvariantCulture.TextInfo.ToUpper(identifier); else if (char.IsLower(identifier[0])) - return char.ToUpperInvariant(identifier[0]) + identifier.Substring(1); + return string.Concat(char.ToUpperInvariant(identifier[0]).ToString(), identifier.AsSpan(1)); else return identifier; } @@ -48,7 +48,7 @@ namespace System.Xml.Serialization if (identifier.Length <= 2) return CultureInfo.InvariantCulture.TextInfo.ToLower(identifier); else if (char.IsUpper(identifier[0])) - return char.ToLower(identifier[0]) + identifier.Substring(1); + return string.Concat(char.ToLower(identifier[0]).ToString(), identifier.AsSpan(1)); else return identifier; } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReader.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReader.cs index 6469ca5..5a01178 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReader.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReader.cs @@ -822,8 +822,8 @@ namespace System.Xml.Serialization } else { - attr.Value = _r.LookupNamespace(attr.Value.Substring(0, colon)) + ":" + - attr.Value.Substring(colon + 1); + attr.Value = string.Concat(_r.LookupNamespace(attr.Value.Substring(0, colon)), ":", + attr.Value.AsSpan(colon + 1)); } } return; diff --git a/src/libraries/System.Web.HttpUtility/src/System.Web.HttpUtility.csproj b/src/libraries/System.Web.HttpUtility/src/System.Web.HttpUtility.csproj index 363a3a7..94c825b 100644 --- a/src/libraries/System.Web.HttpUtility/src/System.Web.HttpUtility.csproj +++ b/src/libraries/System.Web.HttpUtility/src/System.Web.HttpUtility.csproj @@ -18,6 +18,7 @@ + diff --git a/src/libraries/System.Web.HttpUtility/src/System/Web/Util/HttpEncoder.cs b/src/libraries/System.Web.HttpUtility/src/System/Web/Util/HttpEncoder.cs index 550bbe0..847e414 100644 --- a/src/libraries/System.Web.HttpUtility/src/System/Web/Util/HttpEncoder.cs +++ b/src/libraries/System.Web.HttpUtility/src/System/Web/Util/HttpEncoder.cs @@ -639,7 +639,7 @@ namespace System.Web.Util int i = value.IndexOf('?'); if (i >= 0) { - return UrlPathEncodeImpl(value.Substring(0, i)) + value.Substring(i); + return string.Concat(UrlPathEncodeImpl(value.Substring(0, i)), value.AsSpan(i)); } // encode DBCS characters and spaces only -- 2.7.4