public GameTable(string path) { using (var stream = File.OpenRead(path)) using (var reader = new BinaryReader(stream)) { // header ReadOnlySpan <GameTableHeader> headerSpan = MemoryMarshal.Cast <byte, GameTableHeader>( reader.ReadBytes(Marshal.SizeOf <GameTableHeader>())); header = headerSpan[0]; // fields stream.Position = Marshal.SizeOf <GameTableHeader>() + (int)header.FieldOffset; ReadOnlySpan <GameTableField> fields = MemoryMarshal.Cast <byte, GameTableField>( reader.ReadBytes(Marshal.SizeOf <GameTableField>() * (int)header.FieldCount)); // optimisation to prevent too much CPU time being spent on GetCustomAttribute for large tables var attributeCache = new Dictionary <FieldInfo, GameTableFieldArrayAttribute>(); foreach (FieldInfo modelField in typeof(T).GetFields()) { GameTableFieldArrayAttribute attribute = modelField.GetCustomAttribute <GameTableFieldArrayAttribute>(); attributeCache.Add(modelField, attribute); } ValidateModelFields(fields, attributeCache); ReadEntries(reader, fields, attributeCache); ReadLookupTable(reader); } }
public GameTable(string path) { using (FileStream fileStream = File.OpenRead(path)) using (var stream = new BufferedStream(fileStream, bufferSize)) using (var reader = new BinaryReader(stream)) { if (reader.BaseStream.Remaining() < Marshal.SizeOf <GameTableHeader>()) { throw new InvalidDataException(); } // header ReadOnlySpan <GameTableHeader> headerSpan = MemoryMarshal.Cast <byte, GameTableHeader>(reader.ReadBytes(headerSize)); header = headerSpan[0]; if (header.Signature != 0x4454424C) { throw new InvalidDataException(); } // fields stream.Position = headerSize + (int)header.FieldOffset; ReadOnlySpan <GameTableField> fields = MemoryMarshal.Cast <byte, GameTableField>( reader.ReadBytes(fieldSize * (int)header.FieldCount)); ValidateModelFields(fields); ReadEntries(reader, fields); } }