Improve performance and safety
This commit is contained in:
758
Misaki.HighPerformance.LowLevel/Collections/FixedString.gen.cs
Normal file
758
Misaki.HighPerformance.LowLevel/Collections/FixedString.gen.cs
Normal file
@@ -0,0 +1,758 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Misaki.HighPerformance.LowLevel.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a stack allocated fixed-size UTF-8 encoded string of length 32 bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 32 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString32"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 32)]
|
||||
public unsafe struct FixedString32
|
||||
{
|
||||
public const int MAX_LENGTH = 15;
|
||||
|
||||
private ushort _length;
|
||||
private fixed char _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
return new string(bufferPtr, 0, _length);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
_length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString32.");
|
||||
}
|
||||
|
||||
_length = (ushort)value.Length;
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
fixed (char* valuePtr = value)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, valuePtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString32(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString32(ReadOnlySpan<char> input)
|
||||
{
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString32.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, inputPtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString32(char* input, ushort length)
|
||||
: this(new ReadOnlySpan<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Span<byte> AsSpan()
|
||||
{
|
||||
fixed (char* ptr = _buffer)
|
||||
{
|
||||
return new(ptr, _length);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly char* GetUnsafePtr()
|
||||
{
|
||||
return (char*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a stack allocated fixed-size UTF-8 encoded string of length 64 bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 64 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString64"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 64)]
|
||||
public unsafe struct FixedString64
|
||||
{
|
||||
public const int MAX_LENGTH = 31;
|
||||
|
||||
private ushort _length;
|
||||
private fixed char _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
return new string(bufferPtr, 0, _length);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
_length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString64.");
|
||||
}
|
||||
|
||||
_length = (ushort)value.Length;
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
fixed (char* valuePtr = value)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, valuePtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString64(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString64(ReadOnlySpan<char> input)
|
||||
{
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString64.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, inputPtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString64(char* input, ushort length)
|
||||
: this(new ReadOnlySpan<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Span<byte> AsSpan()
|
||||
{
|
||||
fixed (char* ptr = _buffer)
|
||||
{
|
||||
return new(ptr, _length);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly char* GetUnsafePtr()
|
||||
{
|
||||
return (char*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a stack allocated fixed-size UTF-8 encoded string of length 128 bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 128 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString128"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 128)]
|
||||
public unsafe struct FixedString128
|
||||
{
|
||||
public const int MAX_LENGTH = 63;
|
||||
|
||||
private ushort _length;
|
||||
private fixed char _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
return new string(bufferPtr, 0, _length);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
_length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString128.");
|
||||
}
|
||||
|
||||
_length = (ushort)value.Length;
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
fixed (char* valuePtr = value)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, valuePtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString128(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString128(ReadOnlySpan<char> input)
|
||||
{
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString128.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, inputPtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString128(char* input, ushort length)
|
||||
: this(new ReadOnlySpan<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Span<byte> AsSpan()
|
||||
{
|
||||
fixed (char* ptr = _buffer)
|
||||
{
|
||||
return new(ptr, _length);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly char* GetUnsafePtr()
|
||||
{
|
||||
return (char*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a stack allocated fixed-size UTF-8 encoded string of length 256 bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 256 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString256"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 256)]
|
||||
public unsafe struct FixedString256
|
||||
{
|
||||
public const int MAX_LENGTH = 127;
|
||||
|
||||
private ushort _length;
|
||||
private fixed char _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
return new string(bufferPtr, 0, _length);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
_length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString256.");
|
||||
}
|
||||
|
||||
_length = (ushort)value.Length;
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
fixed (char* valuePtr = value)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, valuePtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString256(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString256(ReadOnlySpan<char> input)
|
||||
{
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString256.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, inputPtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString256(char* input, ushort length)
|
||||
: this(new ReadOnlySpan<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Span<byte> AsSpan()
|
||||
{
|
||||
fixed (char* ptr = _buffer)
|
||||
{
|
||||
return new(ptr, _length);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly char* GetUnsafePtr()
|
||||
{
|
||||
return (char*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a stack allocated fixed-size UTF-8 encoded string of length 512 bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 512 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString512"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 512)]
|
||||
public unsafe struct FixedString512
|
||||
{
|
||||
public const int MAX_LENGTH = 255;
|
||||
|
||||
private ushort _length;
|
||||
private fixed char _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
return new string(bufferPtr, 0, _length);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
_length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString512.");
|
||||
}
|
||||
|
||||
_length = (ushort)value.Length;
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
fixed (char* valuePtr = value)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, valuePtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString512(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString512(ReadOnlySpan<char> input)
|
||||
{
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString512.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, inputPtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString512(char* input, ushort length)
|
||||
: this(new ReadOnlySpan<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Span<byte> AsSpan()
|
||||
{
|
||||
fixed (char* ptr = _buffer)
|
||||
{
|
||||
return new(ptr, _length);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly char* GetUnsafePtr()
|
||||
{
|
||||
return (char*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a stack allocated fixed-size UTF-8 encoded string of length 1024 bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 1024 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString1024"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 1024)]
|
||||
public unsafe struct FixedString1024
|
||||
{
|
||||
public const int MAX_LENGTH = 511;
|
||||
|
||||
private ushort _length;
|
||||
private fixed char _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
return new string(bufferPtr, 0, _length);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
_length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString1024.");
|
||||
}
|
||||
|
||||
_length = (ushort)value.Length;
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
fixed (char* valuePtr = value)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, valuePtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString1024(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString1024(ReadOnlySpan<char> input)
|
||||
{
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString1024.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, inputPtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString1024(char* input, ushort length)
|
||||
: this(new ReadOnlySpan<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Span<byte> AsSpan()
|
||||
{
|
||||
fixed (char* ptr = _buffer)
|
||||
{
|
||||
return new(ptr, _length);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly char* GetUnsafePtr()
|
||||
{
|
||||
return (char*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a stack allocated fixed-size UTF-8 encoded string of length 2048 bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 2048 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString2048"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 2048)]
|
||||
public unsafe struct FixedString2048
|
||||
{
|
||||
public const int MAX_LENGTH = 1023;
|
||||
|
||||
private ushort _length;
|
||||
private fixed char _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
return new string(bufferPtr, 0, _length);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
_length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString2048.");
|
||||
}
|
||||
|
||||
_length = (ushort)value.Length;
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
fixed (char* valuePtr = value)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, valuePtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString2048(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString2048(ReadOnlySpan<char> input)
|
||||
{
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString2048.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, inputPtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString2048(char* input, ushort length)
|
||||
: this(new ReadOnlySpan<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Span<byte> AsSpan()
|
||||
{
|
||||
fixed (char* ptr = _buffer)
|
||||
{
|
||||
return new(ptr, _length);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly char* GetUnsafePtr()
|
||||
{
|
||||
return (char*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a stack allocated fixed-size UTF-8 encoded string of length 4096 bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length 4096 bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString4096"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = 4096)]
|
||||
public unsafe struct FixedString4096
|
||||
{
|
||||
public const int MAX_LENGTH = 2047;
|
||||
|
||||
private ushort _length;
|
||||
private fixed char _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
return new string(bufferPtr, 0, _length);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
_length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString4096.");
|
||||
}
|
||||
|
||||
_length = (ushort)value.Length;
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
fixed (char* valuePtr = value)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, valuePtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString4096(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString4096(ReadOnlySpan<char> input)
|
||||
{
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString4096.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, inputPtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString4096(char* input, ushort length)
|
||||
: this(new ReadOnlySpan<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Span<byte> AsSpan()
|
||||
{
|
||||
fixed (char* ptr = _buffer)
|
||||
{
|
||||
return new(ptr, _length);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly char* GetUnsafePtr()
|
||||
{
|
||||
return (char*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
108
Misaki.HighPerformance.LowLevel/Collections/FixedString.tt
Normal file
108
Misaki.HighPerformance.LowLevel/Collections/FixedString.tt
Normal file
@@ -0,0 +1,108 @@
|
||||
<#@ template debug="false" hostspecific="false" language="C#" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ import namespace="System.Linq" #>
|
||||
<#@ import namespace="System.Text" #>
|
||||
<#@ import namespace="System.Collections.Generic" #>
|
||||
<#@ output extension=".gen.cs" #>
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Misaki.HighPerformance.LowLevel.Collections;
|
||||
|
||||
<# for (int i = 32; i <= 4096; i *= 2) { #>
|
||||
/// <summary>
|
||||
/// Represents a stack allocated fixed-size UTF-8 encoded string of length <#= i #> bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This struct is designed to hold data on the stack. Every copy of this struct causes a copy of the underlying data.
|
||||
/// If you need a heap allocated fixed-size UTF-8 encoded string of length <#= i #> bytes, consider using <see cref="Misaki.HighPerformance.Unsafe.Buffer.FixedString<#= i #>"/>.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential, Size = <#= i #>)]
|
||||
public unsafe struct FixedString<#= i #>
|
||||
{
|
||||
public const int MAX_LENGTH = <#= (i - 2) / 2 #>;
|
||||
|
||||
private ushort _length;
|
||||
private fixed char _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
return new string(bufferPtr, 0, _length);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
_length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedString<#= i #>.");
|
||||
}
|
||||
|
||||
_length = (ushort)value.Length;
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
fixed (char* valuePtr = value)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, valuePtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString<#= i #>(string input)
|
||||
: this(input.AsSpan())
|
||||
{
|
||||
}
|
||||
|
||||
public FixedString<#= i #>(ReadOnlySpan<char> input)
|
||||
{
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedString<#= i #>.");
|
||||
}
|
||||
|
||||
_length = (ushort)input.Length;
|
||||
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (char* bufferPtr = _buffer)
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(bufferPtr, inputPtr, (uint)(_length * sizeof(char)));
|
||||
}
|
||||
}
|
||||
|
||||
public FixedString<#= i #>(char* input, ushort length)
|
||||
: this(new ReadOnlySpan<char>(input, length))
|
||||
{
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Span<byte> AsSpan()
|
||||
{
|
||||
fixed (char* ptr = _buffer)
|
||||
{
|
||||
return new(ptr, _length);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly char* GetUnsafePtr()
|
||||
{
|
||||
return (char*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
<# } #>
|
||||
@@ -14,8 +14,10 @@ namespace Misaki.HighPerformance.LowLevel.Collections;
|
||||
[StructLayout(LayoutKind.Sequential, Size = 32)]
|
||||
public unsafe struct FixedText32
|
||||
{
|
||||
public const int MAX_LENGTH = 30;
|
||||
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[30];
|
||||
private fixed byte _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
@@ -36,14 +38,14 @@ public unsafe struct FixedText32
|
||||
}
|
||||
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 30)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText32.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, 30));
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, MAX_LENGTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,7 +53,7 @@ public unsafe struct FixedText32
|
||||
public FixedText32(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 30)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText32.");
|
||||
}
|
||||
@@ -59,7 +61,7 @@ public unsafe struct FixedText32
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, 30);
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, MAX_LENGTH);
|
||||
_length = (ushort)actualByteCount;
|
||||
}
|
||||
}
|
||||
@@ -76,7 +78,7 @@ public unsafe struct FixedText32
|
||||
|
||||
public FixedText32(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 30)
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText32.");
|
||||
}
|
||||
@@ -105,12 +107,9 @@ public unsafe struct FixedText32
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte* GetUnsafePointer()
|
||||
public readonly byte* GetUnsafePtr()
|
||||
{
|
||||
fixed (byte* ptr = _buffer)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
return (byte*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -129,8 +128,10 @@ public unsafe struct FixedText32
|
||||
[StructLayout(LayoutKind.Sequential, Size = 64)]
|
||||
public unsafe struct FixedText64
|
||||
{
|
||||
public const int MAX_LENGTH = 62;
|
||||
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[62];
|
||||
private fixed byte _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
@@ -151,14 +152,14 @@ public unsafe struct FixedText64
|
||||
}
|
||||
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 62)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText64.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, 62));
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, MAX_LENGTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,7 +167,7 @@ public unsafe struct FixedText64
|
||||
public FixedText64(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 62)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText64.");
|
||||
}
|
||||
@@ -174,7 +175,7 @@ public unsafe struct FixedText64
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, 62);
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, MAX_LENGTH);
|
||||
_length = (ushort)actualByteCount;
|
||||
}
|
||||
}
|
||||
@@ -191,7 +192,7 @@ public unsafe struct FixedText64
|
||||
|
||||
public FixedText64(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 62)
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText64.");
|
||||
}
|
||||
@@ -220,12 +221,9 @@ public unsafe struct FixedText64
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte* GetUnsafePointer()
|
||||
public readonly byte* GetUnsafePtr()
|
||||
{
|
||||
fixed (byte* ptr = _buffer)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
return (byte*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -244,8 +242,10 @@ public unsafe struct FixedText64
|
||||
[StructLayout(LayoutKind.Sequential, Size = 128)]
|
||||
public unsafe struct FixedText128
|
||||
{
|
||||
public const int MAX_LENGTH = 126;
|
||||
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[126];
|
||||
private fixed byte _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
@@ -266,14 +266,14 @@ public unsafe struct FixedText128
|
||||
}
|
||||
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 126)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText128.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, 126));
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, MAX_LENGTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,7 +281,7 @@ public unsafe struct FixedText128
|
||||
public FixedText128(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 126)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText128.");
|
||||
}
|
||||
@@ -289,7 +289,7 @@ public unsafe struct FixedText128
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, 126);
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, MAX_LENGTH);
|
||||
_length = (ushort)actualByteCount;
|
||||
}
|
||||
}
|
||||
@@ -306,7 +306,7 @@ public unsafe struct FixedText128
|
||||
|
||||
public FixedText128(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 126)
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText128.");
|
||||
}
|
||||
@@ -335,12 +335,9 @@ public unsafe struct FixedText128
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte* GetUnsafePointer()
|
||||
public readonly byte* GetUnsafePtr()
|
||||
{
|
||||
fixed (byte* ptr = _buffer)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
return (byte*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -359,8 +356,10 @@ public unsafe struct FixedText128
|
||||
[StructLayout(LayoutKind.Sequential, Size = 256)]
|
||||
public unsafe struct FixedText256
|
||||
{
|
||||
public const int MAX_LENGTH = 254;
|
||||
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[254];
|
||||
private fixed byte _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
@@ -381,14 +380,14 @@ public unsafe struct FixedText256
|
||||
}
|
||||
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 254)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText256.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, 254));
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, MAX_LENGTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,7 +395,7 @@ public unsafe struct FixedText256
|
||||
public FixedText256(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 254)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText256.");
|
||||
}
|
||||
@@ -404,7 +403,7 @@ public unsafe struct FixedText256
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, 254);
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, MAX_LENGTH);
|
||||
_length = (ushort)actualByteCount;
|
||||
}
|
||||
}
|
||||
@@ -421,7 +420,7 @@ public unsafe struct FixedText256
|
||||
|
||||
public FixedText256(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 254)
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText256.");
|
||||
}
|
||||
@@ -450,12 +449,9 @@ public unsafe struct FixedText256
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte* GetUnsafePointer()
|
||||
public readonly byte* GetUnsafePtr()
|
||||
{
|
||||
fixed (byte* ptr = _buffer)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
return (byte*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -474,8 +470,10 @@ public unsafe struct FixedText256
|
||||
[StructLayout(LayoutKind.Sequential, Size = 512)]
|
||||
public unsafe struct FixedText512
|
||||
{
|
||||
public const int MAX_LENGTH = 510;
|
||||
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[510];
|
||||
private fixed byte _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
@@ -496,14 +494,14 @@ public unsafe struct FixedText512
|
||||
}
|
||||
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 510)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText512.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, 510));
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, MAX_LENGTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -511,7 +509,7 @@ public unsafe struct FixedText512
|
||||
public FixedText512(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 510)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText512.");
|
||||
}
|
||||
@@ -519,7 +517,7 @@ public unsafe struct FixedText512
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, 510);
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, MAX_LENGTH);
|
||||
_length = (ushort)actualByteCount;
|
||||
}
|
||||
}
|
||||
@@ -536,7 +534,7 @@ public unsafe struct FixedText512
|
||||
|
||||
public FixedText512(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 510)
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText512.");
|
||||
}
|
||||
@@ -565,12 +563,9 @@ public unsafe struct FixedText512
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte* GetUnsafePointer()
|
||||
public readonly byte* GetUnsafePtr()
|
||||
{
|
||||
fixed (byte* ptr = _buffer)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
return (byte*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -589,8 +584,10 @@ public unsafe struct FixedText512
|
||||
[StructLayout(LayoutKind.Sequential, Size = 1024)]
|
||||
public unsafe struct FixedText1024
|
||||
{
|
||||
public const int MAX_LENGTH = 1022;
|
||||
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[1022];
|
||||
private fixed byte _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
@@ -611,14 +608,14 @@ public unsafe struct FixedText1024
|
||||
}
|
||||
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 1022)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText1024.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, 1022));
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, MAX_LENGTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -626,7 +623,7 @@ public unsafe struct FixedText1024
|
||||
public FixedText1024(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 1022)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText1024.");
|
||||
}
|
||||
@@ -634,7 +631,7 @@ public unsafe struct FixedText1024
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, 1022);
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, MAX_LENGTH);
|
||||
_length = (ushort)actualByteCount;
|
||||
}
|
||||
}
|
||||
@@ -651,7 +648,7 @@ public unsafe struct FixedText1024
|
||||
|
||||
public FixedText1024(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 1022)
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText1024.");
|
||||
}
|
||||
@@ -680,12 +677,9 @@ public unsafe struct FixedText1024
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte* GetUnsafePointer()
|
||||
public readonly byte* GetUnsafePtr()
|
||||
{
|
||||
fixed (byte* ptr = _buffer)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
return (byte*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -704,8 +698,10 @@ public unsafe struct FixedText1024
|
||||
[StructLayout(LayoutKind.Sequential, Size = 2048)]
|
||||
public unsafe struct FixedText2048
|
||||
{
|
||||
public const int MAX_LENGTH = 2046;
|
||||
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[2046];
|
||||
private fixed byte _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
@@ -726,14 +722,14 @@ public unsafe struct FixedText2048
|
||||
}
|
||||
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 2046)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText2048.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, 2046));
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, MAX_LENGTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -741,7 +737,7 @@ public unsafe struct FixedText2048
|
||||
public FixedText2048(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 2046)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText2048.");
|
||||
}
|
||||
@@ -749,7 +745,7 @@ public unsafe struct FixedText2048
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, 2046);
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, MAX_LENGTH);
|
||||
_length = (ushort)actualByteCount;
|
||||
}
|
||||
}
|
||||
@@ -766,7 +762,7 @@ public unsafe struct FixedText2048
|
||||
|
||||
public FixedText2048(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 2046)
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText2048.");
|
||||
}
|
||||
@@ -795,12 +791,9 @@ public unsafe struct FixedText2048
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte* GetUnsafePointer()
|
||||
public readonly byte* GetUnsafePtr()
|
||||
{
|
||||
fixed (byte* ptr = _buffer)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
return (byte*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -819,8 +812,10 @@ public unsafe struct FixedText2048
|
||||
[StructLayout(LayoutKind.Sequential, Size = 4096)]
|
||||
public unsafe struct FixedText4096
|
||||
{
|
||||
public const int MAX_LENGTH = 4094;
|
||||
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[4094];
|
||||
private fixed byte _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
@@ -841,14 +836,14 @@ public unsafe struct FixedText4096
|
||||
}
|
||||
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > 4094)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText4096.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, 4094));
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, MAX_LENGTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -856,7 +851,7 @@ public unsafe struct FixedText4096
|
||||
public FixedText4096(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > 4094)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText4096.");
|
||||
}
|
||||
@@ -864,7 +859,7 @@ public unsafe struct FixedText4096
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, 4094);
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, MAX_LENGTH);
|
||||
_length = (ushort)actualByteCount;
|
||||
}
|
||||
}
|
||||
@@ -881,7 +876,7 @@ public unsafe struct FixedText4096
|
||||
|
||||
public FixedText4096(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > 4094)
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText4096.");
|
||||
}
|
||||
@@ -910,12 +905,9 @@ public unsafe struct FixedText4096
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte* GetUnsafePointer()
|
||||
public readonly byte* GetUnsafePtr()
|
||||
{
|
||||
fixed (byte* ptr = _buffer)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
return (byte*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
||||
@@ -21,8 +21,10 @@ namespace Misaki.HighPerformance.LowLevel.Collections;
|
||||
[StructLayout(LayoutKind.Sequential, Size = <#= i #>)]
|
||||
public unsafe struct FixedText<#= i #>
|
||||
{
|
||||
public const int MAX_LENGTH = <#= i - 2 #>;
|
||||
|
||||
private ushort _length;
|
||||
private fixed byte _buffer[<#= i - 2 #>];
|
||||
private fixed byte _buffer[MAX_LENGTH];
|
||||
|
||||
public readonly ushort Length => _length;
|
||||
public string Value
|
||||
@@ -43,14 +45,14 @@ public unsafe struct FixedText<#= i #>
|
||||
}
|
||||
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(value);
|
||||
if (maxBytes > <#= i - 2 #>)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText<#= i #>.");
|
||||
}
|
||||
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, <#= i - 2 #>));
|
||||
_length = (ushort)Encoding.UTF8.GetBytes(value, new Span<byte>(bufferPtr, MAX_LENGTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,7 +60,7 @@ public unsafe struct FixedText<#= i #>
|
||||
public FixedText<#= i #>(ReadOnlySpan<char> input)
|
||||
{
|
||||
var maxBytes = Encoding.UTF8.GetByteCount(input);
|
||||
if (maxBytes > <#= i - 2 #>)
|
||||
if (maxBytes > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input string is too long to fit in FixedText<#= i #>.");
|
||||
}
|
||||
@@ -66,7 +68,7 @@ public unsafe struct FixedText<#= i #>
|
||||
fixed (char* inputPtr = input)
|
||||
fixed (byte* bufferPtr = _buffer)
|
||||
{
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, <#= i - 2 #>);
|
||||
var actualByteCount = Encoding.UTF8.GetBytes(inputPtr, input.Length, bufferPtr, MAX_LENGTH);
|
||||
_length = (ushort)actualByteCount;
|
||||
}
|
||||
}
|
||||
@@ -83,7 +85,7 @@ public unsafe struct FixedText<#= i #>
|
||||
|
||||
public FixedText<#= i #>(ReadOnlySpan<byte> input)
|
||||
{
|
||||
if (input.Length > <#= i - 2 #>)
|
||||
if (input.Length > MAX_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("Input byte array is too long to fit in FixedText<#= i #>.");
|
||||
}
|
||||
@@ -112,12 +114,9 @@ public unsafe struct FixedText<#= i #>
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte* GetUnsafePointer()
|
||||
public readonly byte* GetUnsafePtr()
|
||||
{
|
||||
fixed (byte* ptr = _buffer)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
return (byte*)((ushort*)Unsafe.AsPointer(in this) + 1);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Misaki.HighPerformance.LowLevel.Collections;
|
||||
@@ -50,18 +51,26 @@ public readonly unsafe struct ReadOnlyUnsafeCollection<T> : IEnumerable<T>
|
||||
private readonly T* _buffer;
|
||||
private readonly int _count;
|
||||
|
||||
public readonly int Count => _count;
|
||||
public int Count => _count;
|
||||
|
||||
public readonly T this[int index]
|
||||
public ref readonly T this[int index]
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => UnsafeUtility.ReadArrayElement<T>(_buffer, index);
|
||||
get
|
||||
{
|
||||
CheckIndexBounds(index);
|
||||
return ref UnsafeUtility.ReadArrayElementRef<T>(_buffer, index);
|
||||
}
|
||||
}
|
||||
|
||||
public readonly T this[uint index]
|
||||
public ref readonly T this[uint index]
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => UnsafeUtility.ReadArrayElement<T>(_buffer, index);
|
||||
get
|
||||
{
|
||||
CheckIndexBounds((int)index);
|
||||
return ref UnsafeUtility.ReadArrayElementRef<T>(_buffer, index);
|
||||
}
|
||||
}
|
||||
|
||||
public Enumerator GetEnumerator() => new Enumerator(in this);
|
||||
@@ -74,6 +83,16 @@ public readonly unsafe struct ReadOnlyUnsafeCollection<T> : IEnumerable<T>
|
||||
_count = count;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[Conditional("ENABLE_COLLECTION_CHECKS")]
|
||||
private readonly void CheckIndexBounds(int index)
|
||||
{
|
||||
if (index >= _count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index), "Index is out of range.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a read-only span that represents the valid elements in the underlying buffer.
|
||||
/// </summary>
|
||||
|
||||
@@ -17,7 +17,25 @@ public unsafe struct UnTypedArray : IUnTypedCollection
|
||||
public readonly nuint Size => _size;
|
||||
public readonly nuint Alignment => _alignment;
|
||||
|
||||
public readonly bool IsCreated => _buffer != null && _allocationHandle.pAllocator != null && _memoryHandle.IsValid;
|
||||
public readonly bool IsCreated
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_buffer != null)
|
||||
{
|
||||
if (_allocationHandle.IsValid != null)
|
||||
{
|
||||
return _allocationHandle.IsValid(_allocationHandle.State, _memoryHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an UnsafeArray with a default size of 1 and uses the Persistent allocator.
|
||||
@@ -34,8 +52,13 @@ public unsafe struct UnTypedArray : IUnTypedCollection
|
||||
throw new ArgumentOutOfRangeException(nameof(size), "Count must be greater than zero.");
|
||||
}
|
||||
|
||||
if (handle.Alloc == null)
|
||||
{
|
||||
throw new InvalidOperationException("Target allocation handle does not support allocation.");
|
||||
}
|
||||
|
||||
MemoryHandle memHandle;
|
||||
_buffer = handle.Alloc(_allocationHandle.pAllocator, size, alignment, allocationOption, &memHandle);
|
||||
_buffer = handle.Alloc(_allocationHandle.State, size, alignment, allocationOption, &memHandle);
|
||||
_size = size;
|
||||
_alignment = alignment;
|
||||
|
||||
@@ -87,7 +110,7 @@ public unsafe struct UnTypedArray : IUnTypedCollection
|
||||
}
|
||||
|
||||
MemoryHandle memHandle = _memoryHandle;
|
||||
_buffer = _allocationHandle.Realloc(_allocationHandle.pAllocator, _buffer, _size, newSize, _alignment, option, &memHandle);
|
||||
_buffer = _allocationHandle.Realloc(_allocationHandle.State, _buffer, _size, newSize, _alignment, option, &memHandle);
|
||||
_size = newSize;
|
||||
_memoryHandle = memHandle;
|
||||
}
|
||||
@@ -232,9 +255,9 @@ public unsafe struct UnTypedArray : IUnTypedCollection
|
||||
return;
|
||||
}
|
||||
|
||||
if (_allocationHandle.pAllocator != null)
|
||||
if (_allocationHandle.Free != null)
|
||||
{
|
||||
_allocationHandle.Free(_allocationHandle.pAllocator, _buffer, _memoryHandle);
|
||||
_allocationHandle.Free(_allocationHandle.State, _buffer, _memoryHandle);
|
||||
}
|
||||
|
||||
_buffer = null;
|
||||
|
||||
@@ -102,7 +102,25 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
}
|
||||
}
|
||||
|
||||
public readonly bool IsCreated => _buffer != null && _allocationHandle.pAllocator != null && _memoryHandle.IsValid;
|
||||
public readonly bool IsCreated
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_buffer != null)
|
||||
{
|
||||
if (_allocationHandle.IsValid != null)
|
||||
{
|
||||
return _allocationHandle.IsValid(_allocationHandle.State, _memoryHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Enumerator GetEnumerator() => new((UnsafeArray<T>*)UnsafeUtility.AddressOf(ref this));
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator();
|
||||
@@ -130,8 +148,13 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
throw new ArgumentOutOfRangeException(nameof(count), "Count can not be less than zero.");
|
||||
}
|
||||
|
||||
if (handle.Alloc == null)
|
||||
{
|
||||
throw new InvalidOperationException("Target allocation handle does not support allocation.");
|
||||
}
|
||||
|
||||
MemoryHandle memHandle;
|
||||
var buff = handle.Alloc(handle.pAllocator, (nuint)(count * sizeof(T)), AlignOf<T>(), allocationOption, &memHandle);
|
||||
var buff = handle.Alloc(handle.State, (nuint)(count * sizeof(T)), AlignOf<T>(), allocationOption, &memHandle);
|
||||
|
||||
_buffer = (T*)buff;
|
||||
_memoryHandle = memHandle;
|
||||
@@ -168,6 +191,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[Conditional("ENABLE_COLLECTION_CHECKS")]
|
||||
private readonly void ThrowIfNotCreated()
|
||||
{
|
||||
if (!IsCreated)
|
||||
@@ -202,6 +226,11 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
{
|
||||
ThrowIfNotCreated();
|
||||
|
||||
if (_allocationHandle.Realloc == null)
|
||||
{
|
||||
throw new InvalidOperationException("Target allocation handle does not support reallocation.");
|
||||
}
|
||||
|
||||
if (newSize == Count)
|
||||
{
|
||||
return;
|
||||
@@ -209,7 +238,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
|
||||
MemoryHandle memHandle = _memoryHandle;
|
||||
var elemSize = SizeOf<T>();
|
||||
_buffer = (T*)_allocationHandle.Realloc(_allocationHandle.pAllocator, _buffer, (nuint)Count * elemSize, (nuint)newSize * elemSize, AlignOf<T>(), option, &memHandle);
|
||||
_buffer = (T*)_allocationHandle.Realloc(_allocationHandle.State, _buffer, (nuint)Count * elemSize, (nuint)newSize * elemSize, AlignOf<T>(), option, &memHandle);
|
||||
_memoryHandle = memHandle;
|
||||
_count = newSize;
|
||||
}
|
||||
@@ -273,9 +302,9 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
return;
|
||||
}
|
||||
|
||||
if (_allocationHandle.pAllocator != null)
|
||||
if (_allocationHandle.Free != null)
|
||||
{
|
||||
_allocationHandle.Free(_allocationHandle.pAllocator, _buffer, _memoryHandle);
|
||||
_allocationHandle.Free(_allocationHandle.State, _buffer, _memoryHandle);
|
||||
}
|
||||
|
||||
_buffer = null;
|
||||
|
||||
@@ -55,7 +55,6 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeHashCollection<KeyValu
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
var idx = _helper.Find(key);
|
||||
@@ -98,7 +97,7 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeHashCollection<KeyValu
|
||||
/// <param name="key">The key to add.</param>
|
||||
/// <param name="item">The value to add.</param>
|
||||
/// <returns>True if the key-value pair was added.</returns>
|
||||
public bool TryAdd(TKey key, TValue item)
|
||||
public bool TryAdd(in TKey key, TValue item)
|
||||
{
|
||||
var idx = _helper.TryAdd(key);
|
||||
if (idx != -1)
|
||||
@@ -117,7 +116,7 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeHashCollection<KeyValu
|
||||
/// <param name="key">The key to add.</param>
|
||||
/// <param name="item">The value to add.</param>
|
||||
/// <exception cref="ArgumentException">Thrown if the key was already present.</exception>
|
||||
public void Add(TKey key, TValue item)
|
||||
public void Add(in TKey key, TValue item)
|
||||
{
|
||||
var result = TryAdd(key, item);
|
||||
if (!result)
|
||||
@@ -131,7 +130,7 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeHashCollection<KeyValu
|
||||
/// </summary>
|
||||
/// <param name="item">The value to remove.</param>
|
||||
/// <returns>True if the value was present.</returns>
|
||||
public bool Remove(TKey key)
|
||||
public bool Remove(in TKey key)
|
||||
{
|
||||
return -1 != _helper.TryRemove(key);
|
||||
}
|
||||
@@ -142,17 +141,38 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeHashCollection<KeyValu
|
||||
/// <param name="key">The key to look up.</param>
|
||||
/// <param name="item">Outputs the value associated with the key. Outputs default if the key was not present.</param>
|
||||
/// <returns>True if the key was present.</returns>
|
||||
public bool TryGetValue(TKey key, out TValue item)
|
||||
public bool TryGetValue(in TKey key, out TValue item)
|
||||
{
|
||||
return _helper.TryGetValue(key, out item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the value associated with the specified key, or returns a default value if the key is not found.
|
||||
/// </summary>
|
||||
/// <param name="key">The key whose value to retrieve.</param>
|
||||
/// <param name="defaultValue">The value to return if the specified key does not exist. If not specified, the default value for the type is used.</param>
|
||||
/// <returns>The value associated with the specified key if the key is found; otherwise, the specified default value.</returns>
|
||||
public TValue GetValueOrDefault(in TKey key, TValue defaultValue = default)
|
||||
{
|
||||
if (_helper.TryGetValue<TValue>(key, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public ref TValue GetValueRef(in TKey key, out bool exists)
|
||||
{
|
||||
return ref _helper.GetValueRef<TValue>(key, out exists);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a given key is present in this hash map.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to look up.</param>
|
||||
/// <returns>True if the key was present.</returns>
|
||||
public bool ContainsKey(TKey key)
|
||||
public bool ContainsKey(in TKey key)
|
||||
{
|
||||
return -1 != _helper.Find(key);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user