예제 #1
0
        private void ValidateEnumType(Type type, Partition.TypeDefinitionEntry typeDefinition)
        {
            var fieldNames = new Dictionary <uint, string>();

            foreach (var fieldInfo in type.GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                var attribute = fieldInfo.GetCustomAttributes(typeof(PartitionEnumMemberAttribute), false)
                                .OfType <PartitionEnumMemberAttribute>()
                                .FirstOrDefault();
                if (attribute == null)
                {
                    continue;
                }
                fieldNames.Add((uint)fieldInfo.GetRawConstantValue(), attribute.MemberName);
            }

            for (int i = typeDefinition.FieldStartIndex, o = 0; o < typeDefinition.FieldCount; i++, o++)
            {
                var    fieldDefinition = this._Partition.FieldDefinitionEntries[i];
                string fieldName;
                if (fieldNames.TryGetValue(fieldDefinition.DataOffset, out fieldName) == false)
                {
                    throw new InvalidOperationException("enum " + type + " does not have a member for " +
                                                        fieldDefinition.DataOffset);
                }
                if (fieldName != fieldDefinition.Name)
                {
                    throw new InvalidOperationException("enum " + type + " does has the wrong member name for " +
                                                        fieldDefinition.DataOffset + " (" + fieldDefinition.Name +
                                                        " vs " + fieldName + ")");
                }
            }
        }
예제 #2
0
        public void Deserialize(Stream input)
        {
            var basePosition = input.Position;

            var magic = input.ReadValueU32(Endian.Little);

            if (magic != Signature && magic.Swap() != Signature)
            {
                throw new FormatException();
            }
            var endian = magic == Signature ? Endian.Little : Endian.Big;

            var headerSize = input.ReadValueU32(endian);

            if (basePosition + headerSize > input.Length)
            {
                throw new EndOfStreamException();
            }

            var dataSize = input.ReadValueU32(endian);

            if (basePosition + headerSize + dataSize > input.Length)
            {
                throw new EndOfStreamException();
            }

            var importCount           = input.ReadValueU32(endian);
            var instanceCount         = input.ReadValueU16(endian);
            var namedInstanceCount    = input.ReadValueU16(endian);
            var exportedInstanceCount = input.ReadValueU16(endian);
            var typeDefinitionCount   = input.ReadValueU16(endian);
            var fieldDefinitionCount  = input.ReadValueU16(endian);
            var nameTableSize         = input.ReadValueU16(endian);
            var stringTableSize       = input.ReadValueU32(endian);
            var arrayCount            = input.ReadValueU32(endian);
            var arrayOffset           = input.ReadValueU32(endian);
            var guid = input.ReadValueGuid(endian);

            input.Seek(8, SeekOrigin.Current);

            var computedHeaderSize = 64 +
                                     (importCount * 32) +
                                     nameTableSize +
                                     (fieldDefinitionCount * 16) +
                                     (typeDefinitionCount * 16) +
                                     (instanceCount * 4).Align(16) +
                                     (arrayCount * 12).Align(16);

            if (computedHeaderSize != headerSize)
            {
                throw new FormatException();
            }

            var importEntries = new Partition.ImportEntry[importCount];

            for (int i = 0; i < importCount; i++)
            {
                importEntries[i] = Partition.ImportEntry.Read(input, endian);
            }

            var nameTableBytes = input.ReadBytes(nameTableSize);
            var names          = new List <string>();

            using (var data = new MemoryStream(nameTableBytes, false))
            {
                while (data.Position < data.Length)
                {
                    names.Add(data.ReadStringZ(Encoding.UTF8));
                }
            }

            // TODO(gibbed): do this better.
            var hashesToNames = names.Distinct().ToDictionary(Common.Hashing.DJB.Compute, s => s);

            var fieldDefinitionEntries = new Partition.FieldDefinitionEntry[fieldDefinitionCount];

            for (int i = 0; i < fieldDefinitionCount; i++)
            {
                var fieldDefinitionEntry =
                    fieldDefinitionEntries[i] = Partition.FieldDefinitionEntry.Read(input, endian);
                if (fieldDefinitionEntry.Flags.UnknownFlags2 != 0)
                {
                    throw new FormatException();
                }
                fieldDefinitionEntries[i].Name = hashesToNames[fieldDefinitionEntries[i].NameHash];
            }

            var typeDefinitionEntries = new Partition.TypeDefinitionEntry[typeDefinitionCount];

            for (int i = 0; i < typeDefinitionCount; i++)
            {
                var typeDefinitionEntry =
                    typeDefinitionEntries[i] = Partition.TypeDefinitionEntry.Read(input, endian);
                if (typeDefinitionEntry.Flags.UnknownFlags2 != 0)
                {
                    throw new FormatException();
                }
                typeDefinitionEntries[i].Name = hashesToNames[typeDefinitionEntries[i].NameHash];
            }

            var instancePadding = (instanceCount * 4).Padding(16);
            var instanceEntries = new Partition.InstanceEntry[instanceCount];

            for (int i = 0; i < instanceCount; i++)
            {
                instanceEntries[i] = Partition.InstanceEntry.Read(input, endian);
            }
            input.Seek(instancePadding, SeekOrigin.Current);

            var arrayPadding = (arrayCount * 12).Padding(16);
            var arrayEntries = new Partition.ArrayEntry[arrayCount];

            for (int i = 0; i < arrayCount; i++)
            {
                arrayEntries[i] = Partition.ArrayEntry.Read(input, endian);
            }
            input.Seek(arrayPadding, SeekOrigin.Current);

            if (basePosition + headerSize != input.Position)
            {
                throw new FormatException();
            }

            var dataBytes = input.ReadBytes(dataSize);

            this._ImportEntries.Clear();
            this._FieldDefinitionEntries.Clear();
            this._TypeDefinitionEntries.Clear();
            this._InstanceEntries.Clear();
            this._ArrayEntries.Clear();

            this._Endian = endian;
            this._Guid   = guid;
            this._ImportEntries.AddRange(importEntries);
            this._NameTableBytes = nameTableBytes;
            this._FieldDefinitionEntries.AddRange(fieldDefinitionEntries);
            this._TypeDefinitionEntries.AddRange(typeDefinitionEntries);
            this._InstanceEntries.AddRange(instanceEntries);
            this._ArrayEntries.AddRange(arrayEntries);
            this._NamedInstanceCount    = namedInstanceCount;
            this._ExportedInstanceCount = exportedInstanceCount;
            this._StringTableSize       = stringTableSize;
            this._ArrayOffset           = arrayOffset;
            this._DataBytes             = dataBytes;
        }