emby-toolbox/EmbyToolbox/Services/NaturalStringComparer.cs
Emby Toolbox 6264b487fe Initial commit: Emby Toolbox (conversion scroll fix, bulk Del for tracks).
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 21:33:47 +05:00

79 lines
2.1 KiB
C#

using System.Collections;
using System.Globalization;
namespace EmbyToolbox.Services;
public sealed class NaturalStringComparer : IComparer<string>, IComparer
{
public static readonly NaturalStringComparer Instance = new();
public int Compare(string? x, string? y)
{
if (ReferenceEquals(x, y))
{
return 0;
}
if (x is null)
{
return -1;
}
if (y is null)
{
return 1;
}
var ix = 0;
var iy = 0;
while (ix < x.Length && iy < y.Length)
{
var cx = x[ix];
var cy = y[iy];
if (char.IsDigit(cx) && char.IsDigit(cy))
{
var startX = ix;
var startY = iy;
while (ix < x.Length && char.IsDigit(x[ix])) ix++;
while (iy < y.Length && char.IsDigit(y[iy])) iy++;
var partX = x[startX..ix].TrimStart('0');
var partY = y[startY..iy].TrimStart('0');
if (partX.Length != partY.Length)
{
return partX.Length.CompareTo(partY.Length);
}
var compareNumeric = string.Compare(partX, partY, StringComparison.Ordinal);
if (compareNumeric != 0)
{
return compareNumeric;
}
var rawX = x[startX..ix];
var rawY = y[startY..iy];
if (rawX.Length != rawY.Length)
{
return rawX.Length.CompareTo(rawY.Length);
}
}
else
{
var cmp = char.ToUpper(cx, CultureInfo.InvariantCulture).CompareTo(char.ToUpper(cy, CultureInfo.InvariantCulture));
if (cmp != 0)
{
return cmp;
}
ix++;
iy++;
}
}
return x.Length.CompareTo(y.Length);
}
int IComparer.Compare(object? x, object? y) => Compare(x as string, y as string);
}