mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Merge remote-tracking branch 'origin/master' into api14-rollup
This commit is contained in:
commit
6f8e33a39c
33 changed files with 1057 additions and 496 deletions
|
|
@ -1,7 +1,12 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Dalamud.Bindings.ImGui;
|
||||
|
||||
/// <summary>
|
||||
/// A structure representing a dynamic array for unmanaged types.
|
||||
/// </summary>
|
||||
public unsafe struct ImVector
|
||||
{
|
||||
public readonly int Size;
|
||||
|
|
@ -15,23 +20,23 @@ public unsafe struct ImVector
|
|||
Data = data;
|
||||
}
|
||||
|
||||
public ref T Ref<T>(int index)
|
||||
{
|
||||
return ref Unsafe.AsRef<T>((byte*)Data + index * Unsafe.SizeOf<T>());
|
||||
}
|
||||
public readonly ref T Ref<T>(int index) => ref Unsafe.AsRef<T>((byte*)this.Data + (index * Unsafe.SizeOf<T>()));
|
||||
|
||||
public IntPtr Address<T>(int index)
|
||||
{
|
||||
return (IntPtr)((byte*)Data + index * Unsafe.SizeOf<T>());
|
||||
}
|
||||
public readonly nint Address<T>(int index) => (nint)((byte*)this.Data + (index * Unsafe.SizeOf<T>()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A structure representing a dynamic array for unmanaged types.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of elements in the vector, must be unmanaged.</typeparam>
|
||||
public unsafe struct ImVector<T> where T : unmanaged
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct ImVector<T> : IEnumerable<T>
|
||||
where T : unmanaged
|
||||
{
|
||||
private int size;
|
||||
private int capacity;
|
||||
private T* data;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ImVector{T}"/> struct with the specified size, capacity, and data pointer.
|
||||
/// </summary>
|
||||
|
|
@ -45,11 +50,6 @@ public unsafe struct ImVector<T> where T : unmanaged
|
|||
this.data = data;
|
||||
}
|
||||
|
||||
private int size;
|
||||
private int capacity;
|
||||
private unsafe T* data;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the element at the specified index.
|
||||
/// </summary>
|
||||
|
|
@ -58,80 +58,72 @@ public unsafe struct ImVector<T> where T : unmanaged
|
|||
/// <exception cref="IndexOutOfRangeException">Thrown when the index is out of range.</exception>
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
readonly get
|
||||
{
|
||||
if (index < 0 || index >= size)
|
||||
{
|
||||
if (index < 0 || index >= this.size)
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
return data[index];
|
||||
return this.data[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (index < 0 || index >= size)
|
||||
{
|
||||
if (index < 0 || index >= this.size)
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
data[index] = value;
|
||||
this.data[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the first element of the vector.
|
||||
/// </summary>
|
||||
public readonly T* Data => data;
|
||||
public readonly T* Data => this.data;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the first element of the vector.
|
||||
/// </summary>
|
||||
public readonly T* Front => data;
|
||||
public readonly T* Front => this.data;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the last element of the vector.
|
||||
/// </summary>
|
||||
public readonly T* Back => size > 0 ? data + size - 1 : null;
|
||||
public readonly T* Back => this.size > 0 ? this.data + this.size - 1 : null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the capacity of the vector.
|
||||
/// </summary>
|
||||
public int Capacity
|
||||
{
|
||||
readonly get => capacity;
|
||||
readonly get => this.capacity;
|
||||
set
|
||||
{
|
||||
if (capacity == value)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfLessThan(value, this.size, nameof(Capacity));
|
||||
if (this.capacity == value)
|
||||
return;
|
||||
}
|
||||
|
||||
if (data == null)
|
||||
if (this.data == null)
|
||||
{
|
||||
data = (T*)ImGui.MemAlloc((nuint)(value * sizeof(T)));
|
||||
this.data = (T*)ImGui.MemAlloc((nuint)(value * sizeof(T)));
|
||||
}
|
||||
else
|
||||
{
|
||||
int newSize = Math.Min(size, value);
|
||||
T* newData = (T*)ImGui.MemAlloc((nuint)(value * sizeof(T)));
|
||||
Buffer.MemoryCopy(data, newData, (nuint)(value * sizeof(T)), (nuint)(newSize * sizeof(T)));
|
||||
ImGui.MemFree(data);
|
||||
data = newData;
|
||||
size = newSize;
|
||||
var newSize = Math.Min(this.size, value);
|
||||
var newData = (T*)ImGui.MemAlloc((nuint)(value * sizeof(T)));
|
||||
Buffer.MemoryCopy(this.data, newData, (nuint)(value * sizeof(T)), (nuint)(newSize * sizeof(T)));
|
||||
ImGui.MemFree(this.data);
|
||||
this.data = newData;
|
||||
this.size = newSize;
|
||||
}
|
||||
|
||||
capacity = value;
|
||||
this.capacity = value;
|
||||
|
||||
// Clear the rest of the data
|
||||
for (int i = size; i < capacity; i++)
|
||||
{
|
||||
data[i] = default;
|
||||
}
|
||||
new Span<T>(this.data + this.size, this.capacity - this.size).Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of elements in the vector.
|
||||
/// </summary>
|
||||
public readonly int Size => size;
|
||||
public readonly int Size => this.size;
|
||||
|
||||
/// <summary>
|
||||
/// Grows the capacity of the vector to at least the specified value.
|
||||
|
|
@ -139,10 +131,8 @@ public unsafe struct ImVector<T> where T : unmanaged
|
|||
/// <param name="newCapacity">The new capacity.</param>
|
||||
public void Grow(int newCapacity)
|
||||
{
|
||||
if (newCapacity > capacity)
|
||||
{
|
||||
Capacity = newCapacity * 2;
|
||||
}
|
||||
var newCapacity2 = this.capacity > 0 ? this.capacity + (this.capacity / 2) : 8;
|
||||
this.Capacity = newCapacity2 > newCapacity ? newCapacity2 : newCapacity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -151,10 +141,8 @@ public unsafe struct ImVector<T> where T : unmanaged
|
|||
/// <param name="size">The minimum capacity required.</param>
|
||||
public void EnsureCapacity(int size)
|
||||
{
|
||||
if (size > capacity)
|
||||
{
|
||||
if (size > this.capacity)
|
||||
Grow(size);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -164,25 +152,46 @@ public unsafe struct ImVector<T> where T : unmanaged
|
|||
public void Resize(int newSize)
|
||||
{
|
||||
EnsureCapacity(newSize);
|
||||
size = newSize;
|
||||
this.size = newSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all elements from the vector.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
public void Clear() => this.size = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Adds an element to the end of the vector.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to add.</param>
|
||||
[OverloadResolutionPriority(1)]
|
||||
public void PushBack(T value)
|
||||
{
|
||||
size = 0;
|
||||
this.EnsureCapacity(this.size + 1);
|
||||
this.data[this.size++] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an element to the end of the vector.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to add.</param>
|
||||
public void PushBack(T value)
|
||||
[OverloadResolutionPriority(2)]
|
||||
public void PushBack(in T value)
|
||||
{
|
||||
EnsureCapacity(size + 1);
|
||||
data[size++] = value;
|
||||
EnsureCapacity(this.size + 1);
|
||||
this.data[this.size++] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an element to the front of the vector.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to add.</param>
|
||||
public void PushFront(in T value)
|
||||
{
|
||||
if (this.size == 0)
|
||||
this.PushBack(value);
|
||||
else
|
||||
this.Insert(0, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -190,48 +199,126 @@ public unsafe struct ImVector<T> where T : unmanaged
|
|||
/// </summary>
|
||||
public void PopBack()
|
||||
{
|
||||
if (size > 0)
|
||||
if (this.size > 0)
|
||||
{
|
||||
size--;
|
||||
this.size--;
|
||||
}
|
||||
}
|
||||
|
||||
public ref T Insert(int index, in T v) {
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(index, nameof(index));
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, this.size, nameof(index));
|
||||
this.EnsureCapacity(this.size + 1);
|
||||
if (index < this.size)
|
||||
{
|
||||
Buffer.MemoryCopy(
|
||||
this.data + index,
|
||||
this.data + index + 1,
|
||||
(this.size - index) * sizeof(T),
|
||||
(this.size - index) * sizeof(T));
|
||||
}
|
||||
|
||||
this.data[index] = v;
|
||||
this.size++;
|
||||
return ref this.data[index];
|
||||
}
|
||||
|
||||
public Span<T> InsertRange(int index, ReadOnlySpan<T> v)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(index, nameof(index));
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, this.size, nameof(index));
|
||||
this.EnsureCapacity(this.size + v.Length);
|
||||
if (index < this.size)
|
||||
{
|
||||
Buffer.MemoryCopy(
|
||||
this.data + index,
|
||||
this.data + index + v.Length,
|
||||
(this.size - index) * sizeof(T),
|
||||
(this.size - index) * sizeof(T));
|
||||
}
|
||||
|
||||
var dstSpan = new Span<T>(this.data + index, v.Length);
|
||||
v.CopyTo(new(this.data + index, v.Length));
|
||||
this.size += v.Length;
|
||||
return dstSpan;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Frees the memory allocated for the vector.
|
||||
/// </summary>
|
||||
public void Free()
|
||||
{
|
||||
if (data != null)
|
||||
if (this.data != null)
|
||||
{
|
||||
ImGui.MemFree(data);
|
||||
data = null;
|
||||
size = 0;
|
||||
capacity = 0;
|
||||
ImGui.MemFree(this.data);
|
||||
this.data = null;
|
||||
this.size = 0;
|
||||
this.capacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public ref T Ref(int index)
|
||||
public readonly ref T Ref(int index)
|
||||
{
|
||||
return ref Unsafe.AsRef<T>((byte*)Data + index * Unsafe.SizeOf<T>());
|
||||
return ref Unsafe.AsRef<T>((byte*)Data + (index * Unsafe.SizeOf<T>()));
|
||||
}
|
||||
|
||||
public ref TCast Ref<TCast>(int index)
|
||||
public readonly ref TCast Ref<TCast>(int index)
|
||||
{
|
||||
return ref Unsafe.AsRef<TCast>((byte*)Data + index * Unsafe.SizeOf<TCast>());
|
||||
return ref Unsafe.AsRef<TCast>((byte*)Data + (index * Unsafe.SizeOf<TCast>()));
|
||||
}
|
||||
|
||||
public void* Address(int index)
|
||||
public readonly void* Address(int index)
|
||||
{
|
||||
return (byte*)Data + index * Unsafe.SizeOf<T>();
|
||||
return (byte*)Data + (index * Unsafe.SizeOf<T>());
|
||||
}
|
||||
|
||||
public void* Address<TCast>(int index)
|
||||
public readonly void* Address<TCast>(int index)
|
||||
{
|
||||
return (byte*)Data + index * Unsafe.SizeOf<TCast>();
|
||||
return (byte*)Data + (index * Unsafe.SizeOf<TCast>());
|
||||
}
|
||||
|
||||
public ImVector* ToUntyped()
|
||||
public readonly ImVector* ToUntyped()
|
||||
{
|
||||
return (ImVector*)Unsafe.AsPointer(ref this);
|
||||
return (ImVector*)Unsafe.AsPointer(ref Unsafe.AsRef(in this));
|
||||
}
|
||||
|
||||
public readonly Span<T> AsSpan() => new(this.data, this.size);
|
||||
|
||||
public readonly Enumerator GetEnumerator() => new(this.data, this.data + this.size);
|
||||
|
||||
readonly IEnumerator<T> IEnumerable<T>.GetEnumerator() => this.GetEnumerator();
|
||||
|
||||
readonly IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
||||
|
||||
public struct Enumerator(T* begin, T* end) : IEnumerator<T>, IEnumerable<T>
|
||||
{
|
||||
private T* current = null;
|
||||
|
||||
public readonly ref T Current => ref *this.current;
|
||||
|
||||
readonly T IEnumerator<T>.Current => this.Current;
|
||||
|
||||
readonly object IEnumerator.Current => this.Current;
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
var next = this.current == null ? begin : this.current + 1;
|
||||
if (next == end)
|
||||
return false;
|
||||
this.current = next;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset() => this.current = null;
|
||||
|
||||
public readonly Enumerator GetEnumerator() => new(begin, end);
|
||||
|
||||
readonly void IDisposable.Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
readonly IEnumerator<T> IEnumerable<T>.GetEnumerator() => this.GetEnumerator();
|
||||
|
||||
readonly IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue