Review usage of string.Substring (part 1)

Reduced allocations by replacing string.Substring with ReadOnlySpan<char>.Slice
This commit is contained in:
Bond_009
2020-07-22 13:34:51 +02:00
parent 0750357916
commit febb6bced6
25 changed files with 124 additions and 99 deletions

View File

@@ -511,8 +511,8 @@ namespace Emby.Server.Implementations.Library
{
// Try to normalize paths located underneath program-data in an attempt to make them more portable
key = key.Substring(_configurationManager.ApplicationPaths.ProgramDataPath.Length)
.TrimStart(new[] { '/', '\\' })
.Replace("/", "\\");
.TrimStart('/', '\\')
.Replace('/', '\\');
}
if (forceCaseInsensitive || !_configurationManager.Configuration.EnableCaseSensitiveItemIds)

View File

@@ -869,7 +869,7 @@ namespace Emby.Server.Implementations.Library
var provider = _providers.FirstOrDefault(i => string.Equals(i.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture), keys[0], StringComparison.OrdinalIgnoreCase));
var splitIndex = key.IndexOf(LiveStreamIdDelimeter);
var splitIndex = key.IndexOf(LiveStreamIdDelimeter, StringComparison.Ordinal);
var keyId = key.Substring(splitIndex + 1);
return new Tuple<IMediaSourceProvider, string>(provider, keyId);
@@ -881,6 +881,7 @@ namespace Emby.Server.Implementations.Library
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private readonly object _disposeLock = new object();

View File

@@ -461,7 +461,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
private async Task<List<ScheduleDirect.ShowImages>> GetImageForPrograms(
ListingsProviderInfo info,
List<string> programIds,
CancellationToken cancellationToken)
CancellationToken cancellationToken)
{
if (programIds.Count == 0)
{
@@ -474,7 +474,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
{
var imageId = i.Substring(0, 10);
if (!imageIdString.Contains(imageId))
if (!imageIdString.Contains(imageId, StringComparison.Ordinal))
{
imageIdString += "\"" + imageId + "\",";
}

View File

@@ -195,7 +195,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
while (!sr.EndOfStream)
{
string line = StripXML(sr.ReadLine());
if (line.Contains("Channel"))
if (line.Contains("Channel", StringComparison.Ordinal))
{
LiveTvTunerStatus status;
var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase);
@@ -226,6 +226,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private static string StripXML(string source)
{
if (string.IsNullOrEmpty(source))
{
return string.Empty;
}
char[] buffer = new char[source.Length];
int bufferIndex = 0;
bool inside = false;
@@ -270,7 +275,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
for (int i = 0; i < model.TunerCount; ++i)
{
var name = string.Format("Tuner {0}", i + 1);
var name = string.Format(CultureInfo.InvariantCulture, "Tuner {0}", i + 1);
var currentChannel = "none"; // @todo Get current channel and map back to Station Id
var isAvailable = await manager.CheckTunerAvailability(ipInfo, i, cancellationToken).ConfigureAwait(false);
var status = isAvailable ? LiveTvTunerStatus.Available : LiveTvTunerStatus.LiveTv;

View File

@@ -158,15 +158,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
private string GetChannelNumber(string extInf, Dictionary<string, string> attributes, string mediaUrl)
{
var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var nameInExtInf = nameParts.Length > 1 ? nameParts[nameParts.Length - 1].Trim() : null;
var nameInExtInf = nameParts.Length > 1 ? nameParts[^1].AsSpan().Trim() : ReadOnlySpan<char>.Empty;
string numberString = null;
string attributeValue;
double doubleValue;
if (attributes.TryGetValue("tvg-chno", out attributeValue))
{
if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out doubleValue))
if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out _))
{
numberString = attributeValue;
}
@@ -176,36 +175,36 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
{
if (attributes.TryGetValue("tvg-id", out attributeValue))
{
if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out doubleValue))
if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out _))
{
numberString = attributeValue;
}
else if (attributes.TryGetValue("channel-id", out attributeValue))
{
if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out doubleValue))
if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out _))
{
numberString = attributeValue;
}
}
}
if (String.IsNullOrWhiteSpace(numberString))
if (string.IsNullOrWhiteSpace(numberString))
{
// Using this as a fallback now as this leads to Problems with channels like "5 USA"
// where 5 isnt ment to be the channel number
// Check for channel number with the format from SatIp
// #EXTINF:0,84. VOX Schweiz
// #EXTINF:0,84.0 - VOX Schweiz
if (!string.IsNullOrWhiteSpace(nameInExtInf))
if (!nameInExtInf.IsEmpty && !nameInExtInf.IsWhiteSpace())
{
var numberIndex = nameInExtInf.IndexOf(' ');
if (numberIndex > 0)
{
var numberPart = nameInExtInf.Substring(0, numberIndex).Trim(new[] { ' ', '.' });
var numberPart = nameInExtInf.Slice(0, numberIndex).Trim(new[] { ' ', '.' });
if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out var number))
if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out _))
{
numberString = numberPart;
numberString = numberPart.ToString();
}
}
}
@@ -231,7 +230,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
{
try
{
numberString = Path.GetFileNameWithoutExtension(mediaUrl.Split('/').Last());
numberString = Path.GetFileNameWithoutExtension(mediaUrl.Split('/')[^1]);
if (!IsValidChannelNumber(numberString))
{
@@ -258,7 +257,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return false;
}
if (!double.TryParse(numberString, NumberStyles.Any, CultureInfo.InvariantCulture, out var value))
if (!double.TryParse(numberString, NumberStyles.Any, CultureInfo.InvariantCulture, out _))
{
return false;
}
@@ -281,7 +280,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
{
var numberPart = nameInExtInf.Substring(0, numberIndex).Trim(new[] { ' ', '.' });
if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out var number))
if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out _))
{
// channel.Number = number.ToString();
nameInExtInf = nameInExtInf.Substring(numberIndex + 1).Trim(new[] { ' ', '-' });

View File

@@ -247,7 +247,7 @@ namespace Emby.Server.Implementations.Localization
}
// Try splitting by : to handle "Germany: FSK 18"
var index = rating.IndexOf(':');
var index = rating.IndexOf(':', StringComparison.Ordinal);
if (index != -1)
{
rating = rating.Substring(index).TrimStart(':').Trim();
@@ -312,12 +312,12 @@ namespace Emby.Server.Implementations.Localization
throw new ArgumentNullException(nameof(culture));
}
const string prefix = "Core";
var key = prefix + culture;
const string Prefix = "Core";
var key = Prefix + culture;
return _dictionaries.GetOrAdd(
key,
f => GetDictionary(prefix, culture, DefaultCulture + ".json").GetAwaiter().GetResult());
f => GetDictionary(Prefix, culture, DefaultCulture + ".json").GetAwaiter().GetResult());
}
private async Task<Dictionary<string, string>> GetDictionary(string prefix, string culture, string baseFilename)

