Ejemplo n.º 1
0
        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");
            }
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
 /// <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);
 }
Ejemplo n.º 4
0
        public T Read <T>(ref ulong position)
        {
            uint bytesRead;
            T    ret = (T)LayoutManager.GetLayout <T>().Read(DataSource, position, out bytesRead);

            position += bytesRead;
            return(ret);
        }
Ejemplo n.º 5
0
        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)));
        }
Ejemplo n.º 6
0
 public uint SizeOf <T>()
 {
     return(LayoutManager.GetLayout <T>().Size);
 }
Ejemplo n.º 7
0
 public T Read <T>(ulong position)
 {
     return((T)LayoutManager.GetLayout <T>().Read(DataSource, position));
 }
Ejemplo n.º 8
0
        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);
        }