LuaStack.cs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using System.Runtime.CompilerServices;
  2. using Lua.Internal;
  3. namespace Lua.Runtime;
  4. public class LuaStack(int initialSize = 256)
  5. {
  6. LuaValue[] array = new LuaValue[initialSize];
  7. int top;
  8. public int Count => top;
  9. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  10. public void EnsureCapacity(int newSize)
  11. {
  12. var size = array.Length;
  13. if (size >= newSize) return;
  14. while (size < newSize)
  15. {
  16. size *= 2;
  17. }
  18. Array.Resize(ref array, size);
  19. }
  20. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  21. public void NotifyTop(int top)
  22. {
  23. if (this.top < top) this.top = top;
  24. }
  25. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  26. public void Push(LuaValue value)
  27. {
  28. EnsureCapacity(top + 1);
  29. UnsafeGet(top) = value;
  30. top++;
  31. }
  32. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  33. public void PushRange(ReadOnlySpan<LuaValue> values)
  34. {
  35. EnsureCapacity(top + values.Length);
  36. values.CopyTo(array.AsSpan()[top..]);
  37. top += values.Length;
  38. }
  39. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  40. public LuaValue Pop()
  41. {
  42. if (top == 0) ThrowEmptyStack();
  43. top--;
  44. var item = UnsafeGet(top);
  45. UnsafeGet(top) = default;
  46. return item;
  47. }
  48. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  49. public void PopUntil(int newSize)
  50. {
  51. if (newSize >= top) return;
  52. if (newSize == 0)
  53. {
  54. array.AsSpan().Clear();
  55. }
  56. else
  57. {
  58. array.AsSpan(newSize - 1).Clear();
  59. }
  60. top = newSize;
  61. }
  62. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  63. public void Clear()
  64. {
  65. array.AsSpan().Clear();
  66. top = 0;
  67. }
  68. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  69. public Span<LuaValue> AsSpan()
  70. {
  71. return new Span<LuaValue>(array, 0, top);
  72. }
  73. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  74. public Span<LuaValue> GetBuffer()
  75. {
  76. return array.AsSpan();
  77. }
  78. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  79. public Memory<LuaValue> GetBufferMemory()
  80. {
  81. return array.AsMemory();
  82. }
  83. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  84. public ref LuaValue UnsafeGet(int index)
  85. {
  86. return ref MemoryMarshalEx.UnsafeElementAt(array, index);
  87. }
  88. static void ThrowEmptyStack()
  89. {
  90. throw new InvalidOperationException("Empty stack");
  91. }
  92. }