View File

@@ -390,7 +390,7 @@ namespace Emby.Server.Implementations.Networking
var host = uri.DnsSafeHost;
_logger.LogDebug("Resolving host {0}", host);
address = GetIpAddresses(host).Result.FirstOrDefault();
address = GetIpAddresses(host).GetAwaiter().GetResult().FirstOrDefault();
if (address != null)
{

View File

@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
@@ -105,7 +106,12 @@ namespace Emby.Server.Implementations.Services
}
var expectedMethodName = actionName.Substring(0, 1) + actionName.Substring(1).ToLowerInvariant();
throw new NotImplementedException(string.Format("Could not find method named {1}({0}) or Any({0}) on Service {2}", requestDto.GetType().GetMethodName(), expectedMethodName, serviceType.GetMethodName()));
throw new NotImplementedException(
string.Format(
CultureInfo.InvariantCulture,
"Could not find method named {1}({0}) or Any({0}) on Service {2}",
requestDto.GetType().GetMethodName(),
expectedMethodName, serviceType.GetMethodName()));
}
private static async Task<object> GetTaskResult(Task task)

View File

@@ -44,7 +44,7 @@ namespace Emby.Server.Implementations.Services
var pos = pathInfo.LastIndexOf('.');
if (pos != -1)
{
var format = pathInfo.Substring(pos + 1);
var format = pathInfo.AsSpan().Slice(pos + 1);
contentType = GetFormatContentType(format);
if (contentType != null)
{
@@ -55,15 +55,18 @@ namespace Emby.Server.Implementations.Services
return pathInfo;
}
private static string GetFormatContentType(string format)
private static string GetFormatContentType(ReadOnlySpan<char> format)
{
// built-in formats
switch (format)
if (format.Equals("json", StringComparison.Ordinal))
{
case "json": return "application/json";
case "xml": return "application/xml";
default: return null;
return "application/json";
}
else if (format.Equals("xml", StringComparison.Ordinal))
{
return "application/xml";
}
return null;
}
public async Task ProcessRequestAsync(HttpListenerHost httpHost, IRequest httpReq, HttpResponse httpRes, ILogger logger, CancellationToken cancellationToken)

View File

@@ -156,7 +156,7 @@ namespace Emby.Server.Implementations.Services
{
var component = components[i];
if (component.StartsWith(VariablePrefix))
if (component.StartsWith(VariablePrefix, StringComparison.Ordinal))
{
var variableName = component.Substring(1, component.Length - 2);
if (variableName[variableName.Length - 1] == WildCardChar)