aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Device/SizeCalculator.cs
blob: 7409c04185c64827126714457c779251b1e78f7b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System;
using System.Reflection;

namespace Ryujinx.Graphics.Device
{
    public static class SizeCalculator
    {
        public static int SizeOf(Type type)
        {
            // Is type a enum type?
            if (type.IsEnum)
            {
                type = type.GetEnumUnderlyingType();
            }

            // Is type a pointer type?
            if (type.IsPointer || type == typeof(IntPtr) || type == typeof(UIntPtr))
            {
                return IntPtr.Size;
            }

            // Is type a struct type?
            if (type.IsValueType && !type.IsPrimitive)
            {
                // Check if the struct has a explicit size, if so, return that.
                if (type.StructLayoutAttribute.Size != 0)
                {
                    return type.StructLayoutAttribute.Size;
                }

                // Otherwise we calculate the sum of the sizes of all fields.
                int size = 0;
                var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

                for (int fieldIndex = 0; fieldIndex < fields.Length; fieldIndex++)
                {
                    size += SizeOf(fields[fieldIndex].FieldType);
                }

                return size;
            }

            // Primitive types.
            return (Type.GetTypeCode(type)) switch
            {
                TypeCode.SByte => sizeof(sbyte),
                TypeCode.Byte => sizeof(byte),
                TypeCode.Int16 => sizeof(short),
                TypeCode.UInt16 => sizeof(ushort),
                TypeCode.Int32 => sizeof(int),
                TypeCode.UInt32 => sizeof(uint),
                TypeCode.Int64 => sizeof(long),
                TypeCode.UInt64 => sizeof(ulong),
                TypeCode.Char => sizeof(char),
                TypeCode.Single => sizeof(float),
                TypeCode.Double => sizeof(double),
                TypeCode.Decimal => sizeof(decimal),
                TypeCode.Boolean => sizeof(bool),
                _ => throw new ArgumentException($"Length for type \"{type.Name}\" is unknown.")
            };
        }
    }
}