< Summary

Class:Towel.DataStructures.StackLinked<T>
Assembly:Towel
File(s):File 1: /home/runner/work/Towel/Towel/Sources/Towel/DataStructures/Stack.cs
Covered lines:38
Uncovered lines:44
Coverable lines:82
Total lines:320
Line coverage:46.3% (38 of 82)
Covered branches:8
Total branches:20
Branch coverage:40% (8 of 20)

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: .ctor(...)100%1100%
File 1: .ctor()100%1100%
File 1: .ctor(...)0%40%
File 1: get_Count()100%1100%
File 1: Clone()100%10%
File 1: ToArray()0%40%
File 1: Push(...)100%1100%
File 1: Peek()0%20%
File 1: Pop()75%483.33%
File 1: Clear()100%10%
File 1: StepperBreak(...)75%477.77%
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
 2012938    internal Node(T value, Node? down = null)
 2012939    {
 2012940      Value = value;
 2012941      Down = down;
 2012942    }
 43  }
 44
 45  #endregion
 46
 47  #region Constructors
 48
 49  /// <summary>Constructs a new stack.</summary>
 1250  public StackLinked()
 1251  {
 1252    _top = null;
 1253    _count = 0;
 1254  }
 55
 56  /// <summary>This constructor is for cloning purposes.</summary>
 57  /// <param name="stack">The stack to clone.</param>
 058  internal StackLinked(StackLinked<T> stack)
 059  {
 060    if (stack._top is not null)
 061    {
 062      _top = new Node(value: stack._top.Value);
 063      Node? a = stack._top.Down;
 064      Node? b = _top;
 065      while (a is not null)
 066      {
 067        b.Down = new Node(value: a.Value);
 068        b = b.Down;
 069        a = a.Down;
 070      }
 071      _count = stack._count;
 072    }
 073  }
 74
 75  #endregion
 76
 77  #region Properties
 78
 79  /// <inheritdoc/>
 580  public int Count => _count;
 81
 82  #endregion
 83
 84  #region Methods
 85
 86  /// <inheritdoc/>
 087  public StackLinked<T> Clone() => new(this);
 88
 89  /// <inheritdoc/>
 90  public T[] ToArray()
 091  {
 092    if (_count is 0)
 093    {
 094      return Array.Empty<T>();
 95    }
 096    T[] array = new T[_count];
 097    for (var (i, node) = (0, _top); node is not null; node = node.Down, i++)
 098    {
 099      array[i] = node.Value;
 0100    }
 0101    return array;
 0102  }
 103
 104  /// <inheritdoc/>
 105  public void Push(T addition)
 20129106  {
 20129107    _top = new Node(value: addition, down: _top);
 20129108    _count++;
 20129109  }
 110
 111  /// <inheritdoc/>
 112  public T Peek()
 0113  {
 0114    if (_top is null)
 0115    {
 0116      throw new InvalidOperationException("Attempting to remove from an empty queue.");
 117    }
 0118    T peek = _top.Value;
 0119    return peek;
 0120  }
 121
 122  /// <inheritdoc/>
 123  public T Pop()
 20099124  {
 20099125    if (_count is 0)
 2126    {
 2127      throw new InvalidOperationException("attempting to pop from an empty stack.");
 128    }
 20097129    if (_top is null)
 0130    {
 0131      throw new TowelBugException($"{nameof(Count)} is greater than 0 but {nameof(_top)} is null");
 132    }
 20097133    T pop = _top.Value;
 20097134    _top = _top.Down;
 20097135    _count--;
 20097136    return pop;
 20097137  }
 138
 139  /// <inheritdoc/>
 140  public void Clear()
 0141  {
 0142    _top = null;
 0143    _count = 0;
 0144  }
 145
 146  /// <inheritdoc/>
 147  public StepStatus StepperBreak<TStep>(TStep step = default)
 148    where TStep : struct, IFunc<T, StepStatus>
 3149  {
 38150    for (Node? node = _top; node is not null; node = node.Down)
 16151    {
 16152      if (step.Invoke(node.Value) is Break)
 0153      {
 0154        return Break;
 155      }
 16156    }
 3157    return Continue;
 3158  }
 159
 0160  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 161
 162  /// <inheritdoc/>
 163  public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 6164  {
 76165    for (Node? node = _top; node is not null; node = node.Down)
 32166    {
 32167      yield return node.Value;
 32168    }
 6169  }
 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>
 187  public StackArray()
 188  {
 189    _array = new T[DefaultMinimumCapacity];
 190    _count = 0;
 191  }
 192
 193  /// <summary>Constructs a new stack.</summary>
 194  /// <param name="minimumCapacity">The minimum capacity of the stack.</param>
 195  public StackArray(int minimumCapacity)
 196  {
 197    if (minimumCapacity <= 0)
 198    {
 199      throw new ArgumentOutOfRangeException(nameof(minimumCapacity), minimumCapacity, $"{nameof(minimumCapacity)} <= 0")
 200    }
 201    _array = new T[minimumCapacity];
 202    _count = 0;
 203    _minimumCapacity = minimumCapacity;
 204  }
 205
 206  internal StackArray(T[] array, int count, int? minimumCapacity)
 207  {
 208    _array = array;
 209    _count = count;
 210    _minimumCapacity = minimumCapacity;
 211  }
 212
 213  /// <summary>This constructor is for cloning purposes.</summary>
 214  /// <param name="stack">The stack to clone.</param>
 215  internal StackArray(StackArray<T> stack)
 216  {
 217    _array = (T[])stack._array.Clone();
 218    _count = stack._count;
 219    _minimumCapacity = stack._minimumCapacity;
 220  }
 221
 222  #endregion
 223
 224  #region Properties
 225
 226  /// <summary>Gets the current capacity of the list.</summary>
 227  public int CurrentCapacity => _array.Length;
 228
 229  /// <summary>Allows you to adjust the minimum capacity of this list.</summary>
 230  public int? MinimumCapacity
 231  {
 232    get => _minimumCapacity;
 233    set
 234    {
 235      if (!value.HasValue)
 236      {
 237        _minimumCapacity = value;
 238      }
 239      else if (value < 1)
 240      {
 241        throw new InvalidOperationException("Attempting to set a minimum capacity to a negative or zero value.");
 242      }
 243      else if (value > _array.Length)
 244      {
 245        Array.Resize<T>(ref _array, value.Value);
 246      }
 247      _minimumCapacity = value;
 248    }
 249  }
 250
 251  /// <inheritdoc/>
 252  public int Count => _count;
 253
 254  #endregion
 255
 256  #region Methods
 257
 258  /// <inheritdoc/>
 259  public StackArray<T> Clone() => new(this);
 260
 261  /// <inheritdoc/>
 262  public T[] ToArray() => _count is 0 ? Array.Empty<T>() : _array[.._count];
 263
 264  /// <inheritdoc/>
 265  public void Push(T addition)
 266  {
 267    if (_count == _array.Length)
 268    {
 269      if (_array.Length > int.MaxValue / 2)
 270      {
 271        throw new InvalidOperationException("your queue is so large that it can no longer double itself (Int32.MaxValue 
 272      }
 273      Array.Resize<T>(ref _array, _array.Length * 2);
 274    }
 275    _array[_count++] = addition;
 276  }
 277
 278  /// <inheritdoc/>
 279  public T Pop()
 280  {
 281    if (_count is 0)
 282    {
 283      throw new InvalidOperationException("attempting to pop from an empty stack.");
 284    }
 285    if (_count < _array.Length / 4 && _array.Length / 2 > _minimumCapacity)
 286    {
 287      Array.Resize<T>(ref _array, _array.Length / 2);
 288    }
 289    T returnValue = _array[--_count];
 290    return returnValue;
 291  }
 292
 293  /// <inheritdoc/>
 294  public T Peek() => _array[_count - 1];
 295
 296  /// <inheritdoc/>
 297  public void Clear()
 298  {
 299    _array = new T[_minimumCapacity ?? DefaultMinimumCapacity];
 300    _count = 0;
 301  }
 302
 303  /// <inheritdoc/>
 304  public StepStatus StepperBreak<TStep>(TStep step = default)
 305    where TStep : struct, IFunc<T, StepStatus> =>
 306    _array.StepperBreak(0, _count, step);
 307
 308  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 309
 310  /// <inheritdoc/>
 311  public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 312  {
 313    for (int i = 0; i < _count; i++)
 314    {
 315      yield return _array[i];
 316    }
 317  }
 318
 319  #endregion
 320}