/// <summary> /// Creates an entry in the file table with the specified path. /// </summary> /// <param name="path">The complete path of the entry to add.</param> /// <param name="entryType">The type of entry to add.</param> public FileTableEntry CreateEntry(string path, EntryType entryType) { //if (path == @"levels\b30\decals-environment\bitmaps\decal fore symb blue b.bitmap") // Debugger.Break(); // Seperate the path into its different levels. string[] parts = path.Split('\\'); // Locate the corresponsing node for each level of the path. // If a level does not exist, create it. FileTableEntry result = rootEntry; for (int x = 0; x < parts.Length; x++) { EntryType currentType = (x < parts.Length - 1) ? (EntryType.Folder) : entryType; List <FileTableEntry> searchResults = result.GetChildren( new NameFilter(parts[x]), new EntryTypeFilter(currentType)); if (searchResults.Count == 0) { // We didn't find this level of the path, so create the node. // Set it to the proper type if it is the last piece, otherwise it's a folder. result = result.AddChild(parts[x], (x < parts.Length - 1) ? EntryType.Folder : entryType); // Add to the table. AddEntryToTable(result); } else { result = searchResults[0]; } } return(result); }
/// <summary> /// Adds a child entry with the specified name of the specified type. /// </summary> public FileTableEntry AddChild(string name, EntryType type) { // See if the entry already exists in this node's children if (ParentEntry != null) { List <FileTableEntry> entries = GetChildren(new NameFilter(name)); if (entries.Count > 0) { return(entries[0]); } } // Creat the new entry and assign it's values. FileTableEntry newNode = CreateEntry(type); newNode.ParentEntry = this; newNode.Name = name; // If this is the first child of this entry, set the reference. if (ChildEntry == null) { ChildEntry = newNode; } else { // If not, set it up as a sibling to the existing child. ChildEntry.AddSibling(newNode); } return(newNode); }
/// <summary> /// Locates and returns the entry that matches the specified criteria. /// Returns null if no matching entry is found. /// </summary> public FileTableEntry GetEntry(string path, EntryType type) { // If there's no path, return the root. if (path == "") { return(rootEntry); } // Split the string, and make sure that it has parts. string[] parts = path.Split('\\'); if (parts.Length == 0) { return(null); } // Locate the entry. FileTableEntry result = rootEntry; for (int x = 0; x < parts.Length; x++) { List <FileTableEntry> results = result.GetChildren(new NameFilter(parts[x]), new EntryTypeFilter((x < (parts.Length - 1)) ? EntryType.Folder : type)); if (results.Count < 1) { result = null; break; } result = results[0]; } return(result != rootEntry ? result : null); }
protected virtual void WriteData(FileTableEntry entry, byte[] data) { bw.BaseStream.Position = entry.DataOffset; bw.Write(Encoding.ASCII.GetBytes("_BIN")); bw.Write(entry.Offset); bw.Write(data); }
/// <summary> /// Adds a file to the archive. /// </summary> public virtual void AddFile(string filename, byte[] buffer) { // See if the file already exists in the archive if (fileTable.GetEntry(filename, EntryType.File) == null) { uint offset = GetDataDescriptor(fileTable.NextEntryOffset); if (offset != FileTableEntry.NullOffset) { if (offset <= fileTable.NextEntryOffset) { // We have reached the data area of the archive, and will need to move // this entry's data to the end of the file, in order to make room // for more entries in the filetable. FileTableEntry moveMe = fileTable.GetEntry(offset); byte[] data = ReadFile(moveMe); moveMe.DataOffset = (uint)archiveFile.Length; moveMe.Save(bw); WriteData(moveMe, data); } } FileTableEntry entry = fileTable.CreateEntry(filename, EntryType.File); AddFile(entry, buffer); } }
public void RemoveEntry(string path, EntryType type) { FileTableEntry entry = GetEntry(path, type); FileTableEntry parent = entry.ParentEntry; FileTableEntry previousSibling = entry.PreviousSiblingEntry; FileTableEntry sibling = entry.SiblingEntry; FileTableEntry child = entry.ChildEntry; if (parent != null) { parent.ChildEntry = entry.FirstSiblingInChain; if (parent.ChildEntry == entry) { parent.ChildEntry = null; } entry.FirstSiblingInChain.ParentEntry = parent; entry.FirstSiblingInChain.Save(diskWriter); parent.Save(diskWriter); } if (previousSibling != null) { previousSibling.SiblingEntry = sibling; previousSibling.Save(diskWriter); } if (sibling != null) { sibling.PreviousSiblingEntry = previousSibling; sibling.Save(diskWriter); } if (child != null) { child.ParentEntry = null; child.Save(diskWriter); } }
protected void AddFile(FileTableEntry entry, byte[] buffer) { entry.DataSize = (uint)buffer.Length; // Set the offset to the end of the file. entry.DataOffset = (uint)archiveFile.Length; entry.Save(bw); WriteData(entry, buffer); }
/// <summary> /// Adds a new sibling to the node. /// </summary> public void AddSibling(FileTableEntry newSibling) { // TODO: Verify that the sibling doesnt already exist. // (Do this the same way that AddChild does) if (SiblingEntry == null) { newSibling.PreviousSiblingEntry = this; SiblingEntry = newSibling; } else { SiblingEntry.AddSibling(newSibling); } }
public virtual string[] GetFolderList(string path) { // Make sure that the path we are looking in exists. FileTableEntry folder = fileTable.GetEntry(path, EntryType.Folder); if (folder == null) { return(new string[0]); } // Get the results. List <FileTableEntry> entries = folder.GetChildren(new EntryTypeFilter(EntryType.Folder)); return(FileTableEntry.EntriesToPaths(entries.ToArray())); }
public virtual byte[] ReadFile(FileTableEntry entry) { if (entry.DataOffset == FileTableEntry.NullOffset) { throw new Exception("No data exists in the archive for entry " + entry.FullPath); } if (GetDataDescriptor(entry.DataOffset) != entry.Offset) { throw new Exception("Error reading data element for entry " + entry.FullPath); } br.BaseStream.Position = entry.DataOffset + 8; byte[] data = br.ReadBytes((int)entry.DataSize); return(data); }
/// <summary> /// Writes the entry and all child entries to disk. /// </summary> protected void WriteEntries(FileTableEntry startEntry) { // Get a recursive list of all of the child folders that exist beneath this node. List <FileTableEntry> folderEntries = startEntry.GetChildren(true, new EntryTypeFilter(EntryType.Folder)); foreach (FileTableEntry folderEntry in folderEntries) { // Write the folder entry. folderEntry.Save(diskWriter); // Write all of the direct child file entry nodes. foreach (FileTableEntry fileEntry in folderEntry.GetChildren(new EntryTypeFilter(EntryType.File))) { fileEntry.Save(diskWriter); } } }
/// <summary> /// Adds the specified entry to the end of the filetable, and updates the heder values. /// </summary> protected void AddEntryToTable(FileTableEntry entry) { // Set the offset accordingly. entry.Offset = NextEntryOffset; header.FileTableSize += (uint)entry.Size; header.FileEntryCount++; // Update the header and save the entry to disk. WriteHeader(); entry.Save(diskWriter); if (entry.ParentEntry != null) { entry.ParentEntry.Save(diskWriter); } if (entry.PreviousSiblingEntry != null) { entry.PreviousSiblingEntry.Save(diskWriter); } }
/// <summary> /// Returns a list of the entry's children that match the specified criteria. /// Optionally recursive. /// </summary> public List <FileTableEntry> GetChildren(bool recursive, params IEntryFilter[] filters) { List <FileTableEntry> entryList = new List <FileTableEntry>(); FileTableEntry child = ChildEntry; while (child != null) { // Test the entry against all of the supplied filters. bool match = true; foreach (IEntryFilter filter in filters) { if (!filter.Match(child)) { match = false; break; } } // Add to the list of results if it matched every filter. if (match) { entryList.Add(child); } // Test the entry's sibling next. child = child.SiblingEntry; } if (recursive) { // Get all of the items from any subfolders as well. List <FileTableEntry> folderList = GetChildren(new EntryTypeFilter(EntryType.Folder)); foreach (FileTableEntry folder in folderList) { entryList.AddRange(folder.GetChildren(true, filters)); } } return(entryList); }
/// <summary> /// Loads an entry, and all of it's referenced entries. /// </summary> protected void Load(BinaryReader reader, uint offset, FileTableEntry parentEntry, FileTableEntry previousSiblingEntry) { if (offset != NullOffset) { reader.BaseStream.Position = offset; entryType = (EntryType)reader.ReadByte(); Offset = offset; DataOffset = reader.ReadUInt32(); DataSize = reader.ReadUInt32(); uint siblingOffset = reader.ReadUInt32(); uint childOffset = reader.ReadUInt32(); ReadExtendedData(reader); Name = reader.ReadString(); if (SiblingOffset < 16 || ChildOffset < 16) { Debugger.Break(); } // Load the referenced entries. ParentEntry = parentEntry; PreviousSiblingEntry = previousSiblingEntry; if (siblingOffset != NullOffset) { SiblingEntry = CreateEntry(EntryType.Folder); SiblingEntry.Load(reader, siblingOffset, parentEntry); } if (childOffset != NullOffset) { ChildEntry = CreateEntry(EntryType.Folder); ChildEntry.Load(reader, childOffset, this); } } }
public void Load(BinaryReader reader, uint offset, FileTableEntry parentEntry) { Load(reader, offset, parentEntry, null); }
public byte[] ReadFile(string filename) { FileTableEntry entry = fileTable.GetEntry(filename, EntryType.File); return(ReadFile(entry)); }
/// <summary> /// Creates the root file entry node. /// Override this method to create a root entry of a different type. /// </summary> protected virtual void CreateRootEntry() { rootEntry = new FileTableEntry(EntryType.Folder); }