public SortedList <int, ArchiveFileEntry> GetOrderedFileEntries() { SortedList <int, ArchiveFileEntry> list = new SortedList <int, ArchiveFileEntry>(); foreach (ArchiveEntryBase entry in Childs) { switch (entry.Type) { case ArchiveEntryType.Archive: { ArchiveArchiveEntry archiveEntry = (ArchiveArchiveEntry)entry; list.Add(archiveEntry.MetricsEntry.Index, archiveEntry.MetricsEntry); list.Add(archiveEntry.ListingEntry.Index, archiveEntry.ListingEntry); list.Add(archiveEntry.ContentEntry.Index, archiveEntry.ContentEntry); break; } case ArchiveEntryType.File: { ArchiveFileEntry fileEntry = (ArchiveFileEntry)entry; list.Add(fileEntry.Index, fileEntry); break; } } } return(list); }
public bool IsUncompressed() { foreach (ArchiveEntryBase child in Childs) { if (child.Type == ArchiveEntryType.Archive) { ArchiveArchiveEntry archiveEntry = (ArchiveArchiveEntry)child; if (archiveEntry.MetricsEntry.Compression != Compression.None || archiveEntry.ListingEntry.Compression != Compression.None || archiveEntry.ContentEntry.Compression != Compression.None) { return(false); } } else if (child.Type == ArchiveEntryType.File) { ArchiveFileEntry fileEntry = (ArchiveFileEntry)child; if (fileEntry.Compression != Compression.None) { return(false); } } } return(true); }
private void MoveContent(ArchiveArchiveEntry[] oldArchives, ArchiveArchiveEntry[] newArchives, ArchiveFileEntry[] newMetrics, ArchiveFileEntry[] newListing, ArchiveArchiveEntry newParent, ArchiveDirectoryEntry newDirectory) { for (int i = 0; i < oldArchives.Length; i++) { ArchiveArchiveEntry oldArchive = oldArchives[i]; ArchiveArchiveEntry newArchive = newArchives[i]; ArchiveFileEntry newContent = oldArchive.ContentEntry.Clone(); { newContent.Compression = Compression.None; newContent.ContentOffset = newParent.CurrentPosition; newArchive.ContentEntry = newContent; } newArchive.MetricsEntry = newMetrics[i]; newArchive.ListingEntry = newListing[i]; newArchive.ContentEntry = newContent; foreach (ArchiveFileEntry oldChild in oldArchive.Childs.OfType <ArchiveFileEntry>()) { MoveFile(oldChild, newArchive, newDirectory); } foreach (ArchiveArchiveEntry oldChild in oldArchive.Childs.OfType <ArchiveArchiveEntry>()) { MoveArchive(oldChild, newArchive, newDirectory); } newContent.UncompressedContentSize = newArchive.CurrentPosition; SetCapacity(newContent); newParent.CurrentPosition += newContent.ContentCapacity; } }
private bool TryAddChildArchive(string path, ArchiveFileEntry entry, ArchiveArchiveEntry parentArchive) { Action <ArchiveArchiveEntry, ArchiveFileEntry> valueSetter; switch (Path.GetExtension(entry.Name)) { case ".fs": valueSetter = (a, e) => a.ContentEntry = e; break; case ".fl": valueSetter = (a, e) => a.ListingEntry = e; break; case ".fi": valueSetter = (a, e) => a.MetricsEntry = e; break; default: return(false); } path = Path.ChangeExtension(path, null); ArchiveArchiveEntry archive = _childArchives.GetOrAdd(path, p => new ArchiveArchiveEntry(Path.ChangeExtension(entry.Name, null))); valueSetter(archive, entry); if (archive.IsComplete) { _childArchives.TryRemove(path, out archive); parentArchive.AddEntry(archive); } return(true); }
private void CorrectOffsets(MemoryMappedFile memoryFile, ArchiveArchiveEntry[] sourceArchives, ArchiveArchiveEntry[] targetArchives) { for (int i = 0; i < sourceArchives.Length; i++) { ArchiveArchiveEntry source = sourceArchives[i]; ArchiveArchiveEntry target = targetArchives[i]; if (source.Name != target.Name) { throw new Exception("Порядок элементов в иерархиях изменился."); } using (MemoryMappedViewStream memory = memoryFile.CreateViewStream(source.MetricsEntry.GetAbsoluteOffset(), source.MetricsEntry.UncompressedContentSize)) using (BinaryWriter bw = new BinaryWriter(memory)) { foreach (ArchiveFileEntry file in target.GetOrderedFileEntries().Values) { bw.Write(file.UncompressedContentSize); bw.Write(file.ContentOffset); bw.Write((int)Compression.None); } ArchiveArchiveEntry[] childSourceArrays = source.Childs.OfType <ArchiveArchiveEntry>().ToArray(); ArchiveArchiveEntry[] childTargetArrays = target.Childs.OfType <ArchiveArchiveEntry>().ToArray(); CorrectOffsets(memoryFile, childSourceArrays, childTargetArrays); } } }
private void MoveArchive(ArchiveArchiveEntry sourceArchive, ArchiveArchiveEntry targetArchvie, ArchiveDirectoryEntry rootDirectory) { ArchiveArchiveEntry[] oldChildArchives = sourceArchive.Childs.OfType <ArchiveArchiveEntry>().ToArray(); ArchiveArchiveEntry[] archiveEntries = MoveArchive(oldChildArchives, targetArchvie); ArchiveFileEntry[] metricsEntries = MoveMetrics(oldChildArchives, archiveEntries, targetArchvie); ArchiveFileEntry[] listingEntries = MoveListing(oldChildArchives, archiveEntries, targetArchvie); MoveContent(oldChildArchives, archiveEntries, metricsEntries, listingEntries, targetArchvie, rootDirectory); }
private void AnalizeUncompressedArchive(MemoryMappedFile memoryFile, ArchiveArchiveEntry archive, long parentOffset) { using (MemoryMappedViewStream metricsStream = memoryFile.CreateViewStream(parentOffset + archive.MetricsEntry.ContentOffset, archive.MetricsEntry.UncompressedContentSize)) using (MemoryMappedViewStream listingStream = memoryFile.CreateViewStream(parentOffset + archive.ListingEntry.ContentOffset, archive.ListingEntry.UncompressedContentSize)) { ReadInformation(archive, metricsStream, listingStream); foreach (ArchiveArchiveEntry child in archive.Childs.OfType <ArchiveArchiveEntry>()) { AnalizeUncompressedArchive(memoryFile, child, parentOffset + archive.ContentEntry.ContentOffset); } } }
public long GetAbsoluteOffset() { long result = ContentOffset; ArchiveArchiveEntry parent = ParentArchive; while (parent != null && parent.ContentEntry != null) { result += parent.ContentEntry.ContentOffset; parent = parent.ParentArchive; } return(result); }
private ArchiveArchiveEntry[] MoveArchive(ArchiveArchiveEntry[] oldArchives, ArchiveArchiveEntry newParent) { List <ArchiveArchiveEntry> result = new List <ArchiveArchiveEntry>(oldArchives.Length); foreach (ArchiveArchiveEntry oldArchive in oldArchives) { ArchiveArchiveEntry newArchive = new ArchiveArchiveEntry(oldArchive.Name); newParent.AddEntry(newArchive); result.Add(newArchive); } return(result.ToArray()); }
private void MoveFile(ArchiveFileEntry oldFile, ArchiveArchiveEntry newParent, ArchiveDirectoryEntry newDirectory) { ArchiveFileEntry newFile = oldFile.Clone(); { newFile.Compression = Compression.None; newFile.ContentOffset = newParent.CurrentPosition; SetCapacity(newFile); newParent.CurrentPosition += newFile.ContentCapacity; } newParent.AddEntry(newFile); newDirectory.AddEntry(oldFile.GetFullPath(), newFile); }
public ArchiveInformation(string filePath, long fileSize, DateTime fileTime, bool isOptimized) { Exceptions.CheckArgumentNullOrEmprty(filePath, "filePath"); if (fileSize < 0) { throw new ArgumentOutOfRangeException("fileSize", fileSize, "Размер файла не может быть отрицательным."); } FilePath = Path.ChangeExtension(filePath, null); FileSize = fileSize; FileTime = fileTime; IsOptimized = isOptimized; RootArchive = new ArchiveArchiveEntry(Path.GetFileNameWithoutExtension(FilePath)); RootDirectory = new ArchiveDirectoryEntry("c:"); }
public MemoryMappedFile GetMemoryMappedFile(MemoryMappedFileAccess access) { ArchiveArchiveEntry archive = this; while (archive.ParentArchive != null) { archive = archive.ParentArchive; } string path = Path.Combine(Options.GameDataDirectoryPath, archive.Name + ".fs"); FileStream stream = new FileStream(path, FileMode.Open, ConvertAccess(access), FileShare.ReadWrite); try { return(MemoryMappedFile.CreateFromFile(stream, null, 0, access, null, HandleInheritability.Inheritable, false)); } catch { stream.SafeDispose(); throw; } }
private ArchiveFileEntry[] MoveListing(ArchiveArchiveEntry[] oldArchives, ArchiveArchiveEntry[] newArchives, ArchiveArchiveEntry newParent) { List <ArchiveFileEntry> result = new List <ArchiveFileEntry>(oldArchives.Length); for (int i = 0; i < oldArchives.Length; i++) { ArchiveArchiveEntry oldArchive = oldArchives[i]; ArchiveArchiveEntry newArchive = newArchives[i]; ArchiveFileEntry newListing = oldArchive.ListingEntry.Clone(); { newListing.Compression = Compression.None; newListing.ContentOffset = newParent.CurrentPosition; newArchive.ListingEntry = newListing; SetCapacity(newListing); newParent.CurrentPosition += newListing.ContentCapacity; } result.Add(newListing); } return(result.ToArray()); }
private void ReadInformation(ArchiveArchiveEntry parentArchive, Stream metricsStream, Stream listingStream) { _childArchives.Clear(); using (BinaryReader mbr = new BinaryReader(metricsStream)) using (StreamReader lsr = new StreamReader(listingStream, Encoding.GetEncoding(1251))) { int index = 0; while (!lsr.EndOfStream) { string path = lsr.ReadLine(); if (string.IsNullOrEmpty(path)) { break; } int uncompressedContentSize = mbr.ReadInt32(); int contentOffset = mbr.ReadInt32(); int compression = mbr.ReadInt32(); ArchiveFileEntry entry = new ArchiveFileEntry(Path.GetFileName(path)) { Index = index++, UncompressedContentSize = uncompressedContentSize, ContentOffset = contentOffset, Compression = (Compression)compression }; if (TryAddChildArchive(path, entry, parentArchive)) { continue; } parentArchive.AddEntry(entry); _info.RootDirectory.AddEntry(path, entry); } } }