Distinguish IO extensions and helpers

This commit is contained in:
Matt Nadareski
2020-12-10 22:16:53 -08:00
parent 7141904fc8
commit 58b3cda921
47 changed files with 325 additions and 353 deletions

View File

@@ -58,7 +58,7 @@ structure according to the original DAT master directory tree structure.";
// Create the new output directory if it doesn't exist
string outputFolder = Path.Combine(outdat, Path.GetFileNameWithoutExtension(foundDats[key]));
DirectoryExtensions.Ensure(outputFolder, create: true);
outputFolder.Ensure(create: true);
// Get all online depots
List<string> onlineDepots = _depots.Where(d => d.Value.Item2).Select(d => d.Key).ToList();

View File

@@ -40,7 +40,7 @@ in -old DAT file. Ignores those entries in -old that are not in -new.";
string outdat = GetString(features, OutStringValue);
// Ensure the output directory
DirectoryExtensions.Ensure(outdat, create: true);
outdat.Ensure(create: true);
// Check that all required files exist
if (!File.Exists(olddat))

View File

@@ -40,7 +40,7 @@ namespace RombaSharp.Features
string outdat = GetString(features, OutStringValue);
// Ensure the output directory
DirectoryExtensions.Ensure(outdat, create: true);
outdat.Ensure(create: true);
// Check that all required directories exist
if (!Directory.Exists(source))

View File

@@ -35,7 +35,7 @@ namespace RombaSharp.Features
string newdat = GetString(features, NewStringValue);
// Ensure the output directory
DirectoryExtensions.Ensure(outdat, create: true);
outdat.Ensure(create: true);
// Check that all required files exist
if (!File.Exists(olddat))

View File

@@ -29,7 +29,7 @@ namespace RombaSharp.Features
logger.Error("This feature is not yet implemented: import");
// First ensure the inputs and database connection
Inputs = DirectoryExtensions.GetFilesOnly(Inputs).Select(p => p.CurrentPath).ToList();
Inputs = PathTool.GetFilesOnly(Inputs).Select(p => p.CurrentPath).ToList();
SqliteConnection dbc = new SqliteConnection(_connectionString);
SqliteCommand slc = new SqliteCommand();
dbc.Open();

View File

@@ -40,7 +40,7 @@ namespace RombaSharp.Features
logger.Error("This feature is not yet implemented: merge");
// Verify that the inputs are valid directories
Inputs = DirectoryExtensions.GetDirectoriesOnly(Inputs).Select(p => p.CurrentPath).ToList();
Inputs = PathTool.GetDirectoriesOnly(Inputs).Select(p => p.CurrentPath).ToList();
// Loop over all input directories
foreach (string input in Inputs)

View File

@@ -31,7 +31,7 @@ namespace RombaSharp.Features
Dictionary<string, string> foundDats = GetValidDats(Inputs);
// Create the new output directory if it doesn't exist
DirectoryExtensions.Ensure(Path.Combine(Globals.ExeDir, "out"), create: true);
Path.Combine(Globals.ExeDir, "out").Ensure(create: true);
// Now that we have the dictionary, we can loop through and output to a new folder for each
foreach (string key in foundDats.Keys)

View File

@@ -3,9 +3,8 @@ using System.Linq;
using System.Security.Cryptography;
using Aaru.Checksums;
using SabreTools.Core;
namespace SabreTools.IO
namespace SabreTools.Core.Tools
{
/// <summary>
/// Async hashing class wraper

View File

@@ -116,6 +116,36 @@ namespace SabreTools.Core.Tools
(int)((msDosDateTime >> 11) & 0x1F), (int)((msDosDateTime >> 5) & 0x3F), (int)((msDosDateTime & 0x1F) * 2));
}
/// <summary>
/// Get a proper romba sub path
/// </summary>
/// <param name="hash">SHA-1 hash to get the path for</param>
/// <param name="depth">Positive value representing the depth of the depot</param>
/// <returns>Subfolder path for the given hash</returns>
public static string GetDepotPath(string hash, int depth)
{
// If the hash isn't the right size, then we return null
if (hash.Length != Constants.SHA1Length)
return null;
// Cap the depth between 0 and 20, for now
if (depth < 0)
depth = 0;
else if (depth > Constants.SHA1ZeroBytes.Length)
depth = Constants.SHA1ZeroBytes.Length;
// Loop through and generate the subdirectory
string path = string.Empty;
for (int i = 0; i < depth; i++)
{
path += hash.Substring(i * 2, 2) + Path.DirectorySeparatorChar;
}
// Now append the filename
path += $"{hash}.gz";
return path;
}
/// Indicates whether the specified array is null or has a length of zero
/// </summary>
/// <param name="array">The array to test</param>
@@ -123,7 +153,7 @@ namespace SabreTools.Core.Tools
/// <link>https://stackoverflow.com/questions/8560106/isnullorempty-equivalent-for-array-c-sharp</link>
public static bool IsNullOrEmpty(this Array array)
{
return (array == null || array.Length == 0);
return array == null || array.Length == 0;
}
/// <summary>
@@ -136,5 +166,33 @@ namespace SabreTools.Core.Tools
List<char> invalidPath = Path.GetInvalidPathChars().ToList();
return new string(s.Where(c => !invalidPath.Contains(c)).ToArray());
}
/// <summary>
/// Returns if the first byte array starts with the second array
/// </summary>
/// <param name="arr1">First byte array to compare</param>
/// <param name="arr2">Second byte array to compare</param>
/// <param name="exact">True if the input arrays should match exactly, false otherwise (default)</param>
/// <returns>True if the first byte array starts with the second, false otherwise</returns>
public static bool StartsWith(this byte[] arr1, byte[] arr2, bool exact = false)
{
// If we have any invalid inputs, we return false
if (arr1 == null || arr2 == null
|| arr1.Length == 0 || arr2.Length == 0
|| arr2.Length > arr1.Length
|| (exact && arr1.Length != arr2.Length))
{
return false;
}
// Otherwise, loop through and see
for (int i = 0; i < arr2.Length; i++)
{
if (arr1[i] != arr2[i])
return false;
}
return true;
}
}
}

