Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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;
            }
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
                    }
            }
        }
Пример #6
0
 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);
 }
Пример #7
0
 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);
             }
         }
 }
Пример #8
0
        public long GetAbsoluteOffset()
        {
            long result = ContentOffset;
            ArchiveArchiveEntry parent = ParentArchive;

            while (parent != null && parent.ContentEntry != null)
            {
                result += parent.ContentEntry.ContentOffset;
                parent  = parent.ParentArchive;
            }
            return(result);
        }
Пример #9
0
        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());
        }
Пример #10
0
        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);
        }
Пример #11
0
        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:");
        }
Пример #12
0
        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;
            }
        }
Пример #13
0
        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());
        }
Пример #14
0
        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);
                    }
                }
        }