2024-02-21 11:07:18 +00:00
|
|
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
|
|
// See the LICENCE file in the repository root for full licence text.
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
namespace osu.Game.Utils
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// This string comparer is something of a cross-over between <see cref="StringComparer.Ordinal"/> and <see cref="StringComparer.OrdinalIgnoreCase"/>.
|
|
|
|
/// <see cref="StringComparer.OrdinalIgnoreCase"/> is used first, but <see cref="StringComparer.Ordinal"/> is used as a tie-breaker.
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>
|
|
|
|
/// This comparer's behaviour somewhat emulates <see cref="StringComparer.InvariantCulture"/>,
|
|
|
|
/// but non-ordinal comparers - both culture-aware and culture-invariant - have huge performance overheads due to i18n factors (up to 5x slower).
|
|
|
|
/// </remarks>
|
|
|
|
/// <example>
|
|
|
|
/// Given the following strings to sort: <c>[A, B, C, D, a, b, c, d, A]</c> and a stable sorting algorithm:
|
|
|
|
/// <list type="bullet">
|
|
|
|
/// <item>
|
|
|
|
/// <see cref="StringComparer.Ordinal"/> would return <c>[A, A, B, C, D, a, b, c, d]</c>.
|
|
|
|
/// This is undesirable as letters are interleaved.
|
|
|
|
/// </item>
|
|
|
|
/// <item>
|
|
|
|
/// <see cref="StringComparer.OrdinalIgnoreCase"/> would return <c>[A, a, A, B, b, C, c, D, d]</c>.
|
|
|
|
/// Different letters are not interleaved, but because case is ignored, the As are left in arbitrary order.
|
|
|
|
/// </item>
|
|
|
|
/// </list>
|
|
|
|
/// <item>
|
|
|
|
/// <see cref="OrdinalSortByCaseStringComparer"/> would return <c>[a, A, A, b, B, c, C, d, D]</c>, which is the expected behaviour.
|
|
|
|
/// </item>
|
|
|
|
/// </example>
|
|
|
|
public class OrdinalSortByCaseStringComparer : IComparer<string>
|
|
|
|
{
|
2024-02-21 13:02:20 +00:00
|
|
|
public static readonly OrdinalSortByCaseStringComparer DEFAULT = new OrdinalSortByCaseStringComparer();
|
2024-02-21 11:07:18 +00:00
|
|
|
|
|
|
|
private OrdinalSortByCaseStringComparer()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
public int Compare(string? a, string? b)
|
|
|
|
{
|
|
|
|
int result = StringComparer.OrdinalIgnoreCase.Compare(a, b);
|
|
|
|
if (result == 0)
|
|
|
|
result = -StringComparer.Ordinal.Compare(a, b); // negative to place lowercase letters before uppercase.
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|