< Summary

Information
Class: MoreStructures.Utilities.StringIncludingTerminatorComparer
Assembly: MoreStructures
File(s): /home/runner/work/MoreStructures/MoreStructures/MoreStructures/Utilities/StringIncludingTerminatorComparer.cs
Line coverage
100%
Covered lines: 21
Uncovered lines: 0
Coverable lines: 21
Total lines: 68
Line coverage: 100%
Branch coverage
100%
Covered branches: 18
Total branches: 18
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
get_Terminator()100%1100%
.ctor(...)100%1100%
.cctor()100%1100%
Build(...)100%1100%
Compare(...)100%18100%

File(s)

/home/runner/work/MoreStructures/MoreStructures/MoreStructures/Utilities/StringIncludingTerminatorComparer.cs

#LineLine coverage
 1using System.Collections.Concurrent;
 2
 3namespace MoreStructures.Utilities;
 4
 5/// <summary>
 6/// An implementation of <see cref="IComparer{T}"/> for <see cref="string"/>, which compares string taking into account
 7/// the fact that the string may contain (at any index, not necessarily at then end) a special char, called terminator,
 8/// which has to be considered smaller than any other char.
 9/// </summary>
 10public class StringIncludingTerminatorComparer : IComparer<string>
 11{
 12    /// <summary>
 13    /// The character acting as terminator, and which has to be considered smaller than any other char.
 14    /// </summary>
 9156015    public char Terminator { get; }
 16
 717    private StringIncludingTerminatorComparer(char terminator)
 718    {
 719        Terminator = terminator;
 720    }
 21
 122    private static readonly ConcurrentDictionary<char, StringIncludingTerminatorComparer> _instances = new();
 23
 24    /// <summary>
 25    /// Builds a <see cref="StringIncludingTerminatorComparer"/> with the provided <paramref name="terminator"/>.
 26    /// Caches instances.
 27    /// </summary>
 28    /// <param name="terminator"><inheritdoc cref="Terminator" path="/summary"/></param>
 29    /// <returns>
 30    /// An instance of <see cref="StringIncludingTerminatorComparer"/>, new or previously created and cached.
 31    /// </returns>
 32    public static StringIncludingTerminatorComparer Build(char terminator)
 13033    {
 13734        return _instances.GetOrAdd(terminator, t => new StringIncludingTerminatorComparer(t));
 13035    }
 36
 37    /// <inheritdoc path="//*[not(self::summary or self::remarks)]"/>
 38    /// <summary>
 39    ///     <inheritdoc/>
 40    /// </summary>
 41    /// <remarks>
 42    ///     Special rules applied by <see cref="StringIncludingTerminatorComparer"/>:
 43    ///     <br/>
 44    ///     - If either string is null or empty, the standard <see cref="string.Compare(string?, string?)"/> is used.
 45    ///       <br/>
 46    ///     - If one string starts with the terminator, and the other doesn't, the one which does is smaller.
 47    ///       <br/>
 48    ///     - If none of the cases above applies, <see cref="string.Compare(string?, string?)"/> is used on the
 49    ///       substring starting from index 1 of each of the strings <paramref name="x"/> and <paramref name="y"/>.
 50    /// </remarks>
 51    public int Compare(string? x, string? y)
 3186752    {
 3186753        if (x == null || y == null || x.Length == 0 || y.Length == 0)
 26154            return string.Compare(x, y);
 55
 3160656        if (x[0] == Terminator && y[0] != Terminator)
 325957            return -1;
 58
 2834759        if (x[0] != Terminator && y[0] == Terminator)
 35960            return 1;
 61
 2798862        var firstCharDifference = x[0] - y[0];
 2798863        if (firstCharDifference != 0)
 2259564            return firstCharDifference;
 65
 539366        return Compare(x[1..], y[1..]);
 3186767    }
 68}