From 067afedb600485af20e2ec7b70bb41055499a365 Mon Sep 17 00:00:00 2001 From: Diogo Trindade Date: Thu, 17 Oct 2024 17:39:01 +0100 Subject: [PATCH] file processors initial work --- .../FileProcessing/CryXmlProcessor.cs | 12 +++---- .../FileProcessing/IFileProcessor.cs | 31 +++++++++++++++++++ .../FileProcessing/ZipFileProcessor.cs | 6 ++-- src/StarBreaker.P4k/P4kFile.cs | 8 +++++ src/StarBreaker.Sandbox/Program.cs | 4 +-- 5 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 src/StarBreaker.P4k/FileProcessing/IFileProcessor.cs diff --git a/src/StarBreaker.P4k/FileProcessing/CryXmlProcessor.cs b/src/StarBreaker.P4k/FileProcessing/CryXmlProcessor.cs index b80aaa5..1cf6b7a 100644 --- a/src/StarBreaker.P4k/FileProcessing/CryXmlProcessor.cs +++ b/src/StarBreaker.P4k/FileProcessing/CryXmlProcessor.cs @@ -6,17 +6,17 @@ public sealed class CryXmlProcessor : IFileProcessor { public bool CanProcess(string entryName, Stream stream) { - if (stream.Length < 4) - return false; - Span test = stackalloc byte[4]; - if (stream.Read(test) != 4) + var read = stream.Read(test); + stream.Seek(0, SeekOrigin.Current); + + if (read != 4) return false; - + return CryXml.IsCryXmlB(test); } - public void ProcessEntry(string outputRootFolder, string entryName, Stream stream) + public void ProcessEntry(string outputRootFolder, string entryName, Stream entryStream) { throw new NotImplementedException(); } diff --git a/src/StarBreaker.P4k/FileProcessing/IFileProcessor.cs b/src/StarBreaker.P4k/FileProcessing/IFileProcessor.cs new file mode 100644 index 0000000..e10c2c2 --- /dev/null +++ b/src/StarBreaker.P4k/FileProcessing/IFileProcessor.cs @@ -0,0 +1,31 @@ +namespace StarBreaker.P4k; + +public interface IFileProcessor +{ + bool CanProcess(string entryName, Stream stream); + void ProcessEntry(string outputRootFolder, string entryName, Stream entryStream); +} + +public static class FileProcessors +{ + private static readonly GenericFileProcessor _genericFileProcessor = new(); + public static List Processors { get; } + + static FileProcessors() + { + //reflection would be nicer but native aot doesn't support it + Processors = + [ + new CryXmlProcessor(), + new ZipFileProcessor(), + ]; + } + + public static IFileProcessor GetProcessor(string entryName, Stream entryStream) + { + if (Processors.FirstOrDefault(p => p.CanProcess(entryName, entryStream)) is { } processor) + return processor; + + return _genericFileProcessor; + } +} \ No newline at end of file diff --git a/src/StarBreaker.P4k/FileProcessing/ZipFileProcessor.cs b/src/StarBreaker.P4k/FileProcessing/ZipFileProcessor.cs index 9e07c34..f352aef 100644 --- a/src/StarBreaker.P4k/FileProcessing/ZipFileProcessor.cs +++ b/src/StarBreaker.P4k/FileProcessing/ZipFileProcessor.cs @@ -10,11 +10,11 @@ public bool CanProcess(string entryName, Stream stream) return entryName.EndsWith(".zip", StringComparison.OrdinalIgnoreCase); } - public void ProcessEntry(string outputRootFolder, string entryName, Stream stream) + public void ProcessEntry(string outputRootFolder, string entryName, Stream entryStream) { var entryPath = Path.Combine(outputRootFolder, Path.ChangeExtension(entryName, "unzipped")); - - using var archive = new ZipArchive(stream, ZipArchiveMode.Read); + + using var archive = new ZipArchive(entryStream, ZipArchiveMode.Read, leaveOpen: true); foreach (var childEntry in archive.Entries) { if (childEntry.Length == 0) diff --git a/src/StarBreaker.P4k/P4kFile.cs b/src/StarBreaker.P4k/P4kFile.cs index 753f77b..1512bac 100644 --- a/src/StarBreaker.P4k/P4kFile.cs +++ b/src/StarBreaker.P4k/P4kFile.cs @@ -132,6 +132,14 @@ public void Extract(string outputDir, string? filter = null, IProgress? var processedEntries = 0; progress?.Report(0); + + //TODO: Preprocessing step: + // 1. start with the list of total files + // 2. run the following according to the filter: + // 3. find one-shot single file procesors + // 4. find file -> multiple file processors + // 5. find multiple file -> single file unsplit processors - remove from the list so we don't double process + // run it! Parallel.ForEach(filteredEntries, entry => { diff --git a/src/StarBreaker.Sandbox/Program.cs b/src/StarBreaker.Sandbox/Program.cs index 823a8c1..6dadee0 100644 --- a/src/StarBreaker.Sandbox/Program.cs +++ b/src/StarBreaker.Sandbox/Program.cs @@ -5,7 +5,7 @@ //ExtractChunkFiles.Run(); //ExtractSocPak.Run(); //await GrpcClient.RunAsync(); -//TimeP4kExtract.Run(); +TimeP4kExtract.Run(); //TimeZipNode.Run(); -StringCrc32c.Run(); +//StringCrc32c.Run();