| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 | #pragma warning disable CS1591#nullable enableusing System;using System.Collections.Generic;namespace MediaBrowser.Controller.Sorting{    public class AlphanumComparator : IComparer<string?>    {        public static int CompareValues(string? s1, string? s2)        {            if (s1 == null && s2 == null)            {                return 0;            }            else if (s1 == null)            {                return -1;            }            else if (s2 == null)            {                return 1;            }            int len1 = s1.Length;            int len2 = s2.Length;            // Early return for empty strings            if (len1 == 0 && len2 == 0)            {                return 0;            }            else if (len1 == 0)            {                return -1;            }            else if (len2 == 0)            {                return 1;            }            int pos1 = 0;            int pos2 = 0;            do            {                int start1 = pos1;                int start2 = pos2;                bool isNum1 = char.IsDigit(s1[pos1++]);                bool isNum2 = char.IsDigit(s2[pos2++]);                while (pos1 < len1 && char.IsDigit(s1[pos1]) == isNum1)                {                    pos1++;                }                while (pos2 < len2 && char.IsDigit(s2[pos2]) == isNum2)                {                    pos2++;                }                var span1 = s1.AsSpan(start1, pos1 - start1);                var span2 = s2.AsSpan(start2, pos2 - start2);                if (isNum1 && isNum2)                {                    // Trim leading zeros so we can compare the length                    // of the strings to find the largest number                    span1 = span1.TrimStart('0');                    span2 = span2.TrimStart('0');                    var span1Len = span1.Length;                    var span2Len = span2.Length;                    if (span1Len < span2Len)                    {                        return -1;                    }                    else if (span1Len > span2Len)                    {                        return 1;                    }                    else if (span1Len >= 20) // Number is probably too big for a ulong                    {                        // Trim all the first digits that are the same                        int i = 0;                        while (i < span1Len && span1[i] == span2[i])                        {                            i++;                        }                        // If there are no more digits it's the same number                        if (i == span1Len)                        {                            continue;                        }                        // Only need to compare the most significant digit                        span1 = span1.Slice(i, 1);                        span2 = span2.Slice(i, 1);                    }                    if (!ulong.TryParse(span1, out var num1)                        || !ulong.TryParse(span2, out var num2))                    {                        return 0;                    }                    else if (num1 < num2)                    {                        return -1;                    }                    else if (num1 > num2)                    {                        return 1;                    }                }                else                {                    int result = span1.CompareTo(span2, StringComparison.InvariantCulture);                    if (result != 0)                    {                        return result;                    }                }            } while (pos1 < len1 && pos2 < len2);            return len1 - len2;        }        /// <inheritdoc />        public int Compare(string? x, string? y)        {            return CompareValues(x, y);        }    }}
 |