using System; using System.IO; namespace Lucidiot.Magellan { public static class MapArchive { public static MapArchiveEntry[] ReadHeader(string path) { if (!File.Exists(path)) throw new FileNotFoundException("Archive file not found.", path); using (FileStream stream = File.Open(path, FileMode.Open)) { return ReadHeader(stream); } } public static MapArchiveEntry[] ReadHeader(Stream stream) { if (!stream.CanSeek) throw new ArgumentException("Reading capability is required on the stream in order to read the header.", "stream"); using (BinaryReader br = new BinaryReader(stream)) { return ReadHeader(br); } } public static MapArchiveEntry[] ReadHeader(BinaryReader br) { uint length1 = br.ReadUInt32(); uint length2 = br.ReadUInt32(); if (length1 != length2) throw new NotSupportedException("Unexpected header: Two different entry counts found."); MapArchiveEntry[] entries = new MapArchiveEntry[length1]; for (int i = 0; i < length1; i++) { entries[i] = MapArchiveEntry.Parse(br); } return entries; } public static void ExtractAll(string path, string destination) { if (!File.Exists(path)) throw new FileNotFoundException("MGI file not found.", path); if (!Directory.Exists(destination)) throw new DirectoryNotFoundException("Destination path is not a valid directory."); using (FileStream stream = File.Open(path, FileMode.Open)) { ExtractAll(stream, destination); } } public static void ExtractAll(Stream stream, string destination) { if (!stream.CanSeek) throw new ArgumentException("Seeking capability is required on the stream in order to extract.", "stream"); if (!stream.CanRead) throw new ArgumentException("Reading capability is required on the stream in order to extract.", "stream"); using (BinaryReader br = new BinaryReader(stream)) { ExtractAll(br, destination); } } public static void ExtractAll(BinaryReader br, string destination) { if (!br.BaseStream.CanSeek) throw new ArgumentException("Seeking capability is required on the stream reader in order to extract.", "br"); ExtractAll(br, ReadHeader(br), destination); } public static void ExtractAll(string path, MapArchiveEntry[] entries, string destination) { if (!File.Exists(path)) throw new FileNotFoundException("Archive file not found.", path); if (!Directory.Exists(destination)) throw new DirectoryNotFoundException("Destination path is not a valid directory."); using (FileStream stream = File.Open(path, FileMode.Open)) { ExtractAll(stream, entries, destination); } } public static void ExtractAll(Stream stream, MapArchiveEntry[] entries, string destination) { if (!stream.CanSeek) throw new ArgumentException("Seeking capability is required on the stream in order to extract.", "stream"); if (!stream.CanRead) throw new ArgumentException("Reading capability is required on the stream in order to extract.", "stream"); using (BinaryReader br = new BinaryReader(stream)) { ExtractAll(br, entries, destination); } } public static void ExtractAll(BinaryReader br, MapArchiveEntry[] entries, string destination) { if (!br.BaseStream.CanSeek) throw new ArgumentException("Seeking capability is required on the stream reader in order to extract.", "br"); if (!br.BaseStream.CanRead) throw new ArgumentException("Reading capability is required on the stream reader in order to extract.", "br"); foreach (MapArchiveEntry entry in entries) { string path = Path.Combine(destination, entry.FullName.Replace('\0', '_')); entry.Extract(br, path); } } } }