< Summary

Class:Towel.DataStructures.StackArray<T>
Assembly:Towel
File(s):File 1: /home/runner/work/Towel/Towel/Sources/Towel/DataStructures/Stack.cs
Covered lines:29
Uncovered lines:50
Coverable lines:79
Total lines:320
Line coverage:36.7% (29 of 79)
Covered branches:10
Total branches:24
Branch coverage:41.6% (10 of 24)

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: .ctor()100%1100%
File 1: .ctor(...)0%20%
File 1: .ctor(...)100%10%
File 1: .ctor(...)100%10%
File 1: get_CurrentCapacity()100%10%
File 1: get_MinimumCapacity()100%10%
File 1: set_MinimumCapacity(...)0%60%
File 1: get_Count()100%1100%
File 1: Clone()100%10%
File 1: ToArray()0%20%
File 1: Push(...)75%480%
File 1: Pop()83.33%672.72%
File 1: Peek()100%10%
File 1: Clear()0%20%
File 1: StepperBreak(...)100%1100%
File 1: System.Collections.IEnumerable.GetEnumerator()100%10%
File 1: GetEnumerator()100%2100%

File(s)

/home/runner/work/Towel/Towel/Sources/Towel/DataStructures/Stack.cs

#LineLine coverage
 1namespace Towel.DataStructures;
 2
 3/// <summary>Implements a First-In-Last-Out stack data structure.</summary>
 4/// <typeparam name="T">The generic type within the structure.</typeparam>
 5public interface IStack<T> : IDataStructure<T>,
 6  DataStructure.ICountable,
 7  DataStructure.IClearable
 8{
 9  #region Methods
 10
 11  /// <summary>Adds an item to the top of the stack.</summary>
 12  /// <param name="push">The item to add to the stack.</param>
 13  void Push(T push);
 14  /// <summary>Returns the most recent addition to the stack.</summary>
 15  /// <returns>The most recent addition to the stack.</returns>
 16  T Peek();
 17  /// <summary>Removes and returns the most recent addition to the stack.</summary>
 18  /// <returns>The most recent addition to the stack.</returns>
 19  T Pop();
 20
 21  #endregion
 22}
 23
 24/// <summary>Implements a First-In-Last-Out stack data structure using a linked list.</summary>
 25/// <typeparam name="T">The generic type within the structure.</typeparam>
 26public class StackLinked<T> : IStack<T>, ICloneable<StackLinked<T>>
 27{
 28  internal Node? _top;
 29  internal int _count;
 30
 31  #region Nested Types
 32
 33  internal class Node
 34  {
 35    internal T Value;
 36    internal Node? Down;
 37
 38    internal Node(T value, Node? down = null)
 39    {
 40      Value = value;
 41      Down = down;
 42    }
 43  }
 44
 45  #endregion
 46
 47  #region Constructors
 48
 49  /// <summary>Constructs a new stack.</summary>
 50  public StackLinked()
 51  {
 52    _top = null;
 53    _count = 0;
 54  }
 55
 56  /// <summary>This constructor is for cloning purposes.</summary>
 57  /// <param name="stack">The stack to clone.</param>
 58  internal StackLinked(StackLinked<T> stack)
 59  {
 60    if (stack._top is not null)
 61    {
 62      _top = new Node(value: stack._top.Value);
 63      Node? a = stack._top.Down;
 64      Node? b = _top;
 65      while (a is not null)
 66      {
 67        b.Down = new Node(value: a.Value);
 68        b = b.Down;
 69        a = a.Down;
 70      }
 71      _count = stack._count;
 72    }
 73  }
 74
 75  #endregion
 76
 77  #region Properties
 78
 79  /// <inheritdoc/>
 80  public int Count => _count;
 81
 82  #endregion
 83
 84  #region Methods
 85
 86  /// <inheritdoc/>
 87  public StackLinked<T> Clone() => new(this);
 88
 89  /// <inheritdoc/>
 90  public T[] ToArray()
 91  {
 92    if (_count is 0)
 93    {
 94      return Array.Empty<T>();
 95    }
 96    T[] array = new T[_count];
 97    for (var (i, node) = (0, _top); node is not null; node = node.Down, i++)
 98    {
 99      array[i] = node.Value;
 100    }
 101    return array;
 102  }
 103
 104  /// <inheritdoc/>
 105  public void Push(T addition)
 106  {
 107    _top = new Node(value: addition, down: _top);
 108    _count++;
 109  }
 110
 111  /// <inheritdoc/>
 112  public T Peek()
 113  {
 114    if (_top is null)
 115    {
 116      throw new InvalidOperationException("Attempting to remove from an empty queue.");
 117    }
 118    T peek = _top.Value;
 119    return peek;
 120  }
 121
 122  /// <inheritdoc/>
 123  public T Pop()
 124  {
 125    if (_count is 0)
 126    {
 127      throw new InvalidOperationException("attempting to pop from an empty stack.");
 128    }
 129    if (_top is null)
 130    {
 131      throw new TowelBugException($"{nameof(Count)} is greater than 0 but {nameof(_top)} is null");
 132    }
 133    T pop = _top.Value;
 134    _top = _top.Down;
 135    _count--;
 136    return pop;
 137  }
 138
 139  /// <inheritdoc/>
 140  public void Clear()
 141  {
 142    _top = null;
 143    _count = 0;
 144  }
 145
 146  /// <inheritdoc/>
 147  public StepStatus StepperBreak<TStep>(TStep step = default)
 148    where TStep : struct, IFunc<T, StepStatus>
 149  {
 150    for (Node? node = _top; node is not null; node = node.Down)
 151    {
 152      if (step.Invoke(node.Value) is Break)
 153      {
 154        return Break;
 155      }
 156    }
 157    return Continue;
 158  }
 159
 160  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 161
 162  /// <inheritdoc/>
 163  public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 164  {
 165    for (Node? node = _top; node is not null; node = node.Down)
 166    {
 167      yield return node.Value;
 168    }
 169  }
 170
 171  #endregion
 172}
 173
 174/// <summary>Implements a First-In-Last-Out stack data structure using an array.</summary>
 175/// <typeparam name="T">The generic type within the structure.</typeparam>
 176public class StackArray<T> : IStack<T>, ICloneable<StackArray<T>>
 177{
 178  internal const int DefaultMinimumCapacity = 1;
 179
 180  internal T[] _array;
 181  internal int _count;
 182  internal int? _minimumCapacity;
 183
 184  #region Constructors
 185
 186  /// <summary>Constructs a new stack.</summary>
 10187  public StackArray()
 10188  {
 10189    _array = new T[DefaultMinimumCapacity];
 10190    _count = 0;
 10191  }
 192
 193  /// <summary>Constructs a new stack.</summary>
 194  /// <param name="minimumCapacity">The minimum capacity of the stack.</param>
 0195  public StackArray(int minimumCapacity)
 0196  {
 0197    if (minimumCapacity <= 0)
 0198    {
 0199      throw new ArgumentOutOfRangeException(nameof(minimumCapacity), minimumCapacity, $"{nameof(minimumCapacity)} <= 0")
 200    }
 0201    _array = new T[minimumCapacity];
 0202    _count = 0;
 0203    _minimumCapacity = minimumCapacity;
 0204  }
 205
 0206  internal StackArray(T[] array, int count, int? minimumCapacity)
 0207  {
 0208    _array = array;
 0209    _count = count;
 0210    _minimumCapacity = minimumCapacity;
 0211  }
 212
 213  /// <summary>This constructor is for cloning purposes.</summary>
 214  /// <param name="stack">The stack to clone.</param>
 0215  internal StackArray(StackArray<T> stack)
 0216  {
 0217    _array = (T[])stack._array.Clone();
 0218    _count = stack._count;
 0219    _minimumCapacity = stack._minimumCapacity;
 0220  }
 221
 222  #endregion
 223
 224  #region Properties
 225
 226  /// <summary>Gets the current capacity of the list.</summary>
 0227  public int CurrentCapacity => _array.Length;
 228
 229  /// <summary>Allows you to adjust the minimum capacity of this list.</summary>
 230  public int? MinimumCapacity
 231  {
 0232    get => _minimumCapacity;
 233    set
 0234    {
 0235      if (!value.HasValue)
 0236      {
 0237        _minimumCapacity = value;
 0238      }
 0239      else if (value < 1)
 0240      {
 0241        throw new InvalidOperationException("Attempting to set a minimum capacity to a negative or zero value.");
 242      }
 0243      else if (value > _array.Length)
 0244      {
 0245        Array.Resize<T>(ref _array, value.Value);
 0246      }
 0247      _minimumCapacity = value;
 0248    }
 249  }
 250
 251  /// <inheritdoc/>
 5252  public int Count => _count;
 253
 254  #endregion
 255
 256  #region Methods
 257
 258  /// <inheritdoc/>
 0259  public StackArray<T> Clone() => new(this);
 260
 261  /// <inheritdoc/>
 0262  public T[] ToArray() => _count is 0 ? Array.Empty<T>() : _array[.._count];
 263
 264  /// <inheritdoc/>
 265  public void Push(T addition)
 20048266  {
 20048267    if (_count == _array.Length)
 46268    {
 46269      if (_array.Length > int.MaxValue / 2)
 0270      {
 0271        throw new InvalidOperationException("your queue is so large that it can no longer double itself (Int32.MaxValue 
 272      }
 46273      Array.Resize<T>(ref _array, _array.Length * 2);
 46274    }
 20048275    _array[_count++] = addition;
 20048276  }
 277
 278  /// <inheritdoc/>
 279  public T Pop()
 20018280  {
 20018281    if (_count is 0)
 2282    {
 2283      throw new InvalidOperationException("attempting to pop from an empty stack.");
 284    }
 20016285    if (_count < _array.Length / 4 && _array.Length / 2 > _minimumCapacity)
 0286    {
 0287      Array.Resize<T>(ref _array, _array.Length / 2);
 0288    }
 20016289    T returnValue = _array[--_count];
 20016290    return returnValue;
 20016291  }
 292
 293  /// <inheritdoc/>
 0294  public T Peek() => _array[_count - 1];
 295
 296  /// <inheritdoc/>
 297  public void Clear()
 0298  {
 0299    _array = new T[_minimumCapacity ?? DefaultMinimumCapacity];
 0300    _count = 0;
 0301  }
 302
 303  /// <inheritdoc/>
 304  public StepStatus StepperBreak<TStep>(TStep step = default)
 305    where TStep : struct, IFunc<T, StepStatus> =>
 3306    _array.StepperBreak(0, _count, step);
 307
 0308  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 309
 310  /// <inheritdoc/>
 311  public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 6312  {
 76313    for (int i = 0; i < _count; i++)
 32314    {
 32315      yield return _array[i];
 32316    }
 6317  }
 318
 319  #endregion
 320}