< Summary

Class:GDX.Collections.Generic.CircularBuffer[T]
Assembly:GDX
File(s):D:/BuildAgent/work/GDX-Documentation/Projects/GDX_Development/Packages/com.dotbunny.gdx/GDX/Collections/Generic/CircularBuffer.cs
Covered lines:88
Uncovered lines:49
Coverable lines:137
Total lines:315
Line coverage:64.2% (88 of 137)
Covered branches:0
Total branches:0
Covered methods:14
Total methods:15
Method coverage:93.3% (14 of 15)

Coverage History

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
CircularBuffer(...)0%4.134080%
CircularBuffer(...)0%42600%
Add(...)0%110100%
Clear()0%220100%
GetBack()0%330100%
GetFront()0%110100%
IsEmpty()0%110100%
IsFull()0%110100%
PopBack()0%2.152066.67%
PopFront()0%2.212062.5%
PushBack(...)0%4.064084.21%
PushFront(...)0%6.984042.86%
ToArray()0%4.964060.87%

File(s)

D:/BuildAgent/work/GDX-Documentation/Projects/GDX_Development/Packages/com.dotbunny.gdx/GDX/Collections/Generic/CircularBuffer.cs

#LineLine coverage
 1// Copyright (c) 2020-2022 dotBunny Inc.
 2// dotBunny licenses this file to you under the BSL-1.0 license.
 3// See the LICENSE file in the project root for more information.
 4
 5using System;
 6using System.Runtime.CompilerServices;
 7
 8namespace GDX.Collections.Generic
 9{
 10    /// <summary>
 11    ///     A sized buffer which loops back over itself as elements are used.
 12    /// </summary>
 13    /// <typeparam name="T">The type of <see cref="object" />s contained within.</typeparam>
 14    [VisualScriptingCompatible(1)]
 15    public struct CircularBuffer<T>
 16    {
 17        /// <summary>
 18        ///     Internal array of backed data for the <see cref="CircularBuffer{T}" />.
 19        /// </summary>
 20        public readonly T[] Array;
 21
 22        /// <summary>
 23        ///     The cached array length for <see cref="Array" />.
 24        /// </summary>
 25        public readonly int Capacity;
 26
 27        /// <summary>
 28        ///     The current size of occupied elements in the <see cref="CircularBuffer{T}" />.
 29        /// </summary>
 30        /// <remarks>CAUTION! Changing this will alter the understanding of the data.</remarks>
 31        public int Count;
 32
 33        /// <summary>
 34        ///     The index of the last item in <see cref="Array" />.
 35        /// </summary>
 36        /// <remarks>CAUTION! Changing this will alter the understanding of the data.</remarks>
 37        public int EndIndex;
 38
 39        /// <summary>
 40        ///     The index of the first item in <see cref="Array" />.
 41        /// </summary>
 42        /// <remarks>CAUTION! Changing this will alter the understanding of the data.</remarks>
 43        public int StartIndex;
 44
 45        /// <summary>
 46        ///     Create a <see cref="CircularBuffer{T}" /> with a <paramref name="capacity" />.
 47        /// </summary>
 48        /// <param name="capacity">The maximum number of items allowed in the <see cref="CircularBuffer{T}" /></param>
 49        public CircularBuffer(int capacity)
 2250        {
 2251            if (capacity < 1)
 052            {
 053                throw new ArgumentException("Circular buffer cannot have negative or zero capacity.", nameof(capacity));
 54            }
 55
 2256            Array = new T[capacity];
 2257            Capacity = capacity;
 58
 2259            Count = 0;
 60
 2261            StartIndex = 0;
 2262            EndIndex = Count == capacity ? 0 : Count;
 2263        }
 64
 65        /// <summary>
 66        ///     Create a <see cref="CircularBuffer{T}" /> with a <paramref name="capacity" />, filling with
 67        ///     <paramref name="targetItems"/>.
 68        /// </summary>
 69        /// <param name="capacity">The maximum number of items allowed in the <see cref="CircularBuffer{T}" /></param>
 70        /// <param name="targetItems">An array of values to fill the <see cref="CircularBuffer{T}" /> with.</param>
 71        /// <exception cref="ArgumentException">
 72        ///     Invalid number of entries provided to the <see cref="CircularBuffer{T}" />
 73        ///     constructor.
 74        /// </exception>
 75        /// <exception cref="ArgumentNullException">No items were provided to the <see cref="CircularBuffer{T}" /> const
 76        public CircularBuffer(int capacity, T[] targetItems)
 077        {
 078            if (capacity < 1)
 079            {
 080                throw new ArgumentException("Circular buffer cannot have negative or zero capacity.", nameof(capacity));
 81            }
 82
 083            if (targetItems == null)
 084            {
 085                throw new ArgumentNullException(nameof(targetItems));
 86            }
 87
 088            if (targetItems.Length > capacity)
 089            {
 090                throw new ArgumentException("Too many items to fit circular buffer", nameof(targetItems));
 91            }
 92
 093            Array = new T[capacity];
 094            Capacity = capacity;
 95
 096            System.Array.Copy(targetItems, Array, targetItems.Length);
 097            Count = targetItems.Length;
 98
 099            StartIndex = 0;
 0100            EndIndex = Count == capacity ? 0 : Count;
 0101        }
 102
 103        /// <summary>
 104        ///     Access item at <paramref name="pseudoIndex" />.
 105        /// </summary>
 106        /// <param name="pseudoIndex"></param>
 107        /// <exception cref="IndexOutOfRangeException">Provided index is out of buffers range.</exception>
 108        public T this[int pseudoIndex]
 109        {
 110            get
 11111            {
 11112                return Array[
 113                    StartIndex +
 114                    (pseudoIndex < Capacity - StartIndex ? pseudoIndex : pseudoIndex - Capacity)];
 11115            }
 116            set
 3117            {
 3118                Array[
 119                    StartIndex +
 120                    (pseudoIndex < Capacity - StartIndex ? pseudoIndex : pseudoIndex - Capacity)] = value;
 3121            }
 122        }
 123
 124        /// <summary>
 125        ///     Add an <paramref name="item" /> to the <see cref="Array" />.
 126        /// </summary>
 127        /// <param name="item">The typed <see cref="object" /> to add.</param>
 128        public void Add(T item)
 95129        {
 95130            PushBack(item);
 95131        }
 132
 133        /// <summary>
 134        ///     Clear all values of the <see cref="Array" />.
 135        /// </summary>
 136        public void Clear()
 2137        {
 20138            for (int i = 0; i < Array.Length; i++)
 8139            {
 8140                Array[i] = default;
 8141            }
 142
 2143            Count = 0;
 2144            StartIndex = 0;
 2145            EndIndex = 0;
 2146        }
 147
 148        /// <summary>
 149        ///     Get the last item in the <see cref="Array" />.
 150        /// </summary>
 151        /// <returns>The last typed object in <see cref="Array" />.</returns>
 152        public T GetBack()
 1153        {
 1154            return Array[(EndIndex != 0 ? EndIndex : Capacity) - 1];
 1155        }
 156
 157        /// <summary>
 158        ///     Get the first item in the <see cref="Array" />.
 159        /// </summary>
 160        /// <returns>The first typed object in <see cref="Array" />.</returns>
 161        public T GetFront()
 1162        {
 1163            return Array[StartIndex];
 1164        }
 165
 166
 167        /// <summary>
 168        ///     Does the <see cref="Array" /> have any items in it?
 169        /// </summary>
 170        /// <returns>true/false</returns>
 171        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 172        public bool IsEmpty()
 3173        {
 3174            return Count == 0;
 3175        }
 176
 177        /// <summary>
 178        ///     Is the <see cref="Array" /> at capacity?
 179        /// </summary>
 180        /// <returns>true/false</returns>
 181        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 182        public bool IsFull()
 2183        {
 2184            return Count == Capacity;
 2185        }
 186
 187        /// <summary>
 188        ///     Remove an item from the end of the <see cref="Array" />.
 189        /// </summary>
 190        public void PopBack()
 1191        {
 1192            if (EndIndex == 0)
 0193            {
 0194                EndIndex = Capacity;
 0195            }
 196
 1197            EndIndex--;
 1198            Array[EndIndex] = default;
 1199            --Count;
 1200        }
 201
 202        /// <summary>
 203        ///     Remove an item from the start of the <see cref="Array" />.
 204        /// </summary>
 205        public void PopFront()
 1206        {
 1207            Array[StartIndex] = default;
 1208            if (++StartIndex == Capacity)
 0209            {
 0210                StartIndex = 0;
 0211            }
 212
 1213            --Count;
 1214        }
 215
 216        /// <summary>
 217        ///     Add an item to the end of the <see cref="Array" />.
 218        /// </summary>
 219        /// <param name="targetItem">The item to add to the end of <see cref="Array" />.</param>
 220        public void PushBack(T targetItem)
 96221        {
 96222            if (Count == Capacity)
 13223            {
 13224                Array[EndIndex] = targetItem;
 13225                if (++EndIndex == Capacity)
 0226                {
 0227                    EndIndex = 0;
 0228                }
 229
 13230                StartIndex = EndIndex;
 13231            }
 232            else
 83233            {
 83234                Array[EndIndex] = targetItem;
 83235                if (++EndIndex == Capacity)
 20236                {
 20237                    EndIndex = 0;
 20238                }
 239
 83240                ++Count;
 83241            }
 96242        }
 243
 244        /// <summary>
 245        ///     Add an item to the start of the <see cref="Array" />.
 246        /// </summary>
 247        /// <param name="targetItem">The item to add to the start of <see cref="Array" />.</param>
 248        public void PushFront(T targetItem)
 1249        {
 1250            if (Count == Capacity)
 1251            {
 1252                if (StartIndex == 0)
 0253                {
 0254                    StartIndex = Capacity;
 0255                }
 256
 1257                StartIndex--;
 1258                EndIndex = StartIndex;
 1259                Array[StartIndex] = targetItem;
 1260            }
 261            else
 0262            {
 0263                if (StartIndex == 0)
 0264                {
 0265                    StartIndex = Capacity;
 0266                }
 267
 0268                StartIndex--;
 0269                Array[StartIndex] = targetItem;
 0270                ++Count;
 0271            }
 1272        }
 273
 274        /// <summary>
 275        ///     Copy <see cref="Array" /> to an array of the same type.
 276        /// </summary>
 277        /// <returns>A copied version of the <see cref="Array" /> as an array.</returns>
 278        public T[] ToArray()
 2279        {
 2280            T[] newArray = new T[Count];
 281
 282            // We dont need to fill anything as its empty.
 2283            if (Count <= 0)
 0284            {
 0285                return newArray;
 286            }
 287
 288            int length;
 289
 290            // First Part
 2291            if (StartIndex < EndIndex)
 0292            {
 0293                length = EndIndex - StartIndex;
 0294                System.Array.Copy(Array, StartIndex, newArray, 0, length);
 0295            }
 296            else
 2297            {
 2298                length = Array.Length - StartIndex;
 2299                System.Array.Copy(Array, StartIndex, newArray, 0, length);
 2300            }
 301
 302            // Second Part
 2303            if (StartIndex > EndIndex)
 0304            {
 0305                System.Array.Copy(Array, EndIndex, newArray, length, 0);
 0306            }
 307            else
 2308            {
 2309                System.Array.Copy(Array, 0, newArray, length, EndIndex);
 2310            }
 311
 2312            return newArray;
 2313        }
 314    }
 315}