< Summary

Information
Class: MoreStructures.VirtuallyRotatedTextWithTerminator
Assembly: MoreStructures
File(s): /home/runner/work/MoreStructures/MoreStructures/MoreStructures/VirtuallyRotatedTextWithTerminator.cs
Line coverage
100%
Covered lines: 91
Uncovered lines: 0
Coverable lines: 91
Total lines: 107
Line coverage: 100%
Branch coverage
100%
Covered branches: 16
Total branches: 16
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
get_Underlying()100%1100%
.ctor(...)100%1100%
get_Item(...)100%2100%
GetEnumerator()100%1100%
System.Collections.IEnumerable.GetEnumerator()100%1100%
CompareTo(...)100%14100%

File(s)

/home/runner/work/MoreStructures/MoreStructures/MoreStructures/VirtuallyRotatedTextWithTerminator.cs

#LineLine coverage
 1using MoreStructures.Utilities;
 2
 3namespace MoreStructures;
 4
 5/// <summary>
 6/// A text string with a terminator character which has been rotated leftwards or rightwards, of a number of positions
 7/// (0 included).
 8/// </summary>
 9/// <param name="Underlying">The <see cref="TextWithTerminator"/> instance which has been rotated.</param>
 10/// <param name="Rotation">
 11/// The number of characters to rotate: positive = rightwards, negative = leftwards.
 12/// </param>
 13/// <remarks>
 14/// A virtually rotated terminator-terminated text is required by Burrows-Wheeler Transform construction, when the
 15/// length of the text is too high to build the Burrows-Wheeler Matrix, which would have n^2 items.
 16/// </remarks>
 18461417public record VirtuallyRotatedTextWithTerminator(RotatedTextWithTerminator Underlying, int Rotation)
 1044018    : IValueEnumerable<char>, IComparable<VirtuallyRotatedTextWithTerminator>
 1044019{
 1044020    // CharOrTerminatorComparer is a record, so compared by value
 1044021    private readonly IComparer<char> _charsComparer = CharOrTerminatorComparer.Build(Underlying.Terminator);
 1044022
 1044023    private sealed class Enumerator : IEnumerator<char>
 1044024    {
 1044025        private readonly RotatedTextWithTerminator _underlying;
 1044026        private readonly int _rotation;
 1044027        private int _current;
 1044028
 6276929        public Enumerator(RotatedTextWithTerminator underlying, int rotation)
 6276930        {
 6276931            _underlying = underlying;
 6276932            _rotation = rotation;
 6276933            Reset();
 6276934        }
 1044035
 1044036        public char Current
 1044037        {
 1044038            get
 17031839            {
 17031840                if (_current < 0)
 141                    throw new InvalidOperationException($"Enumeration has not started. Call {nameof(MoveNext)}.");
 17031742                if (_current >= _underlying.Length)
 143                    throw new InvalidOperationException("Enumeration already finished");
 17031644                var index = (_current - _rotation) % _underlying.Length;
 17031645                return _underlying[index >= 0 ? index : _underlying.Length + index];
 17031646            }
 1044047        }
 1044048
 1549        object System.Collections.IEnumerator.Current => Current;
 1044050
 1044051        public void Dispose()
 6276752        {
 1044053            // Nothing, for the time being
 6276754        }
 10760855        public bool MoveNext() => ++_current < _underlying.Length;
 6277156        public void Reset() => _current = -1;
 1044057    }
 1044058
 1044059    /// <summary>
 1044060    /// Select a part of <see cref="Underlying"/> by the provided index (either w.r.t. the start or to the end of the
 1044061    /// text), applying the <see cref="Rotation"/>. Treat <paramref name="index"/> as circular, over modulo the length
 1044062    /// of <see cref="Underlying"/>.
 1044063    /// </summary>
 1044064    /// <param name="index">The index applied to the underlying string.</param>
 1044065    /// <returns>A char containing the selected part.</returns>
 1044066    public char this[Index index]
 1044067    {
 1044068        get
 925269        {
 925270            var length = Underlying.Length;
 925271            var rotatedIndex = (index.GetOffset(length) - Rotation) % length;
 925272            return Underlying[rotatedIndex >= 0 ? rotatedIndex : length + rotatedIndex];
 925273        }
 1044074    }
 1044075
 1044076    /// <inheritdoc/>
 1044077    public IEnumerator<char> GetEnumerator() =>
 6276978        new Enumerator(Underlying, Rotation);
 1044079
 1044080    /// <inheritdoc/>
 1044081    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() =>
 282        GetEnumerator();
 1044083
 1044084    /// <inheritdoc/>
 1044085    public int CompareTo(VirtuallyRotatedTextWithTerminator? other)
 3138386    {
 3138387        if (other == null)
 188            throw new ArgumentNullException(nameof(other), "Cannot compare to null.");
 1044089
 3138290        using var enumerator = GetEnumerator();
 3138291        using var otherEnumerator = other.GetEnumerator();
 1044092
 3138293        var moveNext = enumerator.MoveNext();
 3138294        var otherMoveNext = otherEnumerator.MoveNext();
 1044095
 5378396        while (moveNext && otherMoveNext && enumerator.Current == otherEnumerator.Current)
 2240197        {
 2240198            moveNext = enumerator.MoveNext();
 2240199            otherMoveNext = otherEnumerator.MoveNext();
 22401100        }
 10440101
 31383102        if (moveNext && !otherMoveNext) return 1;
 31382103        if (!moveNext && otherMoveNext) return -1;
 62751104        if (moveNext) return _charsComparer.Compare(enumerator.Current, otherEnumerator.Current);
 9105        return 0;
 31382106    }
 10440107}