View File

@@ -5,9 +5,9 @@ using System.Linq;
using System.Xml.Serialization;
using SabreTools.Core;
using SabreTools.Core.Tools;
using SabreTools.DatFiles.Formats;
using SabreTools.DatItems;
using SabreTools.IO;
using SabreTools.Logging;
using Newtonsoft.Json;
@@ -467,7 +467,7 @@ namespace SabreTools.DatFiles
// We can only write out if there's a SHA-1
if (!string.IsNullOrWhiteSpace(disk.SHA1))
{
name = PathExtensions.GetDepotPath(disk.SHA1, Header.OutputDepot.Depth).Replace('\\', '/');
name = Utilities.GetDepotPath(disk.SHA1, Header.OutputDepot.Depth).Replace('\\', '/');
item.SetFields(new Dictionary<Field, string> { [Field.DatItem_Name] = $"{pre}{name}{post}" } );
}
}
@@ -478,7 +478,7 @@ namespace SabreTools.DatFiles
// We can only write out if there's a SHA-1
if (!string.IsNullOrWhiteSpace(media.SHA1))
{
name = PathExtensions.GetDepotPath(media.SHA1, Header.OutputDepot.Depth).Replace('\\', '/');
name = Utilities.GetDepotPath(media.SHA1, Header.OutputDepot.Depth).Replace('\\', '/');
item.SetFields(new Dictionary<Field, string> { [Field.DatItem_Name] = $"{pre}{name}{post}" });
}
}
@@ -489,7 +489,7 @@ namespace SabreTools.DatFiles
// We can only write out if there's a SHA-1
if (!string.IsNullOrWhiteSpace(rom.SHA1))
{
name = PathExtensions.GetDepotPath(rom.SHA1, Header.OutputDepot.Depth).Replace('\\', '/');
name = Utilities.GetDepotPath(rom.SHA1, Header.OutputDepot.Depth).Replace('\\', '/');
item.SetFields(new Dictionary<Field, string> { [Field.DatItem_Name] = $"{pre}{name}{post}" });
}
}

View File

