using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; namespace DisplayMagicianShared { internal static class ExtensionMethods { /// A delegate callback throws an exception. /*public static Type[] Accepts(this Delegate @delegate, int parameterIndex = 0) { Type[] types = null; var parameters = @delegate.GetType().GetMethod("Invoke")?.GetParameters(); if (parameterIndex > 0) { if (parameters?.Length >= parameterIndex) { types = parameters[parameterIndex - 1].GetCustomAttributes(typeof(AcceptsAttribute), true) .Cast() .FirstOrDefault()? .Types; } } if (types == null) { if (parameters != null) { types = parameters.SelectMany(param => param.GetCustomAttributes(typeof(AcceptsAttribute), true)) .Cast() .FirstOrDefault()? .Types; } else { types = @delegate.GetType().GetCustomAttributes(typeof(AcceptsAttribute), false) .Cast() .FirstOrDefault()? .Types; } } return types ?? new Type[0]; }*/ /*public static IEnumerable AllocateAll(this IEnumerable allocatableArray) { foreach ( var allocatable in allocatableArray.Where(item => item.GetType().GetInterfaces().Contains(typeof(IAllocatable)))) { var boxedCopy = (IAllocatable)allocatable; boxedCopy.Allocate(); yield return (T)boxedCopy; } } */ public static TResult BitWiseConvert(T source) where TResult : struct, IConvertible where T : struct, IConvertible { if (typeof(T) == typeof(TResult)) { return (TResult)(object)source; } var sourceSize = Marshal.SizeOf(typeof(T)); var destinationSize = Marshal.SizeOf(typeof(TResult)); var minSize = Math.Min(sourceSize, destinationSize); var sourcePointer = Marshal.AllocHGlobal(sourceSize); Marshal.StructureToPtr(source, sourcePointer, false); var bytes = new byte[destinationSize]; if (BitConverter.IsLittleEndian) { Marshal.Copy(sourcePointer, bytes, 0, minSize); } else { Marshal.Copy(sourcePointer + (sourceSize - minSize), bytes, destinationSize - minSize, minSize); } Marshal.FreeHGlobal(sourcePointer); var destinationPointer = Marshal.AllocHGlobal(destinationSize); Marshal.Copy(bytes, 0, destinationPointer, destinationSize); var destination = (TResult)Marshal.PtrToStructure(destinationPointer, typeof(TResult)); Marshal.FreeHGlobal(destinationPointer); return destination; } /*public static void DisposeAll(this IEnumerable disposableArray) { foreach ( var disposable in disposableArray.Where( item => item.GetType() .GetInterfaces() .Any(i => i == typeof(IDisposable) || i == typeof(IAllocatable)))) { ((IDisposable)disposable).Dispose(); } }*/ public static bool GetBit(this T integer, int index) where T : struct, IConvertible { var bigInteger = BitWiseConvert(integer); var mask = 1ul << index; return (bigInteger & mask) > 0; } public static ulong GetBits(this T integer, int index, int count) where T : struct, IConvertible { var bigInteger = BitWiseConvert(integer); if (index > 0) { bigInteger >>= index; } count = 64 - count; bigInteger <<= count; bigInteger >>= count; return bigInteger; } // ReSharper disable once FunctionComplexityOverflow // ReSharper disable once ExcessiveIndentation /*public static T Instantiate(this Type type) { object instance = default(T); try { if (type.IsValueType) { instance = (T)Activator.CreateInstance(type); } if (type.GetInterfaces().Any(i => i == typeof(IInitializable) || i == typeof(IAllocatable))) { foreach (var field in type.GetRuntimeFields()) { if (field.IsStatic || field.IsLiteral) { continue; } if (field.FieldType == typeof(StructureVersion)) { var version = type.GetCustomAttributes(typeof(StructureVersionAttribute), true) .Cast() .FirstOrDefault()? .VersionNumber; field.SetValue(instance, version.HasValue ? new StructureVersion(version.Value, type) : new StructureVersion()); } else if (field.FieldType.IsArray) { var size = field.GetCustomAttributes(typeof(MarshalAsAttribute), false) .Cast() .FirstOrDefault(attribute => attribute.Value != UnmanagedType.LPArray)? .SizeConst; var arrayType = field.FieldType.GetElementType(); var array = Array.CreateInstance( arrayType ?? throw new InvalidOperationException("Field type is null."), size ?? 0); if (arrayType.IsValueType) { for (var i = 0; i < array.Length; i++) { var obj = arrayType.Instantiate(); array.SetValue(obj, i); } } field.SetValue(instance, array); } else if (field.FieldType == typeof(string)) { var isByVal = field.GetCustomAttributes(typeof(MarshalAsAttribute), false) .Cast() .Any(attribute => attribute.Value == UnmanagedType.ByValTStr); if (isByVal) { field.SetValue(instance, string.Empty); } } else if (field.FieldType.IsValueType) { var isByRef = field.GetCustomAttributes(typeof(MarshalAsAttribute), false) .Cast() .Any(attribute => attribute.Value == UnmanagedType.LPStruct); if (!isByRef) { var value = field.FieldType.Instantiate(); field.SetValue(instance, value); } } } } } catch { // ignored } return (T)instance; }*/ public static T[] Repeat(this T structure, int count) { return Enumerable.Range(0, count).Select(i => structure).ToArray(); } public static T SetBit(this T integer, int index, bool value) where T : struct, IConvertible { var bigInteger = BitWiseConvert(integer); var mask = 1ul << index; var newInteger = value ? bigInteger | mask : bigInteger & ~mask; return BitWiseConvert(newInteger); } // ReSharper disable once TooManyArguments public static T SetBits(this T integer, int index, int count, ulong value) where T : struct, IConvertible { var bigInteger = BitWiseConvert(integer); count = 64 - count; value <<= count; value >>= count - index; bigInteger |= value; return BitWiseConvert(bigInteger); } public static byte[] ToByteArray(this T structure) where T : struct { var size = Marshal.SizeOf(typeof(T)); var array = new byte[size]; var pointer = Marshal.AllocHGlobal(size); try { Marshal.StructureToPtr(structure, pointer, true); Marshal.Copy(pointer, array, 0, size); return array; } finally { Marshal.FreeHGlobal(pointer); } } public static T ToStructure(this byte[] byteArray) where T : struct { var size = Marshal.SizeOf(typeof(T)); var pointer = Marshal.AllocHGlobal(size); try { Marshal.Copy(byteArray, 0, pointer, Math.Min(byteArray.Length, size)); return (T)Marshal.PtrToStructure(pointer, typeof(T)); } finally { Marshal.FreeHGlobal(pointer); } } } }