diff options
Diffstat (limited to 'lib/Utils/src')
-rw-r--r-- | lib/Utils/src/Memory/MemoryUtil.cs | 32 | ||||
-rw-r--r-- | lib/Utils/src/Memory/VnString.cs | 28 |
2 files changed, 48 insertions, 12 deletions
diff --git a/lib/Utils/src/Memory/MemoryUtil.cs b/lib/Utils/src/Memory/MemoryUtil.cs index 1be46e4..c4cbc2f 100644 --- a/lib/Utils/src/Memory/MemoryUtil.cs +++ b/lib/Utils/src/Memory/MemoryUtil.cs @@ -82,6 +82,7 @@ namespace VNLib.Utils.Memory /// </summary> public const int MAX_UNSAFE_POOL_SIZE = 80 * 1024; + //Cache the system page size private static readonly int SystemPageSize = Environment.SystemPageSize; /// <summary> @@ -266,6 +267,12 @@ namespace VNLib.Utils.Memory } } + /* + * Initializing a non-readonly span/memory as of .NET 6.0 is a reference + * reintpretation, essentially a pointer cast, so there is little/no cost + * to implicitely casting to a readonly span/memory types to reduce complexity + */ + /// <summary> /// Initializes a block of memory with zeros /// </summary> @@ -297,7 +304,7 @@ namespace VNLib.Utils.Memory } //Get the size of the structure - int size = Unsafe.SizeOf<T>(); + int size = sizeof(T); //Zero block Unsafe.InitBlock(block, 0, (uint)(size * itemCount)); @@ -310,7 +317,7 @@ namespace VNLib.Utils.Memory /// <param name="block">The pointer to the allocated structure</param> public static void ZeroStruct<T>(IntPtr block) { - //get thes size of the structure + //get thes size of the structure does not have to be primitive type int size = Unsafe.SizeOf<T>(); //Zero block Unsafe.InitBlock(block.ToPointer(), 0, (uint)size); @@ -321,7 +328,7 @@ namespace VNLib.Utils.Memory /// </summary> /// <typeparam name="T">The structure type</typeparam> /// <param name="structPtr">The pointer to the allocated structure</param> - public static void ZeroStruct<T>(void* structPtr) where T: unmanaged + public static void ZeroStruct<T>(void* structPtr) { //get thes size of the structure int size = Unsafe.SizeOf<T>(); @@ -336,10 +343,8 @@ namespace VNLib.Utils.Memory /// <param name="structPtr">The pointer to the allocated structure</param> public static void ZeroStruct<T>(T* structPtr) where T : unmanaged { - //get thes size of the structure - int size = Unsafe.SizeOf<T>(); //Zero block - Unsafe.InitBlock(structPtr, 0, (uint)size); + Unsafe.InitBlock(structPtr, 0, (uint)sizeof(T)); } #endregion @@ -669,8 +674,10 @@ namespace VNLib.Utils.Memory //Pin the array GCHandle arrHandle = GCHandle.Alloc(array, GCHandleType.Pinned); + //Get array base address void* basePtr = (void*)arrHandle.AddrOfPinnedObject(); + //Get element offset void* indexOffet = Unsafe.Add<T>(basePtr, elementOffset); @@ -678,6 +685,19 @@ namespace VNLib.Utils.Memory } /// <summary> + /// Gets a runtime <see cref="MemoryHandle"/> wrapper for the given pointer + /// </summary> + /// <param name="value">The pointer to get the handle for</param> + /// <param name="handle">The optional <see cref="GCHandle"/> to attach</param> + /// <param name="pinnable">An optional <see cref="IPinnable"/> instace to wrap with the handle</param> + /// <returns>The <see cref="MemoryHandle"/> wrapper</returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static MemoryHandle GetMemoryHandleFromPointer(IntPtr value, GCHandle handle = default, IPinnable? pinnable = null) + { + return new MemoryHandle(value.ToPointer(), handle, pinnable); + } + + /// <summary> /// Gets a <see cref="Span{T}"/> from the supplied address /// </summary> /// <typeparam name="T"></typeparam> diff --git a/lib/Utils/src/Memory/VnString.cs b/lib/Utils/src/Memory/VnString.cs index 8bb0bb6..7df6009 100644 --- a/lib/Utils/src/Memory/VnString.cs +++ b/lib/Utils/src/Memory/VnString.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Utils @@ -239,13 +239,16 @@ namespace VNLib.Utils.Memory { throw new IOException("The input stream is not readable"); } + //See if the stream is a vn memory stream if (stream is VnMemoryStream vnms) { //Get the number of characters int numChars = encoding.GetCharCount(vnms.AsSpan()); + //New handle MemoryHandle<char> charBuffer = heap.Alloc<char>(numChars); + try { //Write characters to character buffer @@ -264,8 +267,10 @@ namespace VNLib.Utils.Memory { //Create a new char bufer starting with the buffer size MemoryHandle<char> charBuffer = heap.Alloc<char>(bufferSize); + //Rent a temp binary buffer IMemoryOwner<byte> binBuffer = heap.DirectAlloc<byte>(bufferSize); + try { int length = 0; @@ -273,22 +278,28 @@ namespace VNLib.Utils.Memory { //read async int read = await stream.ReadAsync(binBuffer.Memory); + //guard if (read <= 0) { break; } + //calculate the number of characters int numChars = encoding.GetCharCount(binBuffer.Memory.Span[..read]); + //Guard for overflow if (((ulong)(numChars + length)) >= int.MaxValue) { throw new OverflowException(); } + //Re-alloc buffer charBuffer.ResizeIfSmaller(length + numChars); + //Decode and update position _ = encoding.GetChars(binBuffer.Memory.Span[..read], charBuffer.Span.Slice(length, numChars)); + //Update char count length += numChars; } while (true); @@ -319,6 +330,7 @@ namespace VNLib.Utils.Memory { //Check Check(); + //Check bounds return _stringSequence.Span[index]; } @@ -341,13 +353,16 @@ namespace VNLib.Utils.Memory { //Check Check(); + //Check bounds if (start < 0 || (start + count) >= Length) { throw new ArgumentOutOfRangeException(nameof(count)); } + //get sub-sequence slice for the current string SubSequence<char> sub = _stringSequence.Slice((nuint)start, count); + //Create new string with offsets pointing to same internal referrence return new VnString(sub); } @@ -365,6 +380,7 @@ namespace VNLib.Utils.Memory /// <exception cref="ObjectDisposedException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception> public VnString Substring(int start) => Substring(start, (Length - start)); + public VnString this[Range range] { get @@ -489,16 +505,16 @@ namespace VNLib.Utils.Memory Handle?.Dispose(); } - public static bool operator ==(VnString left, VnString right) => ReferenceEquals(left, null) ? ReferenceEquals(right, null) : left.Equals(right); + public static bool operator ==(VnString left, VnString right) => left is null ? right is not null : left.Equals(right, StringComparison.Ordinal); public static bool operator !=(VnString left, VnString right) => !(left == right); - public static bool operator <(VnString left, VnString right) => ReferenceEquals(left, null) ? !ReferenceEquals(right, null) : left.CompareTo(right) < 0; + public static bool operator <(VnString left, VnString right) => left is null ? right is not null : left.CompareTo(right) < 0; - public static bool operator <=(VnString left, VnString right) => ReferenceEquals(left, null) || left.CompareTo(right) <= 0; + public static bool operator <=(VnString left, VnString right) => left is null || left.CompareTo(right) <= 0; - public static bool operator >(VnString left, VnString right) => !ReferenceEquals(left, null) && left.CompareTo(right) > 0; + public static bool operator >(VnString left, VnString right) => left is not null && left.CompareTo(right) > 0; - public static bool operator >=(VnString left, VnString right) => ReferenceEquals(left, null) ? ReferenceEquals(right, null) : left.CompareTo(right) >= 0; + public static bool operator >=(VnString left, VnString right) => left is null ? right is null : left.CompareTo(right) >= 0; } }
\ No newline at end of file |