private static ILayout GetPointerLayout(Type pointerType, LayoutManager layoutManager) { if (!typeof(Pointer).GetTypeInfo().IsAssignableFrom(pointerType)) { return(null); } Type curPointerType = pointerType; TypeInfo genericPointerTypeInfo = null; while (curPointerType != typeof(Pointer)) { TypeInfo curPointerTypeInfo = curPointerType.GetTypeInfo(); if (curPointerTypeInfo.IsGenericType && curPointerTypeInfo.GetGenericTypeDefinition() == typeof(Pointer <,>)) { genericPointerTypeInfo = curPointerTypeInfo; break; } curPointerType = curPointerTypeInfo.BaseType; } if (genericPointerTypeInfo == null) { throw new LayoutException("Pointer types must be derived from Pointer<,,>"); } Type targetType = genericPointerTypeInfo.GetGenericArguments()[0]; Type storageType = genericPointerTypeInfo.GetGenericArguments()[1]; ILayout targetLayout = layoutManager.GetLayout(targetType); ILayout storageLayout = layoutManager.GetLayout(storageType); // Unforetunately the storageLayout.Read returns a boxed object that can't be // casted to a ulong without first being unboxed. These three Pointer layout // types are identical other than unboxing to a different type. Generics // doesn't work, there is no constraint that ensures the type parameter defines // a casting operator to ulong. Specifying a Func<object,ulong> parameter // would work, but I opted to write each class seperately so that we don't // pay the cost of an extra delegate invocation for each pointer read. It // may be premature optimization, but the complexity of it should be relatively // constrained within this file at least. if (storageLayout.Type == typeof(SizeT)) { return(new SizeTPointerLayout(pointerType, storageLayout, targetLayout)); } else if (storageLayout.Type == typeof(ulong)) { return(new UInt64PointerLayout(pointerType, storageLayout, targetLayout)); } else if (storageLayout.Type == typeof(uint)) { return(new UInt32PointerLayout(pointerType, storageLayout, targetLayout)); } else { throw new LayoutException("Pointer types must have a storage type of SizeT, ulong, or uint"); } }
private static ILayout GetFieldLayout(FieldInfo fieldInfo, LayoutManager layoutManager) { ILayout fieldLayout = null; Type fieldType = fieldInfo.FieldType; if (fieldType.IsArray) { ArraySizeAttribute ca = (ArraySizeAttribute)fieldInfo.GetCustomAttributes(typeof(ArraySizeAttribute)).FirstOrDefault(); if (ca == null) { throw new LayoutException("Array typed fields must use an ArraySize attribute to indicate their size"); } fieldLayout = layoutManager.GetArrayLayout(fieldType, ca.NumElements); } else { fieldLayout = layoutManager.GetLayout(fieldType); } if (!fieldLayout.IsFixedSize) { throw new LayoutException(fieldInfo.Name + " is not a fixed size field. Only fixed size fields are supported in structures"); } return(fieldLayout); }
/// <summary> /// Adds support for parsing the SizeT type /// </summary> /// <param name="size">The number of bytes that should be parsed for SizeT, either 4 or 8</param> /// <param name="layouts">The layout manager that will hold the new layout</param> /// <remarks> /// SizeT reuses the existing parsing logic for either uint or ulong depending on size. The ILayoutManager /// is expected to already have the relevant type's layout defined before calling this method. /// </remarks> public static LayoutManager AddSizeT(this LayoutManager layouts, int size) { if (size == 4) { layouts.AddLayout(new UInt32SizeTLayout(layouts.GetLayout <uint>())); } else if (size == 8) { layouts.AddLayout(new UInt64SizeTLayout(layouts.GetLayout <ulong>())); } else { throw new ArgumentException("Size must be 4 or 8"); } return(layouts); }
public T Read <T>(ref ulong position) { uint bytesRead; T ret = (T)LayoutManager.GetLayout <T>().Read(DataSource, position, out bytesRead); position += bytesRead; return(ret); }
private static ILayout GetEnumLayout(Type enumType, LayoutManager layoutManager) { if (!enumType.GetTypeInfo().IsEnum) { return(null); } Type elementType = enumType.GetTypeInfo().GetEnumUnderlyingType(); return(new EnumLayout(enumType, layoutManager.GetLayout(elementType))); }
public uint SizeOf <T>() { return(LayoutManager.GetLayout <T>().Size); }
public T Read <T>(ulong position) { return((T)LayoutManager.GetLayout <T>().Read(DataSource, position)); }
private static ILayout GetTStructLayout(Type tStructType, LayoutManager layoutManager, IEnumerable <string> enabledDefines, Type requiredBaseType) { if (!requiredBaseType.GetTypeInfo().IsAssignableFrom(tStructType)) { return(null); } if (enabledDefines == null) { enabledDefines = Array.Empty <string>(); } TypeInfo typeInfo = tStructType.GetTypeInfo(); PackAttribute pack = typeInfo.GetCustomAttributes().Where(attr => attr is PackAttribute).Cast <PackAttribute>().SingleOrDefault(); FieldInfo[] reflectionFields = typeInfo.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); reflectionFields = reflectionFields.OrderBy(f => f.MetadataToken).ToArray(); reflectionFields = reflectionFields.Where(f => !f.DeclaringType.Equals(typeof(TStruct))).ToArray(); reflectionFields = reflectionFields.Where(f => IsFieldIncludedInDefines(f, enabledDefines)).ToArray(); TField[] tFields = new TField[reflectionFields.Length]; uint alignCeiling = pack?.Pack ?? 8; uint biggestAlignmentSoFar = 1; uint curOffset = 0; ILayout parentLayout = null; Type baseType = tStructType.GetTypeInfo().BaseType; if (!baseType.Equals(typeof(TStruct))) { // Treat base type as first member. parentLayout = layoutManager.GetLayout(baseType); uint align = Math.Min(parentLayout.NaturalAlignment, alignCeiling); biggestAlignmentSoFar = Math.Max(biggestAlignmentSoFar, align); curOffset += parentLayout.SizeAsBaseType; } // build the field list for (int i = 0; i < reflectionFields.Length; i++) { ILayout fieldLayout = GetFieldLayout(reflectionFields[i], layoutManager); uint fieldSize = fieldLayout.Size; uint align = fieldLayout.NaturalAlignment; align = Math.Min(align, alignCeiling); biggestAlignmentSoFar = Math.Max(biggestAlignmentSoFar, align); curOffset = AlignUp(curOffset, align); tFields[i] = new TField(reflectionFields[i], fieldLayout, curOffset); curOffset += fieldSize; } curOffset = AlignUp(curOffset, biggestAlignmentSoFar); uint sizeAsBaseType = curOffset; if (curOffset == 0) { curOffset = 1; // As with C++, zero-length struct not allowed (except as parent of another struct). } IField[] totalFields; if (parentLayout != null) { totalFields = parentLayout.Fields.Concat(tFields).ToArray(); } else { totalFields = tFields; } TLayout layout = new TLayout(tStructType, curOffset, biggestAlignmentSoFar, sizeAsBaseType, totalFields); foreach (TField field in tFields) { field.DeclaringLayout = layout; } return(layout); }