From 9e92928f7ec520307f6032732894068d09b4f7fb Mon Sep 17 00:00:00 2001
From: Paulo Morgado <470455+paulomorgado@users.noreply.github.com>
Date: Fri, 29 May 2026 14:47:11 +0100
Subject: [PATCH] Reduce string allocations in sys helpers
Apply string interpolation and span-based trimming updates under src/SIPSorcery/sys.
Keep the KeyValuePair deconstruction helper because current transaction code still depends on it.
---
src/SIPSorcery/sys/Crypto/Crypto.cs | 4 +--
src/SIPSorcery/sys/Crypto/PasswordHash.cs | 4 +--
.../sys/Formatting/NumberFormatting.cs | 18 ++++++------
src/SIPSorcery/sys/Net/IPSocket.cs | 28 ++++++++++---------
src/SIPSorcery/sys/TypeExtensions.cs | 6 ++--
5 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/src/SIPSorcery/sys/Crypto/Crypto.cs b/src/SIPSorcery/sys/Crypto/Crypto.cs
index bf1789cfe..d8cbe673d 100644
--- a/src/SIPSorcery/sys/Crypto/Crypto.cs
+++ b/src/SIPSorcery/sys/Crypto/Crypto.cs
@@ -293,7 +293,7 @@ private static FileStream GetFileStream(string filepath)
if (!File.Exists(filepath))
{
logger.LogError("Cannot open a non-existent file for a hash operation, {FilePath}.", filepath);
- throw new IOException("Cannot open a non-existent file for a hash operation, " + filepath + ".");
+ throw new IOException($"Cannot open a non-existent file for a hash operation, {filepath}.");
}
// Open the file.
@@ -303,7 +303,7 @@ private static FileStream GetFileStream(string filepath)
{
inputStream.Close();
logger.LogError("Cannot perform a hash operation on an empty file, {FilePath}.", filepath);
- throw new IOException("Cannot perform a hash operation on an empty file, " + filepath + ".");
+ throw new IOException($"Cannot perform a hash operation on an empty file, {filepath}.");
}
return inputStream;
diff --git a/src/SIPSorcery/sys/Crypto/PasswordHash.cs b/src/SIPSorcery/sys/Crypto/PasswordHash.cs
index 3beee8029..9e04dc642 100644
--- a/src/SIPSorcery/sys/Crypto/PasswordHash.cs
+++ b/src/SIPSorcery/sys/Crypto/PasswordHash.cs
@@ -42,7 +42,7 @@ public static string GenerateSalt(int? explicitIterations = null)
{
if (explicitIterations.HasValue && explicitIterations.Value < RFC289_MINIMUM_ITERATIONS)
{
- throw new ArgumentException("Cannot be less than " + RFC289_MINIMUM_ITERATIONS, "explicitIterations");
+ throw new ArgumentException($"Cannot be less than {RFC289_MINIMUM_ITERATIONS}", "explicitIterations");
}
byte[] salt = new byte[SALT_SIZE];
@@ -50,7 +50,7 @@ public static string GenerateSalt(int? explicitIterations = null)
var iterations = (explicitIterations ?? RFC289_MINIMUM_ITERATIONS).ToString("X");
- return iterations + "." + Convert.ToBase64String(salt);
+ return $"{iterations}.{Convert.ToBase64String(salt)}";
}
///
diff --git a/src/SIPSorcery/sys/Formatting/NumberFormatting.cs b/src/SIPSorcery/sys/Formatting/NumberFormatting.cs
index db1d8161f..b62544c49 100644
--- a/src/SIPSorcery/sys/Formatting/NumberFormatting.cs
+++ b/src/SIPSorcery/sys/Formatting/NumberFormatting.cs
@@ -25,22 +25,22 @@ public static string ToSIFormat(double number, int decimalPlaces)
if (number > 1000000000000)
{
double teraNumber = Math.Round((double)(number / (double)100000000000), decimalPlaces);
- return teraNumber.ToString() + "T";
+ return $"{teraNumber}T";
}
if (number > 1000000000)
{
double gigaNumber = Math.Round((double)(number / (double)100000000), decimalPlaces);
- return gigaNumber.ToString() + "G";
+ return $"{gigaNumber}G";
}
else if (number > 1000000)
{
double kiloNumber = Math.Round((double)(number / (double)1000000), decimalPlaces);
- return kiloNumber.ToString() + "M";
+ return $"{kiloNumber}M";
}
else if (number > 1000)
{
double kiloNumber = Math.Round((double)(number / (double)1000), decimalPlaces);
- return kiloNumber.ToString() + "k";
+ return $"{kiloNumber}k";
}
else
{
@@ -53,26 +53,26 @@ private static string ToSIByteFormat(double number, int decimalPlaces, string su
if (number > 1099511627776)
{
double teraNumber = Math.Round((double)(number / (double)1099511627776), decimalPlaces);
- return teraNumber.ToString() + "T" + suffix;
+ return $"{teraNumber}T{suffix}";
}
if (number > 1073741824)
{
double gigaNumber = Math.Round((double)(number / (double)1073741824), decimalPlaces);
- return gigaNumber.ToString() + "G" + suffix;
+ return $"{gigaNumber}G{suffix}";
}
else if (number > 1048576)
{
double kiloNumber = Math.Round((double)(number / (double)1048576), decimalPlaces);
- return kiloNumber.ToString() + "M" + suffix;
+ return $"{kiloNumber}M{suffix}";
}
else if (number > 1024)
{
double kiloNumber = Math.Round((double)(number / (double)1024), decimalPlaces);
- return kiloNumber.ToString() + "K" + suffix;
+ return $"{kiloNumber}K{suffix}";
}
else
{
- return Math.Round((double)number, decimalPlaces).ToString() + suffix;
+ return $"{Math.Round((double)number, decimalPlaces)}{suffix}";
}
}
diff --git a/src/SIPSorcery/sys/Net/IPSocket.cs b/src/SIPSorcery/sys/Net/IPSocket.cs
index 425a86d15..f5eb689fb 100644
--- a/src/SIPSorcery/sys/Net/IPSocket.cs
+++ b/src/SIPSorcery/sys/Net/IPSocket.cs
@@ -44,8 +44,10 @@ public class IPSocket
///
public static string GetSocketString(IPEndPoint endPoint)
{
- string format = (endPoint.Address.AddressFamily == AddressFamily.InterNetworkV6) ? "[{0}]:{1}" : "{0}:{1}";
- return string.Format(format, endPoint.Address.ToString(), endPoint.Port.ToString(NumberFormatInfo.InvariantInfo));
+ var address = endPoint.Address.ToString();
+ var port = endPoint.Port.ToString(NumberFormatInfo.InvariantInfo);
+
+ return endPoint.Address.AddressFamily == AddressFamily.InterNetworkV6 ? $"[{address}]:{port}" : $"{address}:{port}";
}
///
@@ -123,7 +125,7 @@ public static string ParseHostFromSocket(string socket)
{
string host = socket;
- if (socket != null && socket.Trim().Length > 0 && socket.IndexOf(':') != -1)
+ if (!string.IsNullOrWhiteSpace(socket) && socket.IndexOf(':') != -1)
{
host = socket.Substring(0, socket.LastIndexOf(':')).Trim();
}
@@ -154,14 +156,14 @@ public static int ParsePortFromSocket(string socket)
}
// Look to see if this is IPv4 with a port (IPv6 will have another colon)
// If it's a host name there will also not be another ':'.
- else if (socket.Substring(0, lastColonPos).LastIndexOf(':') != -1)
+ else if (socket.AsSpan(0, lastColonPos).LastIndexOf(':') != -1)
{
// This is an IPv6 address WITHOUT a port.
lastColonPos = -1;
}
}
- if (socket != null && socket.Trim().Length > 0 && lastColonPos != -1)
+ if (!string.IsNullOrWhiteSpace(socket) && lastColonPos != -1)
{
port = Convert.ToInt32(socket.Substring(lastColonPos + 1).Trim());
}
@@ -176,7 +178,7 @@ public static int ParsePortFromSocket(string socket)
/// true/false
public static bool IsIPAddress(string socket)
{
- if (socket == null || socket.Trim().Length == 0)
+ if (string.IsNullOrWhiteSpace(socket))
{
return false;
}
@@ -310,7 +312,7 @@ public static bool Parse(string endpointstring, out string host, out int port)
}
else
{
- throw new FormatException(string.Format("Invalid endpoint ipaddress '{0}'", endpointstring));
+ throw new FormatException($"Invalid endpoint ipaddress '{endpointstring}'");
}
return rc;
@@ -327,7 +329,7 @@ public static IPEndPoint Parse(string endpointstring, int defaultport = -1)
(defaultport < IPEndPoint.MinPort
|| defaultport > IPEndPoint.MaxPort))
{
- throw new ArgumentException(string.Format("Invalid default port '{0}'", defaultport));
+ throw new ArgumentException($"Invalid default port '{defaultport}'");
}
string[] values = endpointstring.Split(new char[] { ':' });
@@ -356,7 +358,7 @@ public static IPEndPoint Parse(string endpointstring, int defaultport = -1)
}
catch
{
- throw new FormatException(string.Format("Invalid endpoint ipaddress '{0}'", endpointstring));
+ throw new FormatException($"Invalid endpoint ipaddress '{endpointstring}'");
}
}
}
@@ -377,7 +379,7 @@ public static IPEndPoint Parse(string endpointstring, int defaultport = -1)
}
else
{
- throw new FormatException(string.Format("Invalid endpoint ipaddress '{0}'", endpointstring));
+ throw new FormatException($"Invalid endpoint ipaddress '{endpointstring}'");
}
if (port == -1)
@@ -396,7 +398,7 @@ private static int getPort(string p)
|| port < IPEndPoint.MinPort
|| port > IPEndPoint.MaxPort)
{
- throw new FormatException(string.Format("Invalid end point port '{0}'", p));
+ throw new FormatException($"Invalid end point port '{p}'");
}
return port;
@@ -410,13 +412,13 @@ private static IPAddress getIPfromHost(string p)
if (hosts == null || hosts.Length == 0)
{
- throw new ArgumentException(string.Format("Host not found: {0}", p));
+ throw new ArgumentException($"Host not found: {p}");
}
return hosts[0];
}
catch
{
- throw new ArgumentException(string.Format("Host not found: {0}", p));
+ throw new ArgumentException($"Host not found: {p}");
}
}
diff --git a/src/SIPSorcery/sys/TypeExtensions.cs b/src/SIPSorcery/sys/TypeExtensions.cs
index 730b0d04f..69d24596c 100644
--- a/src/SIPSorcery/sys/TypeExtensions.cs
+++ b/src/SIPSorcery/sys/TypeExtensions.cs
@@ -55,7 +55,7 @@ public static class TypeExtensions
///
public static bool IsNullOrBlank(this string s)
{
- if (s == null || s.Trim(WhiteSpaceChars).Length == 0)
+ if (s == null || s.AsSpan().Trim(WhiteSpaceChars).Length == 0)
{
return true;
}
@@ -65,7 +65,7 @@ public static bool IsNullOrBlank(this string s)
public static bool NotNullOrBlank(this string s)
{
- if (s == null || s.Trim(WhiteSpaceChars).Length == 0)
+ if (s == null || s.AsSpan().Trim(WhiteSpaceChars).Length == 0)
{
return false;
}
@@ -206,13 +206,11 @@ public static byte[] ParseHexStr(string hexStr)
return buffer.ToArray();
}
- //#if NET472 || NETSTANDARD2_0
public static void Deconstruct(this KeyValuePair tuple, out T1 key, out T2 value)
{
key = tuple.Key;
value = tuple.Value;
}
- //#endif
public static bool IsPrivate(this IPAddress address)
{