using System; using System.Runtime.InteropServices; using System.Text; using System.Collections.Generic; namespace Facepunch.Steamworks { internal static class Helpers { public const int MemoryBufferSize = 1024 * 32; [ThreadStatic] private static IntPtr[] MemoryPool; [ThreadStatic] private static int MemoryPoolIndex; public static unsafe IntPtr TakeMemory() { if ( MemoryPool == null ) { // // The pool has 4 items. This should be safe because we shouldn't really // ever be using more than 2 memory pools // MemoryPool = new IntPtr[4]; for ( int i = 0; i < MemoryPool.Length; i++ ) MemoryPool[i] = Marshal.AllocHGlobal( MemoryBufferSize ); } MemoryPoolIndex++; if ( MemoryPoolIndex >= MemoryPool.Length ) MemoryPoolIndex = 0; var take = MemoryPool[MemoryPoolIndex]; ((byte*)take)[0] = 0; return take; } [ThreadStatic] private static byte[][] BufferPool; [ThreadStatic] private static int BufferPoolIndex; /// /// Returns a buffer. This will get returned and reused later on. /// We shouldn't really be using this anymore. /// public static byte[] TakeBuffer( int minSize ) { if ( BufferPool == null ) { // // The pool has 4 items. // BufferPool = new byte[4][]; for ( int i = 0; i < BufferPool.Length; i++ ) BufferPool[i] = new byte[ 1024 * 128 ]; } BufferPoolIndex++; if ( BufferPoolIndex >= BufferPool.Length ) BufferPoolIndex = 0; if ( BufferPool[BufferPoolIndex].Length < minSize ) { BufferPool[BufferPoolIndex] = new byte[minSize + 1024]; } return BufferPool[BufferPoolIndex]; } internal unsafe static string MemoryToString( IntPtr ptr ) { var len = 0; for( len = 0; len < MemoryBufferSize; len++ ) { if ( ((byte*)ptr)[len] == 0 ) break; } if ( len == 0 ) return string.Empty; return UTF8Encoding.UTF8.GetString( (byte*)ptr, len ); } } internal class MonoPInvokeCallbackAttribute : Attribute { public MonoPInvokeCallbackAttribute() { } } /// /// Prevent unity from stripping shit we depend on /// https://docs.unity3d.com/Manual/ManagedCodeStripping.html /// internal class PreserveAttribute : System.Attribute { } }