Make archives more distinct from normal folders

This commit is contained in:
Matt Nadareski
2025-01-04 22:09:53 -05:00
parent acdc8d84b1
commit 3dc8466cf7
5 changed files with 156 additions and 81 deletions

View File

@@ -470,7 +470,7 @@ namespace SabreTools.DatTools
outputFormat = OutputFormat.ParentFolder; outputFormat = OutputFormat.ParentFolder;
// Get the output archive, if possible // Get the output archive, if possible
Folder? outputArchive = GetPreconfiguredFolder(datFile, date, outputFormat); IFolder? outputArchive = GetPreconfiguredFolder(datFile, date, outputFormat);
// Now rebuild to the output file // Now rebuild to the output file
outputArchive!.Write(fileStream, outDir, (item as Rom)!.ConvertToBaseFile()); outputArchive!.Write(fileStream, outDir, (item as Rom)!.ConvertToBaseFile());
@@ -516,7 +516,7 @@ namespace SabreTools.DatTools
datItem.SetName($"{datItem.GetName()}_{crc}"); datItem.SetName($"{datItem.GetName()}_{crc}");
// Get the output archive, if possible // Get the output archive, if possible
Folder? outputArchive = GetPreconfiguredFolder(datFile, date, outputFormat); IFolder? outputArchive = GetPreconfiguredFolder(datFile, date, outputFormat);
// Now rebuild to the output file // Now rebuild to the output file
bool eitherSuccess = false; bool eitherSuccess = false;
@@ -822,9 +822,9 @@ namespace SabreTools.DatTools
/// <param name="date">True if the date from the DAT should be used if available, false otherwise</param> /// <param name="date">True if the date from the DAT should be used if available, false otherwise</param>
/// <param name="outputFormat">Output format that files should be written to</param> /// <param name="outputFormat">Output format that files should be written to</param>
/// <returns>Folder configured with proper flags</returns> /// <returns>Folder configured with proper flags</returns>
private static Folder? GetPreconfiguredFolder(DatFile datFile, bool date, OutputFormat outputFormat) private static IFolder? GetPreconfiguredFolder(DatFile datFile, bool date, OutputFormat outputFormat)
{ {
Folder? outputArchive = FileTypeTool.CreateFolderType(outputFormat); IFolder? outputArchive = FileTypeTool.CreateFolderType(outputFormat);
if (outputArchive is BaseArchive baseArchive && date) if (outputArchive is BaseArchive baseArchive && date)
baseArchive.SetRealDates(date); baseArchive.SetRealDates(date);

View File

@@ -1,12 +1,24 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using SabreTools.Hashing;
using SabreTools.IO.Logging;
namespace SabreTools.FileTypes namespace SabreTools.FileTypes
{ {
public abstract class BaseArchive : Folder public abstract class BaseArchive : BaseFile, IFolder
{ {
#region Protected instance variables #region Protected instance variables
/// <summary>
/// Hashes that are available for children
/// </summary>
protected HashType[] _hashTypes = [HashType.CRC32, HashType.MD5, HashType.SHA1];
/// <summary>
/// Set of children file objects
/// </summary>
protected List<BaseFile>? _children;
/// <summary> /// <summary>
/// Determines if real dates are written /// Determines if real dates are written
/// </summary> /// </summary>
@@ -17,6 +29,11 @@ namespace SabreTools.FileTypes
/// </summary> /// </summary>
protected const int _bufferSize = 4096 * 128; protected const int _bufferSize = 4096 * 128;
/// <summary>
/// Logging object
/// </summary>
protected Logger _logger;
#endregion #endregion
#region Construtors #region Construtors
@@ -24,36 +41,54 @@ namespace SabreTools.FileTypes
/// <summary> /// <summary>
/// Create a new Archive with no base file /// Create a new Archive with no base file
/// </summary> /// </summary>
public BaseArchive() : base(writeToParent: false) { } public BaseArchive()
{
_logger = new Logger(this);
}
/// <summary> /// <summary>
/// Create a new BaseArchive from the given file /// Create a new BaseArchive from the given file
/// </summary> /// </summary>
/// <param name="filename">Name of the file to use</param> /// <param name="filename">Name of the file to use</param>
public BaseArchive(string filename) : base(filename, writeToParent: false) { } public BaseArchive(string filename) : base(filename)
{
_logger = new Logger(this);
}
#endregion #endregion
#region Extraction #region Extraction
/// <inheritdoc/> /// <inheritdoc/>
public override abstract bool CopyAll(string outDir); public abstract bool CopyAll(string outDir);
/// <inheritdoc/> /// <inheritdoc/>
public override abstract string? CopyToFile(string entryName, string outDir); public abstract string? CopyToFile(string entryName, string outDir);
/// <inheritdoc/> /// <inheritdoc/>
public override abstract (Stream?, string?) GetEntryStream(string entryName); public abstract (Stream?, string?) GetEntryStream(string entryName);
#endregion #endregion
#region Information #region Information
/// <inheritdoc/> /// <summary>
public override abstract List<BaseFile>? GetChildren(); /// Set the hash type that can be included in children
/// </summary>
public void SetHashType(HashType hashType)
=> SetHashTypes([hashType]);
/// <summary>
/// Set the hash types that can be included in children
/// </summary>
public void SetHashTypes(HashType[] hashTypes)
=> _hashTypes = hashTypes;
/// <inheritdoc/> /// <inheritdoc/>
public override abstract List<string> GetEmptyFolders(); public abstract List<BaseFile>? GetChildren();
/// <inheritdoc/>
public abstract List<string> GetEmptyFolders();
/// <summary> /// <summary>
/// Check whether the input file is a standardized format /// Check whether the input file is a standardized format
@@ -73,13 +108,13 @@ namespace SabreTools.FileTypes
} }
/// <inheritdoc/> /// <inheritdoc/>
public override abstract bool Write(string inputFile, string outDir, BaseFile? baseFile); public abstract bool Write(string inputFile, string outDir, BaseFile? baseFile);
/// <inheritdoc/> /// <inheritdoc/>
public override abstract bool Write(Stream? inputStream, string outDir, BaseFile? baseFile); public abstract bool Write(Stream? inputStream, string outDir, BaseFile? baseFile);
/// <inheritdoc/> /// <inheritdoc/>
public override abstract bool Write(List<string> inputFiles, string outDir, List<BaseFile>? baseFiles); public abstract bool Write(List<string> inputFiles, string outDir, List<BaseFile>? baseFiles);
#endregion #endregion
} }

View File

@@ -173,11 +173,11 @@ namespace SabreTools.FileTypes
} }
/// <summary> /// <summary>
/// Create an Folder object of the specified type, if possible /// Create an IFolder object of the specified type, if possible
/// </summary> /// </summary>
/// <param name="outputFormat">OutputFormat representing the archive to create</param> /// <param name="outputFormat">OutputFormat representing the archive to create</param>
/// <returns>Archive object representing the inputs</returns> /// <returns>IFolder object representing the inputs</returns>
public static Folder? CreateFolderType(OutputFormat outputFormat) public static IFolder? CreateFolderType(OutputFormat outputFormat)
{ {
return outputFormat switch return outputFormat switch
{ {

View File

@@ -12,7 +12,7 @@ namespace SabreTools.FileTypes
/// <summary> /// <summary>
/// Represents a folder for reading and writing /// Represents a folder for reading and writing
/// </summary> /// </summary>
public class Folder : BaseFile public class Folder : BaseFile, IFolder
{ {
#region Protected instance variables #region Protected instance variables
@@ -31,11 +31,6 @@ namespace SabreTools.FileTypes
/// </summary> /// </summary>
protected Logger _logger; protected Logger _logger;
/// <summary>
/// Static logger for static methods
/// </summary>
protected static Logger _staticLogger = new();
/// <summary> /// <summary>
/// Flag specific to Folder to omit Machine name from output path /// Flag specific to Folder to omit Machine name from output path
/// </summary> /// </summary>
@@ -70,12 +65,8 @@ namespace SabreTools.FileTypes
#region Extraction #region Extraction
/// <summary> /// <inheritdoc/>
/// Attempt to extract a file as an archive public bool CopyAll(string outDir)
/// </summary>
/// <param name="outDir">Output directory for archive extraction</param>
/// <returns>True if the extraction was a success, false otherwise</returns>
public virtual bool CopyAll(string outDir)
{ {
// If we have an invalid filename // If we have an invalid filename
if (Filename == null) if (Filename == null)
@@ -138,13 +129,8 @@ namespace SabreTools.FileTypes
} }
} }
/// <summary> /// <inheritdoc/>
/// Attempt to extract a file from an archive public string? CopyToFile(string entryName, string outDir)
/// </summary>
/// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="outDir">Output directory for archive extraction</param>
/// <returns>Name of the extracted file, null on error</returns>
public virtual string? CopyToFile(string entryName, string outDir)
{ {
string? realentry = null; string? realentry = null;
@@ -181,12 +167,8 @@ namespace SabreTools.FileTypes
return realentry; return realentry;
} }
/// <summary> /// <inheritdoc/>
/// Attempt to extract a stream from an archive public (Stream?, string?) GetEntryStream(string entryName)
/// </summary>
/// <param name="entryName">Name of the entry to be extracted</param>
/// <returns>Stream representing the entry, null on error</returns>
public virtual (Stream?, string?) GetEntryStream(string entryName)
{ {
// If we have an invalid filename // If we have an invalid filename
if (Filename == null) if (Filename == null)
@@ -236,11 +218,8 @@ namespace SabreTools.FileTypes
public void SetHashTypes(HashType[] hashTypes) public void SetHashTypes(HashType[] hashTypes)
=> _hashTypes = hashTypes; => _hashTypes = hashTypes;
/// <summary> /// <inheritdoc/>
/// Generate a list of immediate children from the current folder public List<BaseFile>? GetChildren()
/// </summary>
/// <returns>List of BaseFile objects representing the found data</returns>
public virtual List<BaseFile>? GetChildren()
{ {
// If we have an invalid filename // If we have an invalid filename
if (Filename == null) if (Filename == null)
@@ -274,12 +253,8 @@ namespace SabreTools.FileTypes
return _children; return _children;
} }
/// <summary> /// <inheritdoc/>
/// Generate a list of empty folders in an archive public List<string>? GetEmptyFolders()
/// </summary>
/// <param name="input">Input file to get data from</param>
/// <returns>List of empty folders in the folder</returns>
public virtual List<string>? GetEmptyFolders()
{ {
return Filename.ListEmpty(); return Filename.ListEmpty();
} }
@@ -288,29 +263,15 @@ namespace SabreTools.FileTypes
#region Writing #region Writing
/// <summary> /// <inheritdoc/>
/// Write an input file to an output folder public bool Write(string inputFile, string outDir, BaseFile? baseFile)
/// </summary>
/// <param name="inputFile">Input filename to be moved</param>
/// <param name="outDir">Output directory to build to</param>
/// <param name="baseFile">BaseFile representing the new information</param>
/// <returns>True if the write was a success, false otherwise</returns>
/// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks>
public virtual bool Write(string inputFile, string outDir, BaseFile? baseFile)
{ {
FileStream fs = File.OpenRead(inputFile); FileStream fs = File.OpenRead(inputFile);
return Write(fs, outDir, baseFile); return Write(fs, outDir, baseFile);
} }
/// <summary> /// <inheritdoc/>
/// Write an input stream to an output folder public bool Write(Stream? inputStream, string outDir, BaseFile? baseFile)
/// </summary>
/// <param name="inputStream">Input stream to be moved</param>
/// <param name="outDir">Output directory to build to</param>
/// <param name="baseFile">BaseFile representing the new information</param>
/// <returns>True if the write was a success, false otherwise</returns>
/// <remarks>This works for now, but it can be sped up by using Ionic.Zip or another zlib wrapper that allows for header values built-in. See edc's code.</remarks>
public virtual bool Write(Stream? inputStream, string outDir, BaseFile? baseFile)
{ {
// If either input is null or empty, return // If either input is null or empty, return
if (inputStream == null || baseFile == null || baseFile.Filename == null) if (inputStream == null || baseFile == null || baseFile.Filename == null)
@@ -388,14 +349,8 @@ namespace SabreTools.FileTypes
} }
} }
/// <summary> /// <inheritdoc/>
/// Write a set of input files to an output folder (assuming the same output archive name) public bool Write(List<string> inputFiles, string outDir, List<BaseFile>? baseFiles)
/// </summary>
/// <param name="inputFiles">Input files to be moved</param>
/// <param name="outDir">Output directory to build to</param>
/// <param name="baseFiles">BaseFiles representing the new information</param>
/// <returns>True if the inputs were written properly, false otherwise</returns>
public virtual bool Write(List<string> inputFiles, string outDir, List<BaseFile>? baseFiles)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

View File

@@ -0,0 +1,85 @@
using System.Collections.Generic;
using System.IO;
namespace SabreTools.FileTypes
{
/// <summary>
/// Represents an item that can contain children
/// </summary>
public interface IFolder
{
#region Extraction
/// <summary>
/// Attempt to extract a file as an archive
/// </summary>
/// <param name="outDir">Output directory for archive extraction</param>
/// <returns>True if the extraction was a success, false otherwise</returns>
bool CopyAll(string outDir);
/// <summary>
/// Attempt to extract a file from an archive
/// </summary>
/// <param name="entryName">Name of the entry to be extracted</param>
/// <param name="outDir">Output directory for archive extraction</param>
/// <returns>Name of the extracted file, null on error</returns>
string? CopyToFile(string entryName, string outDir);
/// <summary>
/// Attempt to extract a stream from an archive
/// </summary>
/// <param name="entryName">Name of the entry to be extracted</param>
/// <returns>Stream representing the entry, null on error</returns>
(Stream?, string?) GetEntryStream(string entryName);
#endregion
#region Information
/// <summary>
/// Generate a list of immediate children from the current folder
/// </summary>
/// <returns>List of BaseFile objects representing the found data</returns>
List<BaseFile>? GetChildren();
/// <summary>
/// Generate a list of empty folders in an archive
/// </summary>
/// <param name="input">Input file to get data from</param>
/// <returns>List of empty folders in the folder</returns>
List<string>? GetEmptyFolders();
#endregion
#region Writing
/// <summary>
/// Write an input file to an output folder
/// </summary>
/// <param name="inputFile">Input filename to be moved</param>
/// <param name="outDir">Output directory to build to</param>
/// <param name="baseFile">BaseFile representing the new information</param>
/// <returns>True if the write was a success, false otherwise</returns>
bool Write(string inputFile, string outDir, BaseFile? baseFile);
/// <summary>
/// Write an input stream to an output folder
/// </summary>
/// <param name="inputStream">Input stream to be moved</param>
/// <param name="outDir">Output directory to build to</param>
/// <param name="baseFile">BaseFile representing the new information</param>
/// <returns>True if the write was a success, false otherwise</returns>
bool Write(Stream? inputStream, string outDir, BaseFile? baseFile);
/// <summary>
/// Write a set of input files to an output folder (assuming the same output archive name)
/// </summary>
/// <param name="inputFiles">Input files to be moved</param>
/// <param name="outDir">Output directory to build to</param>
/// <param name="baseFiles">BaseFiles representing the new information</param>
/// <returns>True if the inputs were written properly, false otherwise</returns>
bool Write(List<string> inputFiles, string outDir, List<BaseFile>? baseFiles);
#endregion
}
}