private static void ValidationChecks <T>(DBHeader header, out uint Build) { var attr = typeof(T).GetCustomAttribute(typeof(DBTableAttribute), false) as DBTableAttribute; if (attr == null) { throw new NotSupportedException("Missing DBTableAttribute."); } if (attr.Build < (int)Expansion.Alpha) { throw new ArgumentException("Invalid Build Number."); } //No header - must be invalid if (!header.IsTypeOf <DBHeader>()) { throw new Exception("Unknown file type."); } if (!header.IsTypeOf <HTFX>() && (header.RecordCount == 0 || header.RecordSize == 0)) { throw new Exception("File contains no records."); } Build = attr.Build; }
private static DBEntry <T> Read <T>(FileStream stream, string dbFile, DBHeader counterpart = null) where T : class { FileName = dbFile; stream.Position = 0; using (var dbReader = new BinaryReader(stream, Encoding.UTF8)) { DBHeader header = ReadHeader(dbReader, counterpart); long pos = dbReader.BaseStream.Position; ValidationChecks <T>(header, out uint build); DBEntry <T> entry = new DBEntry <T>(header, dbFile, build); if (entry.TableStructure == null) { throw new Exception("Definition missing."); } if (header.IsTypeOf <WDBC>() || header.IsTypeOf <WDB2>()) { long stringTableStart = dbReader.BaseStream.Position += header.RecordCount * header.RecordSize; Dictionary <int, string> StringTable = new StringTable().Read(dbReader, stringTableStart); //Get stringtable dbReader.Scrub(pos); ReadIntoTable(ref entry, dbReader, StringTable); //Read data stream.Dispose(); return(entry); } else if (header.IsTypeOf <WDB5>() || header.IsTypeOf <WCH5>() || header.IsTypeOf <WDB6>()) { int CopyTableSize = header.CopyTableSize; //Only WDB5 has a copy table uint CommonDataTableSize = header.CommonDataTableSize; //Only WDB6 has a CommonDataTable //StringTable - only if applicable long copyTablePos = dbReader.BaseStream.Length - CommonDataTableSize - CopyTableSize; long indexTablePos = copyTablePos - (header.HasIndexTable ? header.RecordCount * 4 : 0); long wch7TablePos = indexTablePos - (header.UnknownWCH7 * 4); long stringTableStart = wch7TablePos - header.StringBlockSize; Dictionary <int, string> StringTable = new Dictionary <int, string>(); if (!header.HasOffsetTable) //Stringtable is only present if there isn't an offset map { dbReader.Scrub(stringTableStart); StringTable = new StringTable().Read(dbReader, stringTableStart, stringTableStart + header.StringBlockSize); dbReader.Scrub(pos); } //Read the data using (MemoryStream ms = new MemoryStream(header.ReadData(dbReader, pos, entry.Build))) using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8)) { ReadIntoTable(ref entry, dataReader, StringTable); } //Cleanup header.OffsetLengths = null; stream.Dispose(); return(entry); } else if (header.IsTypeOf <WDB>()) { WDB wdb = (WDB)header; using (MemoryStream ms = new MemoryStream(wdb.ReadData(dbReader))) using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8)) { ReadIntoTable(ref entry, dataReader, new Dictionary <int, string>()); } stream.Dispose(); return(entry); } else if (header.IsTypeOf <HTFX>()) { HTFX htfx = (HTFX)header; using (MemoryStream ms = new MemoryStream(htfx.ReadData(counterpart as WDB6))) using (BinaryReader dataReader = new BinaryReader(ms, Encoding.UTF8)) { ReadIntoTable(ref entry, dataReader, new Dictionary <int, string>()); } stream.Dispose(); return(entry); } else { stream.Dispose(); throw new Exception($"Invalid filetype."); } } }
private static DBHeader ReadHeader(BinaryReader dbReader, DBHeader counterpart = null) { DBHeader header = null; string signature = dbReader.ReadString(4); if (string.IsNullOrWhiteSpace(signature)) { return(null); } if (signature[0] != 'W') { signature = signature.Reverse(); } switch (signature) { case "WDBC": header = new WDBC(); break; case "WDB2": case "WCH2": header = new WDB2(); break; case "WDB5": header = new WDB5(); break; case "WDB6": header = new WDB6(); break; case "WCH5": header = new WCH5(counterpart); break; case "WCH7": header = new WCH7(counterpart); break; case "WCH8": header = new WCH8(counterpart); break; case "WMOB": case "WGOB": case "WQST": case "WIDB": case "WNDB": case "WITX": case "WNPC": case "WPTX": case "WRDN": header = new WDB(); break; case "HTFX": header = new HTFX(); break; } header?.ReadHeader(ref dbReader, signature); return(header); }
public static DBEntry <T> Read <T>(string dbFile, DBHeader counterpart = null) where T : class { return(Read <T>(new FileInfo(dbFile).OpenRead(), dbFile, counterpart)); }