FastListCore.cs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using System.Runtime.InteropServices;
  4. namespace LitMotion.Collections
  5. {
  6. /// <summary>
  7. /// A list of minimal features. Note that it is NOT thread-safe and must NOT be marked readonly as it is a mutable struct.
  8. /// </summary>
  9. /// <typeparam name="T">Element type</typeparam>
  10. [StructLayout(LayoutKind.Auto)]
  11. public struct FastListCore<T>
  12. {
  13. const int InitialCapacity = 8;
  14. public static readonly FastListCore<T> Empty = default;
  15. T[] array;
  16. int tailIndex;
  17. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  18. public void Add(T element)
  19. {
  20. if (array == null)
  21. {
  22. array = new T[InitialCapacity];
  23. }
  24. else if (array.Length == tailIndex)
  25. {
  26. Array.Resize(ref array, tailIndex * 2);
  27. }
  28. array[tailIndex] = element;
  29. tailIndex++;
  30. }
  31. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  32. public void RemoveAtSwapback(int index)
  33. {
  34. Error.IsNull(array);
  35. CheckIndex(index);
  36. array[index] = array[tailIndex - 1];
  37. array[tailIndex - 1] = default;
  38. tailIndex--;
  39. }
  40. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  41. public void Clear(bool removeArray = false)
  42. {
  43. if (array == null) return;
  44. array.AsSpan().Clear();
  45. tailIndex = 0;
  46. if (removeArray) array = null;
  47. }
  48. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  49. public void EnsureCapacity(int capacity)
  50. {
  51. if (array == null)
  52. {
  53. array = new T[InitialCapacity];
  54. }
  55. while (array.Length < capacity)
  56. {
  57. Array.Resize(ref array, array.Length * 2);
  58. }
  59. }
  60. public readonly T this[int index]
  61. {
  62. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  63. get => array[index];
  64. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  65. set => array[index] = value;
  66. }
  67. public readonly int Length
  68. {
  69. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  70. get => tailIndex;
  71. }
  72. public readonly Span<T> AsSpan() => array == null ? Span<T>.Empty : array.AsSpan(0, tailIndex);
  73. public readonly T[] AsArray() => array;
  74. readonly void CheckIndex(int index)
  75. {
  76. if (index < 0 || index > tailIndex) throw new IndexOutOfRangeException();
  77. }
  78. }
  79. }