@@ -45,7 +45,7 @@ namespace SabreTools.DatFiles
Hash hashes = Hash.Standard)
{
// Clean the temp directory path
Globals.TempDir = DirectoryExtensions.Ensure(Globals.TempDir, temp: true);
Globals.TempDir = Globals.TempDir.Ensure(temp: true);
// Set the progress variables
long totalSize = 0;
@@ -269,7 +269,7 @@ namespace SabreTools.DatFiles
if (datFile.Header.OutputDepot?.IsActive == true)
return;
List<string> empties = DirectoryExtensions.ListEmpty(basePath);
List<string> empties = basePath.ListEmpty();
Parallel.ForEach(empties, Globals.ParallelOptions, dir =>
{
// Get the full path for the directory

View File

@@ -1058,10 +1058,10 @@ namespace SabreTools.DatFiles
/// <returns>String containing the new filename</returns>
private string CreateOutFileNamesHelper(string outDir, string extension, bool overwrite)
{
string filename = (string.IsNullOrWhiteSpace(FileName) ? Description : FileName);
string filename = string.IsNullOrWhiteSpace(FileName) ? Description : FileName;
// Strip off the extension if it's a holdover from the DAT
if (PathExtensions.HasValidDatExtension(filename))
if (Parser.HasValidDatExtension(filename))
filename = Path.GetFileNameWithoutExtension(filename);
string outfile = $"{outDir}{filename}{extension}";

View File

@@ -35,7 +35,7 @@ namespace SabreTools.DatFiles.Formats
public override void ParseFile(string filename, int indexId, bool keep, bool throwOnError = false)
{
// Open a file reader
Encoding enc = FileExtensions.GetEncoding(filename);
Encoding enc = filename.GetEncoding();
SeparatedValueReader svr = new SeparatedValueReader(File.OpenRead(filename), enc)
{
Header = true,

View File

@@ -47,7 +47,7 @@ namespace SabreTools.DatFiles.Formats
public override void ParseFile(string filename, int indexId, bool keep, bool throwOnError = false)
{
// Open a file reader
Encoding enc = FileExtensions.GetEncoding(filename);
Encoding enc = filename.GetEncoding();
ClrMameProReader cmpr = new ClrMameProReader(File.OpenRead(filename), enc)
{
DosCenter = false,

View File

@@ -37,7 +37,7 @@ namespace SabreTools.DatFiles.Formats
public override void ParseFile(string filename, int indexId, bool keep, bool throwOnError = false)
{
// Open a file reader
Encoding enc = FileExtensions.GetEncoding(filename);
Encoding enc = filename.GetEncoding();
ClrMameProReader cmpr = new ClrMameProReader(File.OpenRead(filename), enc)
{
DosCenter = true

View File

@@ -35,7 +35,7 @@ namespace SabreTools.DatFiles.Formats
public override void ParseFile(string filename, int indexId, bool keep, bool throwOnError = false)
{
// Open a file reader
Encoding enc = FileExtensions.GetEncoding(filename);
Encoding enc = filename.GetEncoding();
SeparatedValueReader svr = new SeparatedValueReader(File.OpenRead(filename), enc)
{
Header = false,

View File

@@ -39,7 +39,7 @@ namespace SabreTools.DatFiles.Formats
public override void ParseFile(string filename, int indexId, bool keep, bool throwOnError = false)
{
// Open a file reader
Encoding enc = FileExtensions.GetEncoding(filename);
Encoding enc = filename.GetEncoding();
StreamReader sr = new StreamReader(File.OpenRead(filename), enc);
while (!sr.EndOfStream)

View File

@@ -44,7 +44,7 @@ namespace SabreTools.DatFiles.Formats
public override void ParseFile(string filename, int indexId, bool keep, bool throwOnError = false)
{
// Open a file reader
Encoding enc = FileExtensions.GetEncoding(filename);
Encoding enc = filename.GetEncoding();
StreamReader sr = new StreamReader(File.OpenRead(filename), enc);
string gamename = string.Empty;

View File

@@ -898,7 +898,7 @@ namespace SabreTools.DatFiles.Formats
if (datItem.ItemType == ItemType.Rom)
{
var rom = datItem as Rom;
string tempext = "." + PathExtensions.GetNormalizedExtension(rom.Name);
string tempext = "." + rom.Name.GetNormalizedExtension();
xtw.WriteStartElement("files");
if (!string.IsNullOrWhiteSpace(rom.CRC))

View File

@@ -41,7 +41,7 @@ namespace SabreTools.DatFiles.Formats
public override void ParseFile(string filename, int indexId, bool keep, bool throwOnError = false)
{
// Open a file reader
Encoding enc = FileExtensions.GetEncoding(filename);
Encoding enc = filename.GetEncoding();
SeparatedValueReader svr = new SeparatedValueReader(File.OpenRead(filename), enc)
{
Header = true,

View File

@@ -1369,13 +1369,13 @@ namespace SabreTools.DatFiles
reportName = "report";
// Get the proper output directory name
outDir = DirectoryExtensions.Ensure(outDir);
outDir = outDir.Ensure();
// Get the dictionary of desired output report names
Dictionary<StatReportFormat, string> outputs = CreateOutStatsNames(outDir, statDatFormat, reportName);
// Make sure we have all files and then order them
List<ParentablePath> files = DirectoryExtensions.GetFilesOnly(inputs);
List<ParentablePath> files = PathTool.GetFilesOnly(inputs);
files = files
.OrderBy(i => Path.GetDirectoryName(i.CurrentPath))
.ThenBy(i => Path.GetFileName(i.CurrentPath))

View File

@@ -78,7 +78,7 @@ namespace SabreTools.DatFiles
string currentPath = input.CurrentPath;
// Check the file extension first as a safeguard
if (!PathExtensions.HasValidDatExtension(currentPath))
if (!HasValidDatExtension(currentPath))
return;
// If the output filename isn't set already, get the internal filename
@@ -105,6 +105,39 @@ namespace SabreTools.DatFiles
}
}
/// <summary>
/// Get if the given path has a valid DAT extension
/// </summary>
/// <param name="path">Path to check</param>
/// <returns>True if the extension is valid, false otherwise</returns>
public static bool HasValidDatExtension(string path)
{
// Get the extension from the path, if possible
string ext = path.GetNormalizedExtension();
// Check against the list of known DAT extensions
switch (ext)
{
case "csv":
case "dat":
case "json":
case "md5":
case "ripemd160":
case "sfv":
case "sha1":
case "sha256":
case "sha384":
case "sha512":
case "ssv":
case "tsv":
case "txt":
case "xml":
return true;
default:
return false;
}
}
/// <summary>
/// Get what type of DAT the input file is
/// </summary>
@@ -113,11 +146,11 @@ namespace SabreTools.DatFiles
private static DatFormat GetDatFormat(string filename)
{
// Limit the output formats based on extension
if (!PathExtensions.HasValidDatExtension(filename))
if (!HasValidDatExtension(filename))
return 0;
// Get the extension from the filename
string ext = PathExtensions.GetNormalizedExtension(filename);
string ext = filename.GetNormalizedExtension();
// Check if file exists
if (!File.Exists(filename))

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks;
using SabreTools.Core;
using SabreTools.Core.Tools;
using SabreTools.DatItems;
using SabreTools.FileTypes;
using SabreTools.IO;
@@ -54,7 +55,7 @@ namespace SabreTools.DatFiles
}
// Check that the output directory exists
outDir = DirectoryExtensions.Ensure(outDir, create: true);
outDir = outDir.Ensure(create: true);
// Now we want to get forcepack flag if it's not overridden
if (outputFormat == OutputFormat.Folder && datFile.Header.ForcePacking != PackingFlag.None)
@@ -102,7 +103,7 @@ namespace SabreTools.DatFiles
logger.User($"Checking hash '{hash}'");
// Get the extension path for the hash
string subpath = PathExtensions.GetDepotPath(hash, datFile.Header.InputDepot.Depth);
string subpath = Utilities.GetDepotPath(hash, datFile.Header.InputDepot.Depth);
// Find the first depot that includes the hash
string foundpath = null;
@@ -542,7 +543,7 @@ namespace SabreTools.DatFiles
// Get the proper output path
string sha1 = (datItem as Rom).SHA1 ?? string.Empty;
if (outputFormat == OutputFormat.TorrentGzipRomba)
outDir = Path.Combine(outDir, PathExtensions.GetDepotPath(sha1, datFile.Header.OutputDepot.Depth));
outDir = Path.Combine(outDir, Utilities.GetDepotPath(sha1, datFile.Header.OutputDepot.Depth));
else
outDir = Path.Combine(outDir, sha1 + ".gz");
@@ -586,7 +587,7 @@ namespace SabreTools.DatFiles
// Get the proper output path
string sha1 = (datItem as Rom).SHA1 ?? string.Empty;
if (outputFormat == OutputFormat.TorrentXZRomba)
outDir = Path.Combine(outDir, PathExtensions.GetDepotPath(sha1, datFile.Header.OutputDepot.Depth)).Replace(".gz", ".xz");
outDir = Path.Combine(outDir, Utilities.GetDepotPath(sha1, datFile.Header.OutputDepot.Depth)).Replace(".gz", ".xz");
else
outDir = Path.Combine(outDir, sha1 + ".xz");

View File

@@ -63,11 +63,11 @@ namespace SabreTools.DatFiles
List<DatItem> items = datFile.Items[key];
foreach (DatItem item in items)
{
if (newExtA.Contains(PathExtensions.GetNormalizedExtension(item.GetName() ?? string.Empty)))
if (newExtA.Contains((item.GetName() ?? string.Empty).GetNormalizedExtension()))
{
extADat.Items.Add(key, item);
}
else if (newExtB.Contains(PathExtensions.GetNormalizedExtension(item.GetName() ?? string.Empty)))
else if (newExtB.Contains((item.GetName() ?? string.Empty).GetNormalizedExtension()))
{
extBDat.Items.Add(key, item);
}

View File

@@ -3,9 +3,9 @@ using System.IO;
using System.Linq;
using SabreTools.Core;
using SabreTools.Core.Tools;
using SabreTools.DatItems;
using SabreTools.FileTypes;
using SabreTools.IO;
using SabreTools.Logging;
// This file represents all methods related to verifying with a DatFile
@@ -64,7 +64,7 @@ namespace SabreTools.DatFiles
logger.User($"Checking hash '{hash}'");
// Get the extension path for the hash
string subpath = PathExtensions.GetDepotPath(hash, datFile.Header.InputDepot.Depth);
string subpath = Utilities.GetDepotPath(hash, datFile.Header.InputDepot.Depth);
// Find the first depot that includes the hash
string foundpath = null;

View File

@@ -48,7 +48,7 @@ namespace SabreTools.DatFiles
}
// Ensure the output directory is set and created
outDir = DirectoryExtensions.Ensure(outDir, create: true);
outDir = outDir.Ensure(create: true);
// If the DAT has no output format, default to XML
if (datFile.Header.DatFormat == 0)

View File

@@ -1,6 +1,7 @@
using System.IO;
using System.Text;
using SabreTools.Core.Tools;
using SabreTools.IO;
using SabreTools.FileTypes.Aaru;

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks;
using SabreTools.Core;
using SabreTools.Core.Tools;
using SabreTools.IO;
using SabreTools.Logging;
using SabreTools.Skippers;
@@ -207,7 +208,7 @@ namespace SabreTools.FileTypes
return outFileType;
// First line of defense is going to be the extension, for better or worse
if (!PathExtensions.HasValidArchiveExtension(input))
if (!HasValidArchiveExtension(input))
return outFileType;
// Read the first bytes of the file and get the magic number
@@ -451,6 +452,48 @@ namespace SabreTools.FileTypes
}
}
/// <summary>
/// Get if the given path has a valid DAT extension
/// </summary>
/// <param name="path">Path to check</param>
/// <returns>True if the extension is valid, false otherwise</returns>
private static bool HasValidArchiveExtension(string path)
{
// Get the extension from the path, if possible
string ext = path.GetNormalizedExtension();
// Check against the list of known archive extensions
switch (ext)
{
// Aaruformat
case "aaru":
case "aaruf":
case "aaruformat":
case "aif":
case "dicf":
// Archives
case "7z":
case "gz":
case "lzma":
case "rar":
case "rev":
case "r00":
case "r01":
case "tar":
case "tgz":
case "tlz":
case "zip":
case "zipx":
// CHD
case "chd":
return true;
default:
return false;
}
}
#endregion
}
}

View File

@@ -201,7 +201,7 @@ namespace SabreTools.FileTypes
Directory.CreateDirectory(outDir);
// Get all files from the input directory
List<string> files = DirectoryExtensions.GetFilesOrdered(this.Filename);
List<string> files = PathTool.GetFilesOrdered(this.Filename);
// Now sort through to find the first file that matches
string match = files.Where(s => s.EndsWith(entryName)).FirstOrDefault();
@@ -239,7 +239,7 @@ namespace SabreTools.FileTypes
Directory.CreateDirectory(this.Filename);
// Get all files from the input directory
List<string> files = DirectoryExtensions.GetFilesOrdered(this.Filename);
List<string> files = PathTool.GetFilesOrdered(this.Filename);
// Now sort through to find the first file that matches
string match = files.Where(s => s.EndsWith(entryName)).FirstOrDefault();
@@ -296,7 +296,7 @@ namespace SabreTools.FileTypes
/// <returns>List of empty folders in the folder</returns>
public virtual List<string> GetEmptyFolders()
{
return DirectoryExtensions.ListEmpty(this.Filename);
return this.Filename.ListEmpty();
}
#endregion

View File

@@ -445,7 +445,7 @@ namespace SabreTools.FileTypes
baseFile = GetInfo(inputStream, keepReadOpen: true);
// Get the output file name
string outfile = Path.Combine(outDir, PathExtensions.GetDepotPath(Utilities.ByteArrayToString(baseFile.SHA1), Depth));
string outfile = Path.Combine(outDir, Utilities.GetDepotPath(Utilities.ByteArrayToString(baseFile.SHA1), Depth));
// Check to see if the folder needs to be created
if (!Directory.Exists(Path.GetDirectoryName(outfile)))

View File

@@ -337,7 +337,7 @@ namespace SabreTools.FileTypes
baseFile = GetInfo(inputStream, keepReadOpen: true);
// Get the output file name
string outfile = Path.Combine(outDir, PathExtensions.GetDepotPath(Utilities.ByteArrayToString(baseFile.SHA1), Depth));
string outfile = Path.Combine(outDir, Utilities.GetDepotPath(Utilities.ByteArrayToString(baseFile.SHA1), Depth));
outfile = outfile.Replace(".gz", ".xz");
// Check to see if the folder needs to be created

View File

@@ -1,77 +0,0 @@
using System.IO;
using System.Text;
namespace SabreTools.IO
{
/// <summary>
/// Extensions to File functionality
/// </summary>
public static class FileExtensions
{
/// <summary>
/// Determines a text file's encoding by analyzing its byte order mark (BOM).
/// Defaults to ASCII when detection of the text file's endianness fails.
/// </summary>
/// <param name="filename">The text file to analyze.</param>
/// <returns>The detected encoding.</returns>
/// <link>http://stackoverflow.com/questions/3825390/effective-way-to-find-any-files-encoding</link>
public static Encoding GetEncoding(string filename)
{
if (!File.Exists(filename))
return Encoding.Default;
// Try to open the file
try
{
FileStream file = File.OpenRead(filename);
if (file == null)
return Encoding.Default;
// Read the BOM
var bom = new byte[4];
file.Read(bom, 0, 4);
file.Dispose();
// Analyze the BOM
if (bom[0] == 0x2b && bom[1] == 0x2f && bom[2] == 0x76) return Encoding.UTF7;
if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf) return Encoding.UTF8;
if (bom[0] == 0xff && bom[1] == 0xfe) return Encoding.Unicode; //UTF-16LE
if (bom[0] == 0xfe && bom[1] == 0xff) return Encoding.BigEndianUnicode; //UTF-16BE
if (bom[0] == 0 && bom[1] == 0 && bom[2] == 0xfe && bom[3] == 0xff) return Encoding.UTF32;
return Encoding.Default;
}
catch
{
return Encoding.Default;
}
}
/// <summary>
/// Returns if the first byte array starts with the second array
/// </summary>
/// <param name="arr1">First byte array to compare</param>
/// <param name="arr2">Second byte array to compare</param>
/// <param name="exact">True if the input arrays should match exactly, false otherwise (default)</param>
/// <returns>True if the first byte array starts with the second, false otherwise</returns>
public static bool StartsWith(this byte[] arr1, byte[] arr2, bool exact = false)
{
// If we have any invalid inputs, we return false
if (arr1 == null || arr2 == null
|| arr1.Length == 0 || arr2.Length == 0
|| arr2.Length > arr1.Length
|| (exact && arr1.Length != arr2.Length))
{
return false;
}
// Otherwise, loop through and see
for (int i = 0; i < arr2.Length; i++)
{
if (arr1[i] != arr2[i])
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace SabreTools.IO
{
/// <summary>
/// Methods around path operations
/// </summary>
public static class IOExtensions
{
/// <summary>
/// Ensure the output directory is a proper format and can be created
/// </summary>
/// <param name="dir">Directory to check</param>
/// <param name="create">True if the directory should be created, false otherwise (default)</param>
/// <param name="temp">True if this is a temp directory, false otherwise</param>
/// <returns>Full path to the directory</returns>
public static string Ensure(this string dir, bool create = false, bool temp = false)
{
// If the output directory is invalid
if (string.IsNullOrWhiteSpace(dir))
{
if (temp)
dir = Path.GetTempPath();
else
dir = Environment.CurrentDirectory;
}
// Get the full path for the output directory
dir = Path.GetFullPath(dir);
// If we're creating the output folder, do so
if (create)
Directory.CreateDirectory(dir);
return dir;
}
/// <summary>
/// Determines a text file's encoding by analyzing its byte order mark (BOM).
/// Defaults to ASCII when detection of the text file's endianness fails.
/// </summary>
/// <param name="filename">The text file to analyze.</param>
/// <returns>The detected encoding.</returns>
/// <link>http://stackoverflow.com/questions/3825390/effective-way-to-find-any-files-encoding</link>
public static Encoding GetEncoding(this string filename)
{
if (string.IsNullOrEmpty(filename))
return Encoding.Default;
if (!File.Exists(filename))
return Encoding.Default;
// Try to open the file
try
{
FileStream file = File.OpenRead(filename);
if (file == null)
return Encoding.Default;
// Read the BOM
var bom = new byte[4];
file.Read(bom, 0, 4);
file.Dispose();
// Analyze the BOM
if (bom[0] == 0x2b && bom[1] == 0x2f && bom[2] == 0x76) return Encoding.UTF7;
if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf) return Encoding.UTF8;
if (bom[0] == 0xff && bom[1] == 0xfe) return Encoding.Unicode; //UTF-16LE
if (bom[0] == 0xfe && bom[1] == 0xff) return Encoding.BigEndianUnicode; //UTF-16BE
if (bom[0] == 0 && bom[1] == 0 && bom[2] == 0xfe && bom[3] == 0xff) return Encoding.UTF32;
return Encoding.Default;
}
catch
{
return Encoding.Default;
}
}
/// <summary>
/// Get the extension from the path, if possible
/// </summary>
/// <param name="path">Path to get extension from</param>
/// <returns>Extension, if possible</returns>
public static string GetNormalizedExtension(this string path)
{
// Check null or empty first
if (string.IsNullOrWhiteSpace(path))
return null;
// Get the extension from the path, if possible
string ext = Path.GetExtension(path)?.ToLowerInvariant();
// Check if the extension is null or empty
if (string.IsNullOrWhiteSpace(ext))
return null;
// Make sure that extensions are valid
ext = ext.TrimStart('.');
return ext;
}
/// <summary>
/// Get all empty folders within a root folder
/// </summary>
/// <param name="root">Root directory to parse</param>
/// <returns>IEumerable containing all directories that are empty, an empty enumerable if the root is empty, null otherwise</returns>
public static List<string> ListEmpty(this string root)
{
// Check null or empty first
if (string.IsNullOrEmpty(root))
return null;
// Then, check if the root exists
if (!Directory.Exists(root))
return null;
// If it does and it is empty, return a blank enumerable
if (Directory.EnumerateFileSystemEntries(root, "*", SearchOption.AllDirectories).Count() == 0)
return new List<string>();
// Otherwise, get the complete list
return Directory.EnumerateDirectories(root, "*", SearchOption.AllDirectories)
.Where(dir => Directory.EnumerateFileSystemEntries(dir, "*", SearchOption.AllDirectories).Count() == 0)
.ToList();
}
}
}

View File

@@ -71,7 +71,7 @@ namespace SabreTools.IO
public string GetOutputPath(string outDir, bool inplace)
{
// First, we need to ensure the output directory
outDir = DirectoryExtensions.Ensure(outDir);
outDir = outDir.Ensure();
// Check if we have a split path or not
bool splitpath = !string.IsNullOrWhiteSpace(ParentPath);

View File

@@ -1,141 +0,0 @@
using System.IO;
using SabreTools.Core;
namespace SabreTools.IO
{
/// <summary>
/// Extensions to Path functionality
/// </summary>
public static class PathExtensions
{
/// <summary>
/// Get the extension from the path, if possible
/// </summary>
/// <param name="path">Path to get extension from</param>
/// <returns>Extension, if possible</returns>
public static string GetNormalizedExtension(string path)
{
// Check null or empty first
if (string.IsNullOrWhiteSpace(path))
return null;
// Get the extension from the path, if possible
string ext = Path.GetExtension(path)?.ToLowerInvariant();
// Check if the extension is null or empty
if (string.IsNullOrWhiteSpace(ext))
return null;
// Make sure that extensions are valid
ext = ext.TrimStart('.');
return ext;
}
/// <summary>
/// Get a proper romba sub path
/// </summary>
/// <param name="hash">SHA-1 hash to get the path for</param>
/// <param name="depth">Positive value representing the depth of the depot</param>
/// <returns>Subfolder path for the given hash</returns>
public static string GetDepotPath(string hash, int depth)
{
// If the hash isn't the right size, then we return null
if (hash.Length != Constants.SHA1Length)
return null;
// Cap the depth between 0 and 20, for now
if (depth < 0)
depth = 0;
else if (depth > Constants.SHA1ZeroBytes.Length)
depth = Constants.SHA1ZeroBytes.Length;
// Loop through and generate the subdirectory
string path = string.Empty;
for (int i = 0; i < depth; i++)
{
path += hash.Substring(i * 2, 2) + Path.DirectorySeparatorChar;
}
// Now append the filename
path += $"{hash}.gz";
return path;
}
/// <summary>
/// Get if the given path has a valid DAT extension
/// </summary>
/// <param name="path">Path to check</param>
/// <returns>True if the extension is valid, false otherwise</returns>
public static bool HasValidArchiveExtension(string path)
{
// Get the extension from the path, if possible
string ext = GetNormalizedExtension(path);
// Check against the list of known archive extensions
switch (ext)
{
// Aaruformat
case "aaru":
case "aaruf":
case "aaruformat":
case "aif":
case "dicf":
// Archives
case "7z":
case "gz":
case "lzma":
case "rar":
case "rev":
case "r00":
case "r01":
case "tar":
case "tgz":
case "tlz":
case "zip":
case "zipx":
// CHD
case "chd":
return true;
default:
return false;
}
}
/// <summary>
/// Get if the given path has a valid DAT extension
/// </summary>
/// <param name="path">Path to check</param>
/// <returns>True if the extension is valid, false otherwise</returns>
public static bool HasValidDatExtension(string path)
{
// Get the extension from the path, if possible
string ext = GetNormalizedExtension(path);
// Check against the list of known DAT extensions
switch (ext)
{
case "csv":
case "dat":
case "json":
case "md5":
case "ripemd160":
case "sfv":
case "sha1":
case "sha256":
case "sha384":
case "sha512":
case "ssv":
case "tsv":
case "txt":
case "xml":
return true;
default:
return false;
}
}
}
}

View File

@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -8,65 +7,10 @@ using NaturalSort;
namespace SabreTools.IO
{
/// <summary>
/// Extensions to Directory functionality
/// Methods around path operations
/// </summary>
public static class DirectoryExtensions
public static class PathTool
{
/// <summary>
/// Cleans out the temporary directory
/// </summary>
/// <param name="dir">Name of the directory to clean out</param>
public static void Clean(string dir)
{
foreach (string file in Directory.EnumerateFiles(dir, "*", SearchOption.TopDirectoryOnly))
{
try
{
if (File.Exists(file))
File.Delete(file);
}
catch { }
}
foreach (string subdir in Directory.EnumerateDirectories(dir, "*", SearchOption.TopDirectoryOnly))
{
try
{
if (Directory.Exists(subdir))
Directory.Delete(subdir);
}
catch { }
}
}
/// <summary>
/// Ensure the output directory is a proper format and can be created
/// </summary>
/// <param name="dir">Directory to check</param>
/// <param name="create">True if the directory should be created, false otherwise (default)</param>
/// <param name="temp">True if this is a temp directory, false otherwise</param>
/// <returns>Full path to the directory</returns>
public static string Ensure(string dir, bool create = false, bool temp = false)
{
// If the output directory is invalid
if (string.IsNullOrWhiteSpace(dir))
{
if (temp)
dir = Path.GetTempPath();
else
dir = Environment.CurrentDirectory;
}
// Get the full path for the output directory
dir = Path.GetFullPath(dir);
// If we're creating the output folder, do so
if (create)
Directory.CreateDirectory(dir);
return dir;
}
/// <summary>
/// Retrieve a list of just directories from inputs
/// </summary>
@@ -222,26 +166,5 @@ namespace SabreTools.IO
// Return the new list
return infiles;
}
/// <summary>
/// Get all empty folders within a root folder
/// </summary>
/// <param name="root">Root directory to parse</param>
/// <returns>IEumerable containing all directories that are empty, an empty enumerable if the root is empty, null otherwise</returns>
public static List<string> ListEmpty(string root)
{
// Check if the root exists first
if (!Directory.Exists(root))
return null;
// If it does and it is empty, return a blank enumerable
if (Directory.EnumerateFileSystemEntries(root, "*", SearchOption.AllDirectories).Count() == 0)
return new List<string>();
// Otherwise, get the complete list
return Directory.EnumerateDirectories(root, "*", SearchOption.AllDirectories)
.Where(dir => Directory.EnumerateFileSystemEntries(dir, "*", SearchOption.AllDirectories).Count() == 0)
.ToList();
}
}
}

View File

@@ -87,7 +87,7 @@ namespace SabreTools.Logging
{
// Set and create the output
if (addDate)
Filename = $"{Path.GetFileNameWithoutExtension(filename)} ({DateTime.Now:yyyy-MM-dd HH-mm-ss}).{PathExtensions.GetNormalizedExtension(filename)}";
Filename = $"{Path.GetFileNameWithoutExtension(filename)} ({DateTime.Now:yyyy-MM-dd HH-mm-ss}).{filename.GetNormalizedExtension()}";
else
Filename = filename;
}

View File

@@ -128,7 +128,7 @@ Reset the internal state: reset();";
}
// Get only files from inputs
List<ParentablePath> datFilePaths = DirectoryExtensions.GetFilesOnly(command.Arguments);
List<ParentablePath> datFilePaths = PathTool.GetFilesOnly(command.Arguments);
// Assume there could be multiple
foreach (ParentablePath datFilePath in datFilePaths)

View File

@@ -46,7 +46,7 @@ The following systems have headers that this program can work with:
bool nostore = GetBoolean(features, NoStoreHeaderValue);
// Get only files from the inputs
List<ParentablePath> files = DirectoryExtensions.GetFilesOnly(Inputs);
List<ParentablePath> files = PathTool.GetFilesOnly(Inputs);
foreach (ParentablePath file in files)
{
DetectTransformStore(file.CurrentPath, OutputDir, nostore);

View File

@@ -41,7 +41,7 @@ The following systems have headers that this program can work with:
base.ProcessFeatures(features);
// Get only files from the inputs
List<ParentablePath> files = DirectoryExtensions.GetFilesOnly(Inputs);
List<ParentablePath> files = PathTool.GetFilesOnly(Inputs);
foreach (ParentablePath file in files)
{
RestoreHeader(file.CurrentPath, OutputDir);

View File

@@ -82,7 +82,7 @@ namespace SabreTools.Features
// Get a list of files from the input datfiles
var datfiles = GetList(features, DatListValue);
var datfilePaths = DirectoryExtensions.GetFilesOnly(datfiles);
var datfilePaths = PathTool.GetFilesOnly(datfiles);
// If we are in individual mode, process each DAT on their own, appending the DAT name to the output dir
if (GetBoolean(features, IndividualValue))

View File

@@ -48,7 +48,7 @@ namespace SabreTools.Features
return;
// Get only files from the inputs
List<ParentablePath> files = DirectoryExtensions.GetFilesOnly(Inputs, appendparent: true);
List<ParentablePath> files = PathTool.GetFilesOnly(Inputs, appendparent: true);
// Loop over the input files
foreach (ParentablePath file in files)

View File

@@ -149,8 +149,8 @@ namespace SabreTools.Features
updateFields = new List<Field>() { Field.DatItem_Name };
// Ensure we only have files in the inputs
List<ParentablePath> inputPaths = DirectoryExtensions.GetFilesOnly(Inputs, appendparent: true);
List<ParentablePath> basePaths = DirectoryExtensions.GetFilesOnly(GetList(features, BaseDatListValue));
List<ParentablePath> inputPaths = PathTool.GetFilesOnly(Inputs, appendparent: true);
List<ParentablePath> basePaths = PathTool.GetFilesOnly(GetList(features, BaseDatListValue));
// If we're in standard update mode, run through all of the inputs
if (updateMode == UpdateMode.None)

View File

@@ -43,7 +43,7 @@ namespace SabreTools.Features
// Get a list of files from the input datfiles
var datfiles = GetList(features, DatListValue);
var datfilePaths = DirectoryExtensions.GetFilesOnly(datfiles);
var datfilePaths = PathTool.GetFilesOnly(datfiles);
// Get feature flags
TreatAsFile asFiles = GetTreatAsFiles(features);