@@ -18,7 +18,7 @@ namespace ExtendedSystemObjects.Helper
1818 /// Provides helper methods for allocating, reallocating, and clearing unmanaged memory blocks.
1919 /// Designed for use with value types (unmanaged types) only.
2020 /// </summary>
21- internal static class UnmanagedMemoryHelper
21+ internal static unsafe class UnmanagedMemoryHelper
2222 {
2323 /// <summary>
2424 /// Allocates a block of unmanaged memory large enough to hold the specified number of elements of type
@@ -30,10 +30,20 @@ internal static class UnmanagedMemoryHelper
3030 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
3131 internal static IntPtr Allocate < T > ( int count ) where T : unmanaged
3232 {
33- unsafe
34- {
35- return Marshal . AllocHGlobal ( sizeof ( T ) * count ) ;
36- }
33+ return ( nint ) ( T * ) NativeMemory . Alloc ( ( nuint ) count , ( nuint ) sizeof ( T ) ) ;
34+ }
35+
36+ /// <summary>
37+ /// Allocates a block of zero-initialized unmanaged memory.
38+ /// Equivalent to calloc.
39+ /// </summary>
40+ /// <typeparam name="T">The unmanaged value type to allocate memory for.</typeparam>
41+ /// <param name="count">The number of elements to allocate.</param>
42+ /// <returns>A pointer to the allocated zero-initialized unmanaged memory.</returns>
43+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
44+ internal static T * AllocateZeroed < T > ( int count ) where T : unmanaged
45+ {
46+ return ( T * ) NativeMemory . AllocZeroed ( ( nuint ) count , ( nuint ) sizeof ( T ) ) ;
3747 }
3848
3949 /// <summary>
@@ -45,12 +55,21 @@ internal static IntPtr Allocate<T>(int count) where T : unmanaged
4555 /// <param name="newCount">The new number of elements to accommodate.</param>
4656 /// <returns>A pointer to the newly reallocated unmanaged memory block.</returns>
4757 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
48- internal static IntPtr Reallocate < T > ( IntPtr ptr , int newCount ) where T : unmanaged
58+ internal static T * Reallocate < T > ( T * ptr , int newCount ) where T : unmanaged
4959 {
50- unsafe
51- {
52- return Marshal . ReAllocHGlobal ( ptr , ( IntPtr ) ( sizeof ( T ) * newCount ) ) ;
53- }
60+ // Maps directly to C-style realloc.
61+ return ( T * ) NativeMemory . Realloc ( ptr , ( nuint ) ( sizeof ( T ) * newCount ) ) ;
62+ }
63+
64+ /// <summary>
65+ /// Frees a block of unmanaged memory.
66+ /// </summary>
67+ /// <param name="ptr">The pointer to the unmanaged memory block.</param>
68+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
69+ internal static void Free ( void * ptr )
70+ {
71+ // Standardized free operation.
72+ NativeMemory . Free ( ptr ) ;
5473 }
5574
5675 /// <summary>
@@ -60,13 +79,9 @@ internal static IntPtr Reallocate<T>(IntPtr ptr, int newCount) where T : unmanag
6079 /// <param name="buffer">A pointer to the unmanaged memory block.</param>
6180 /// <param name="count">The number of elements to clear.</param>
6281 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
63- internal static void Clear < T > ( IntPtr buffer , int count ) where T : unmanaged
82+ internal static void Clear < T > ( T * buffer , int count ) where T : unmanaged
6483 {
65- unsafe
66- {
67- Span < T > span = new ( buffer . ToPointer ( ) , count ) ;
68- span . Clear ( ) ; // Equivalent to memset 0
69- }
84+ NativeMemory . Clear ( buffer , ( nuint ) count * ( nuint ) sizeof ( T ) ) ;
7085 }
7186
7287 /// <summary>
@@ -79,21 +94,20 @@ internal static void Clear<T>(IntPtr buffer, int count) where T : unmanaged
7994 /// <param name="length">The length.</param>
8095 /// <param name="capacity">The capacity.</param>
8196 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
82- internal static unsafe void ShiftRight < T > ( T * ptr , int index , int count , int length , int capacity )
83- where T : unmanaged
97+ internal static void ShiftRight < T > ( T * ptr , int index , int count , int length , int capacity ) where T : unmanaged
8498 {
85- var elementsToShift = length - index ;
99+ int elementsToShift = length - index ;
86100 if ( elementsToShift <= 0 || count <= 0 )
87101 {
88102 return ;
89103 }
90104
91- // Start copying from the end to avoid overwriting
105+ // Buffer.MemoryCopy acts like memmove, inherently handling overlapping memory regions safely.
92106 Buffer . MemoryCopy (
93107 ptr + index ,
94108 ptr + index + count ,
95- ( capacity - index - count ) * sizeof ( T ) , // should be fine if debug check passes
96- elementsToShift * sizeof ( T ) ) ;
109+ elementsToShift * ( long ) sizeof ( T ) ,
110+ elementsToShift * ( long ) sizeof ( T ) ) ;
97111 }
98112
99113 /// <summary>
@@ -105,20 +119,18 @@ internal static unsafe void ShiftRight<T>(T* ptr, int index, int count, int leng
105119 /// <param name="count">The count.</param>
106120 /// <param name="length">The length.</param>
107121 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
108- internal static unsafe void ShiftLeft < T > ( T * ptr , int index , int count , int length ) where T : unmanaged
122+ internal static void ShiftLeft < T > ( T * ptr , int index , int count , int length ) where T : unmanaged
109123 {
110- var elementsToShift = length - ( index + count ) ;
124+ int elementsToShift = length - ( index + count ) ;
111125 if ( elementsToShift <= 0 )
112126 {
113127 return ;
114128 }
115129
116- var dstSize = ( length - index ) * sizeof ( T ) ; // full space after index
117-
118130 Buffer . MemoryCopy (
119131 ptr + index + count ,
120132 ptr + index ,
121- dstSize ,
133+ ( length - index ) * sizeof ( T ) ,
122134 elementsToShift * sizeof ( T ) ) ;
123135 }
124136
@@ -127,20 +139,21 @@ internal static unsafe void ShiftLeft<T>(T* ptr, int index, int count, int lengt
127139 /// Similar to memcpy.
128140 /// </summary>
129141 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
130- internal static unsafe void Copy < T > ( T * source , T * destination , int count ) where T : unmanaged
142+ internal static void Copy < T > ( T * source , T * destination , int count ) where T : unmanaged
131143 {
132- Buffer . MemoryCopy ( source , destination , count * sizeof ( T ) , count * sizeof ( T ) ) ;
144+ nuint byteCount = ( nuint ) ( count * sizeof ( T ) ) ;
145+ Buffer . MemoryCopy ( source , destination , byteCount , byteCount ) ;
133146 }
134147
135148 /// <summary>
136149 /// Allocates and clones a block of unmanaged memory from a given source.
137150 /// </summary>
138151 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
139- internal static unsafe IntPtr Clone < T > ( T * source , int count ) where T : unmanaged
152+ internal static T * Clone < T > ( T * source , int count ) where T : unmanaged
140153 {
141- var size = sizeof ( T ) * count ;
142- var dest = Marshal . AllocHGlobal ( size ) ;
143- Buffer . MemoryCopy ( source , dest . ToPointer ( ) , size , size ) ;
154+ nuint byteCount = ( nuint ) ( sizeof ( T ) * count ) ;
155+ T * dest = ( T * ) NativeMemory . Alloc ( byteCount ) ;
156+ Buffer . MemoryCopy ( source , dest , byteCount , byteCount ) ;
144157 return dest ;
145158 }
146159
@@ -149,32 +162,27 @@ internal static unsafe IntPtr Clone<T>(T* source, int count) where T : unmanaged
149162 /// Equivalent to memset with a pattern.
150163 /// </summary>
151164 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
152- internal static unsafe void Fill < T > ( T * ptr , T value , int count ) where T : unmanaged
165+ internal static void Fill < T > ( T * ptr , T value , int count ) where T : unmanaged
153166 {
154- // Generates highly optimized, vectorized machine code natively
155167 new Span < T > ( ptr , count ) . Fill ( value ) ;
156168 }
157169
158170 /// <summary>
159171 /// Searches for the first occurrence of a value in unmanaged memory.
160172 /// </summary>
161173 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
162- internal static unsafe int IndexOf < T > ( T * ptr , T value , int length ) where T : unmanaged, IEquatable < T >
174+ internal static int IndexOf < T > ( T * ptr , T value , int length ) where T : unmanaged, IEquatable < T >
163175 {
164- // Bypasses the manual loop and uses native vectorization
165176 return new ReadOnlySpan < T > ( ptr , length ) . IndexOf ( value ) ;
166177 }
167178
168179 /// <summary>
169180 /// Swaps two elements in unmanaged memory.
170181 /// </summary>
171182 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
172- internal static unsafe void Swap < T > ( T * ptr , int indexA , int indexB ) where T : unmanaged
183+ internal static void Swap < T > ( T * ptr , int indexA , int indexB ) where T : unmanaged
173184 {
174- if ( indexA == indexB )
175- {
176- return ;
177- }
185+ if ( indexA == indexB ) return ;
178186
179187 ( ptr [ indexA ] , ptr [ indexB ] ) = ( ptr [ indexB ] , ptr [ indexA ] ) ;
180188 }
0 commit comments