Enable nullability everywhere

This commit is contained in:
Matt Nadareski
2024-02-28 19:19:50 -05:00
parent 11d024bd16
commit 823a9ca7b7
145 changed files with 1545 additions and 1260 deletions

View File

@@ -2,7 +2,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using SabreTools.Core;
using SabreTools.DatFiles;
using SabreTools.DatItems;
@@ -33,16 +32,22 @@ namespace SabreTools.DatTools
/// <param name="inputs">List of inputs to use for renaming</param>
public static void ApplySuperDAT(DatFile datFile, List<ParentablePath> inputs)
{
List<string> keys = datFile.Items.Keys.ToList();
List<string> keys = [.. datFile.Items.Keys];
Parallel.ForEach(keys, Globals.ParallelOptions, key =>
{
ConcurrentList<DatItem> items = datFile.Items[key];
ConcurrentList<DatItem> newItems = new();
ConcurrentList<DatItem>? items = datFile.Items[key];
if (items == null)
return;
ConcurrentList<DatItem> newItems = [];
foreach (DatItem item in items)
{
DatItem newItem = item;
if (newItem.Source == null)
continue;
string filename = inputs[newItem.Source.Index].CurrentPath;
string rootpath = inputs[newItem.Source.Index].ParentPath;
string? rootpath = inputs[newItem.Source.Index].ParentPath;
if (!string.IsNullOrWhiteSpace(rootpath)
&& !rootpath.EndsWith(Path.DirectorySeparatorChar)
@@ -51,7 +56,7 @@ namespace SabreTools.DatTools
rootpath += Path.DirectorySeparatorChar.ToString();
}
filename = filename.Remove(0, rootpath.Length);
filename = filename.Remove(0, rootpath?.Length ?? 0);
newItem.Machine.Name = Path.GetDirectoryName(filename) + Path.DirectorySeparatorChar
+ Path.GetFileNameWithoutExtension(filename) + Path.DirectorySeparatorChar
+ newItem.Machine.Name;
@@ -91,12 +96,16 @@ namespace SabreTools.DatTools
// Then we do a hashwise comparison against the base DAT
Parallel.ForEach(intDat.Items.Keys, Globals.ParallelOptions, key =>
{
ConcurrentList<DatItem> datItems = intDat.Items[key];
ConcurrentList<DatItem> newDatItems = new();
ConcurrentList<DatItem>? datItems = intDat.Items[key];
if (datItems == null)
return;
ConcurrentList<DatItem> newDatItems = [];
foreach (DatItem datItem in datItems)
{
ConcurrentList<DatItem> dupes = datFile.Items.GetDuplicates(datItem, sorted: true);
DatItem newDatItem = datItem.Clone() as DatItem;
if (datItem.Clone() is not DatItem newDatItem)
continue;
// Replace fields from the first duplicate, if we have one
if (dupes.Count > 0)
@@ -121,13 +130,21 @@ namespace SabreTools.DatTools
// Then we do a namewise comparison against the base DAT
Parallel.ForEach(intDat.Items.Keys, Globals.ParallelOptions, key =>
{
ConcurrentList<DatItem> datItems = intDat.Items[key];
ConcurrentList<DatItem> newDatItems = new();
ConcurrentList<DatItem>? datItems = intDat.Items[key];
if (datItems == null)
return;
ConcurrentList<DatItem> newDatItems = [];
foreach (DatItem datItem in datItems)
{
DatItem newDatItem = datItem.Clone() as DatItem;
if (datFile.Items.ContainsKey(key) && datFile.Items[key].Count > 0)
Replacer.ReplaceFields(newDatItem.Machine, datFile.Items[key][0].Machine, machineFields, onlySame);
if (datItem.Clone() is not DatItem newDatItem)
continue;
if (!datFile.Items.TryGetValue(key, out var list) || list == null)
continue;
if (datFile.Items.ContainsKey(key) && list.Count > 0)
Replacer.ReplaceFields(newDatItem.Machine, list[0].Machine, machineFields, onlySame);
newDatItems.Add(newDatItem);
}
@@ -164,26 +181,30 @@ namespace SabreTools.DatTools
intDat.Items.BucketBy(ItemKey.CRC, DedupeType.Full);
// Then we compare against the base DAT
List<string> keys = intDat.Items.Keys.ToList();
List<string> keys = [.. intDat.Items.Keys];
Parallel.ForEach(keys, Globals.ParallelOptions, key =>
{
// Game Against uses game names
if (useGames)
{
// If the key is null, keep it
if (!intDat.Items.TryGetValue(key, out var intList) || intList == null)
return;
// If the base DAT doesn't contain the key, keep it
if (!datFile.Items.ContainsKey(key))
if (!datFile.Items.TryGetValue(key, out var list) || list == null)
return;
// If the number of items is different, then keep it
if (datFile.Items[key].Count != intDat.Items[key].Count)
if (list.Count != intList.Count)
return;
// Otherwise, compare by name and hash the remaining files
bool exactMatch = true;
foreach (DatItem item in intDat.Items[key])
foreach (DatItem item in intList)
{
// TODO: Make this granular to name as well
if (!datFile.Items[key].Contains(item))
if (!list.Contains(item))
{
exactMatch = false;
break;
@@ -198,8 +219,11 @@ namespace SabreTools.DatTools
// Standard Against uses hashes
else
{
ConcurrentList<DatItem> datItems = intDat.Items[key];
ConcurrentList<DatItem> keepDatItems = new();
ConcurrentList<DatItem>? datItems = intDat.Items[key];
if (datItems == null)
return;
ConcurrentList<DatItem> keepDatItems = [];
foreach (DatItem datItem in datItems)
{
if (!datFile.Items.HasDuplicates(datItem, true))
@@ -224,7 +248,7 @@ namespace SabreTools.DatTools
public static List<DatFile> DiffCascade(DatFile datFile, List<DatHeader> datHeaders)
{
// Create a list of DatData objects representing output files
List<DatFile> outDats = new();
List<DatFile> outDats = [];
// Ensure the current DatFile is sorted optimally
datFile.Items.BucketBy(ItemKey.CRC, DedupeType.None);
@@ -237,12 +261,12 @@ namespace SabreTools.DatTools
Parallel.For(0, datHeaders.Count, Globals.ParallelOptions, j =>
{
DatFile diffData = DatFile.Create(datHeaders[j]);
diffData.Items = new ItemDictionary();
diffData.Items = [];
FillWithSourceIndex(datFile, diffData, j);
outDatsArray[j] = diffData;
});
outDats = outDatsArray.ToList();
outDats = [.. outDatsArray];
watch.Stop();
return outDats;
@@ -283,7 +307,7 @@ namespace SabreTools.DatTools
dupeData.Header.FileName += post;
dupeData.Header.Name += post;
dupeData.Header.Description += post;
dupeData.Items = new ItemDictionary();
dupeData.Items = [];
watch.Stop();
@@ -303,8 +327,11 @@ namespace SabreTools.DatTools
{
if (item.DupeType.HasFlag(DupeType.External))
{
DatItem newrom = item.Clone() as DatItem;
newrom.Machine.Name += $" ({Path.GetFileNameWithoutExtension(inputs[item.Source.Index].CurrentPath)})";
if (item.Clone() is not DatItem newrom)
continue;
if (item.Source != null)
newrom.Machine.Name += $" ({Path.GetFileNameWithoutExtension(inputs[item.Source.Index].CurrentPath)})";
dupeData.Items.Add(key, newrom);
}
@@ -356,12 +383,12 @@ namespace SabreTools.DatTools
diffData.Header.FileName += innerpost;
diffData.Header.Name += innerpost;
diffData.Header.Description += innerpost;
diffData.Items = new ItemDictionary();
diffData.Items = [];
outDatsArray[j] = diffData;
});
// Create a list of DatData objects representing individual output files
List<DatFile> outDats = outDatsArray.ToList();
List<DatFile> outDats = [.. outDatsArray];
watch.Stop();
@@ -379,6 +406,9 @@ namespace SabreTools.DatTools
// Loop through and add the items correctly
foreach (DatItem item in items)
{
if (item.Source == null)
continue;
if (item.DupeType.HasFlag(DupeType.Internal) || item.DupeType == 0x00)
outDats[item.Source.Index].Items.Add(key, item);
}
@@ -386,7 +416,7 @@ namespace SabreTools.DatTools
watch.Stop();
return outDats.ToList();
return [.. outDats];
}
/// <summary>
@@ -424,7 +454,7 @@ namespace SabreTools.DatTools
outerDiffData.Header.FileName += post;
outerDiffData.Header.Name += post;
outerDiffData.Header.Description += post;
outerDiffData.Items = new ItemDictionary();
outerDiffData.Items = [];
watch.Stop();
@@ -444,8 +474,10 @@ namespace SabreTools.DatTools
{
if (item.DupeType.HasFlag(DupeType.Internal) || item.DupeType == 0x00)
{
DatItem newrom = item.Clone() as DatItem;
newrom.Machine.Name += $" ({Path.GetFileNameWithoutExtension(inputs[item.Source.Index].CurrentPath)})";
if (item.Clone() is not DatItem newrom || newrom.Source == null)
continue;
newrom.Machine.Name += $" ({Path.GetFileNameWithoutExtension(inputs[newrom.Source.Index].CurrentPath)})";
outerDiffData.Items.Add(key, newrom);
}
}
@@ -523,7 +555,7 @@ namespace SabreTools.DatTools
// Now remove the file dictionary from the source DAT
if (delete)
addFrom.Items = null;
addFrom.Items = [];
}
/// <summary>
@@ -546,7 +578,7 @@ namespace SabreTools.DatTools
foreach (DatItem item in items)
{
if (item.Source.Index == index)
if (item.Source != null && item.Source.Index == index)
indexDat.Items.Add(key, item);
}
});

View File

@@ -3,7 +3,6 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SabreTools.Core;
using SabreTools.DatFiles;
using SabreTools.DatItems;
@@ -87,7 +86,7 @@ namespace SabreTools.DatTools
totalSize = new FileInfo(basePath).Length;
logger.User(totalSize, currentSize);
string parentPath = Path.GetDirectoryName(Path.GetDirectoryName(basePath));
string? parentPath = Path.GetDirectoryName(Path.GetDirectoryName(basePath));
CheckFileForHashes(datFile, basePath, parentPath, asFiles, skipFileType, addBlanks, hashes);
logger.User(totalSize, totalSize, basePath);
}
@@ -109,7 +108,7 @@ namespace SabreTools.DatTools
private static void CheckFileForHashes(
DatFile datFile,
string item,
string basePath,
string? basePath,
TreatAsFile asFiles,
SkipFileType skipFileType,
bool addBlanks,
@@ -120,7 +119,7 @@ namespace SabreTools.DatTools
return;
// Initialize possible archive variables
BaseArchive archive = BaseArchive.Create(item);
BaseArchive? archive = BaseArchive.Create(item);
// Process archives according to flags
if (archive != null)
@@ -188,7 +187,7 @@ namespace SabreTools.DatTools
// Check the file as if it were in a depot
GZipArchive gzarc = new(item);
BaseFile baseFile = gzarc.GetTorrentGZFileInfo();
BaseFile? baseFile = gzarc.GetTorrentGZFileInfo();
// If the rom is valid, add it
if (baseFile != null && baseFile.Filename != null)
@@ -214,15 +213,18 @@ namespace SabreTools.DatTools
/// <param name="item">File to be added</param>
/// <param name="basePath">Path the represents the parent directory</param>
/// <param name="extracted">List of BaseFiles representing the internal files</param>
private static void ProcessArchive(DatFile datFile, string item, string basePath, List<BaseFile> extracted)
private static void ProcessArchive(DatFile datFile, string item, string? basePath, List<BaseFile> extracted)
{
// Get the parent path for all items
string parent = (Path.GetDirectoryName(Path.GetFullPath(item)) + Path.DirectorySeparatorChar).Remove(0, basePath.Length) + Path.GetFileNameWithoutExtension(item);
string parent = (Path.GetDirectoryName(Path.GetFullPath(item)) + Path.DirectorySeparatorChar).Remove(0, basePath?.Length ?? 0) + Path.GetFileNameWithoutExtension(item);
// First take care of the found items
Parallel.ForEach(extracted, Globals.ParallelOptions, baseFile =>
{
DatItem datItem = DatItem.Create(baseFile);
DatItem? datItem = DatItem.Create(baseFile);
if (datItem == null)
return;
ProcessFileHelper(datFile, item, datItem, basePath, parent);
});
}
@@ -234,12 +236,12 @@ namespace SabreTools.DatTools
/// <param name="item">File containing the blanks</param>
/// <param name="basePath">Path the represents the parent directory</param>
/// <param name="archive">BaseArchive to get blanks from</param>
private static void ProcessArchiveBlanks(DatFile datFile, string item, string basePath, BaseArchive archive)
private static void ProcessArchiveBlanks(DatFile datFile, string item, string? basePath, BaseArchive archive)
{
List<string> empties = new();
List<string> empties = [];
// Get the parent path for all items
string parent = (Path.GetDirectoryName(Path.GetFullPath(item)) + Path.DirectorySeparatorChar).Remove(0, basePath.Length) + Path.GetFileNameWithoutExtension(item);
string parent = (Path.GetDirectoryName(Path.GetFullPath(item)) + Path.DirectorySeparatorChar).Remove(0, basePath?.Length ?? 0) + Path.GetFileNameWithoutExtension(item);
// Now get all blank folders from the archive
if (archive != null)
@@ -258,13 +260,13 @@ namespace SabreTools.DatTools
/// </summary>
/// <param name="datFile">Current DatFile object to add to</param>
/// <param name="basePath">Path the represents the parent directory</param>
private static void ProcessDirectoryBlanks(DatFile datFile, string basePath)
private static void ProcessDirectoryBlanks(DatFile datFile, string? basePath)
{
// If we're in depot mode, we don't process blanks
if (datFile.Header.OutputDepot?.IsActive == true)
return;
List<string> empties = basePath.ListEmpty();
List<string> empties = basePath.ListEmpty() ?? [];
Parallel.ForEach(empties, Globals.ParallelOptions, dir =>
{
// Get the full path for the directory
@@ -277,15 +279,27 @@ namespace SabreTools.DatTools
// If we have a SuperDAT, we want anything that's not the base path as the game, and the file as the rom
if (datFile.Header.Type == "SuperDAT")
{
gamename = fulldir.Remove(0, basePath.Length + 1);
if (basePath != null)
gamename = fulldir.Remove(0, basePath.Length + 1);
else
gamename = fulldir;
romname = "_";
}
// Otherwise, we want just the top level folder as the game, and the file as everything else
else
{
gamename = fulldir.Remove(0, basePath.Length + 1).Split(Path.DirectorySeparatorChar)[0];
romname = Path.Combine(fulldir.Remove(0, basePath.Length + 1 + gamename.Length), "_");
if (basePath != null)
{
gamename = fulldir.Remove(0, basePath.Length + 1).Split(Path.DirectorySeparatorChar)[0];
romname = Path.Combine(fulldir.Remove(0, basePath.Length + 1 + gamename.Length), "_");
}
else
{
gamename = fulldir;
romname = Path.Combine(fulldir, "_");
}
}
// Sanitize the names
@@ -293,7 +307,7 @@ namespace SabreTools.DatTools
romname = romname.Trim(Path.DirectorySeparatorChar);
logger.Verbose($"Adding blank empty folder: {gamename}");
datFile.Items["null"].Add(new Rom(romname, gamename));
datFile.Items["null"]?.Add(new Rom(romname, gamename));
});
}
@@ -305,12 +319,13 @@ namespace SabreTools.DatTools
/// <param name="basePath">Path the represents the parent directory</param>
/// <param name="hashes">Hashes to include in the information</param>
/// <param name="asFiles">TreatAsFiles representing CHD and Archive scanning</param>
private static void ProcessFile(DatFile datFile, string item, string basePath, Hash hashes, TreatAsFile asFiles)
private static void ProcessFile(DatFile datFile, string item, string? basePath, Hash hashes, TreatAsFile asFiles)
{
logger.Verbose($"'{Path.GetFileName(item)}' treated like a file");
BaseFile baseFile = BaseFile.GetInfo(item, header: datFile.Header.HeaderSkipper, hashes: hashes, asFiles: asFiles);
DatItem datItem = DatItem.Create(baseFile);
ProcessFileHelper(datFile, item, datItem, basePath, string.Empty);
BaseFile? baseFile = BaseFile.GetInfo(item, header: datFile.Header.HeaderSkipper, hashes: hashes, asFiles: asFiles);
DatItem? datItem = DatItem.Create(baseFile);
if (datItem != null)
ProcessFileHelper(datFile, item, datItem, basePath, string.Empty);
}
/// <summary>
@@ -321,17 +336,17 @@ namespace SabreTools.DatTools
/// <param name="item">Rom data to be used to write to file</param>
/// <param name="basepath">Path the represents the parent directory</param>
/// <param name="parent">Parent game to be used</param>
private static void ProcessFileHelper(DatFile datFile, string item, DatItem datItem, string basepath, string parent)
private static void ProcessFileHelper(DatFile datFile, string item, DatItem datItem, string? basepath, string parent)
{
// If we didn't get an accepted parsed type somehow, cancel out
List<ItemType> parsed = new() { ItemType.Disk, ItemType.File, ItemType.Media, ItemType.Rom };
List<ItemType> parsed = [ItemType.Disk, ItemType.File, ItemType.Media, ItemType.Rom];
if (!parsed.Contains(datItem.ItemType))
return;
try
{
// If the basepath doesn't end with a directory separator, add it
if (!basepath.EndsWith(Path.DirectorySeparatorChar.ToString()))
if (basepath != null && !basepath.EndsWith(Path.DirectorySeparatorChar.ToString()))
basepath += Path.DirectorySeparatorChar.ToString();
// Make sure we have the full item path
@@ -361,10 +376,10 @@ namespace SabreTools.DatTools
/// <param name="item">Item name to use</param>
/// <param name="parent">Parent name to use</param>
/// <param name="basepath">Base path to use</param>
private static void SetDatItemInfo(DatFile datFile, DatItem datItem, string item, string parent, string basepath)
private static void SetDatItemInfo(DatFile datFile, DatItem datItem, string item, string parent, string? basepath)
{
// Get the data to be added as game and item names
string machineName, itemName;
string? machineName, itemName;
// If the parent is blank, then we have a non-archive file
if (string.IsNullOrWhiteSpace(parent))
@@ -372,15 +387,18 @@ namespace SabreTools.DatTools
// If we have a SuperDAT, we want anything that's not the base path as the game, and the file as the rom
if (datFile.Header.Type == "SuperDAT")
{
machineName = Path.GetDirectoryName(item.Remove(0, basepath.Length));
machineName = Path.GetDirectoryName(item.Remove(0, basepath?.Length ?? 0));
itemName = Path.GetFileName(item);
}
// Otherwise, we want just the top level folder as the game, and the file as everything else
else
{
machineName = item.Remove(0, basepath.Length).Split(Path.DirectorySeparatorChar)[0];
itemName = item.Remove(0, (Path.Combine(basepath, machineName).Length));
machineName = item.Remove(0, basepath?.Length ?? 0).Split(Path.DirectorySeparatorChar)[0];
if (basepath != null)
itemName = item.Remove(0, (Path.Combine(basepath, machineName).Length));
else
itemName = item.Remove(0, (machineName.Length));
}
}
@@ -403,7 +421,7 @@ namespace SabreTools.DatTools
}
// Sanitize the names
machineName = machineName.Trim(Path.DirectorySeparatorChar);
machineName = machineName?.Trim(Path.DirectorySeparatorChar);
itemName = itemName?.Trim(Path.DirectorySeparatorChar) ?? string.Empty;
if (!string.IsNullOrWhiteSpace(machineName) && string.IsNullOrWhiteSpace(itemName))

View File

@@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
using SabreTools.Core.Tools;
using SabreTools.DatFiles;
using SabreTools.DatItems;
@@ -130,7 +129,7 @@ namespace SabreTools.DatTools
return 0;
// Get the extension from the filename
string ext = filename.GetNormalizedExtension();
string? ext = filename.GetNormalizedExtension();
// Check if file exists
if (!File.Exists(filename))
@@ -232,7 +231,7 @@ namespace SabreTools.DatTools
else if (first.Contains("doscenter"))
return DatFormat.DOSCenter;
else if (first.Contains("#Name;Title;Emulator;CloneOf;Year;Manufacturer;Category;Players;Rotation;Control;Status;DisplayCount;DisplayType;AltRomname;AltTitle;Extra".ToLowerInvariant()))
else if (first.Contains("#Name;Title;Emulator;CloneOf;Year;Manufacturer;Category;Players;Rotation;Control;Status;DisplayCount;DisplayType;AltRomname;AltTitle;Extra", StringComparison.InvariantCultureIgnoreCase))
return DatFormat.AttractMode;
else
@@ -251,42 +250,49 @@ namespace SabreTools.DatTools
return string.Empty;
// Find the first line that's not whitespace or an XML comment
string line = sr.ReadLine().ToLowerInvariant().Trim();
bool inComment = line.StartsWith("<!--");
string? line = sr.ReadLine()?.ToLowerInvariant()?.Trim();
bool inComment = line?.StartsWith("<!--") ?? false;
while ((string.IsNullOrWhiteSpace(line) || inComment) && !sr.EndOfStream)
{
// Null lines should not happen
if (line == null)
{
line = sr.ReadLine()?.ToLowerInvariant()?.Trim();
continue;
}
// Self-contained comment lines
if (line.StartsWith("<!--") && line.EndsWith("-->"))
{
inComment = false;
line = sr.ReadLine().ToLowerInvariant().Trim();
line = sr.ReadLine()?.ToLowerInvariant()?.Trim();
}
// Start of block comments
else if (line.StartsWith("<!--"))
{
inComment = true;
line = sr.ReadLine().ToLowerInvariant().Trim();
line = sr.ReadLine()?.ToLowerInvariant()?.Trim();
}
// End of block comments
else if (inComment && line.EndsWith("-->"))
{
line = sr.ReadLine().ToLowerInvariant().Trim();
inComment = line.StartsWith("<!--");
line = sr.ReadLine()?.ToLowerInvariant()?.Trim();
inComment = line?.StartsWith("<!--") ?? false;
}
// Empty lines are just skipped
else if (string.IsNullOrWhiteSpace(line))
{
line = sr.ReadLine().ToLowerInvariant().Trim();
inComment |= line.StartsWith("<!--");
line = sr.ReadLine()?.ToLowerInvariant()?.Trim();
inComment |= line?.StartsWith("<!--") ?? false;
}
// In-comment lines
else if (inComment)
{
line = sr.ReadLine().ToLowerInvariant().Trim();
line = sr.ReadLine()?.ToLowerInvariant()?.Trim();
}
}
@@ -294,7 +300,7 @@ namespace SabreTools.DatTools
if (inComment)
return string.Empty;
return line;
return line ?? string.Empty;
}
}
}

View File

@@ -2,7 +2,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using SabreTools.Core;
using SabreTools.Core.Tools;
using SabreTools.DatFiles;
@@ -76,7 +75,7 @@ namespace SabreTools.DatTools
InternalStopwatch watch = new($"Rebuilding all files to {format}");
// Now loop through and get only directories from the input paths
List<string> directories = new();
List<string> directories = [];
Parallel.ForEach(inputs, Globals.ParallelOptions, input =>
{
// Add to the list if the input is a directory
@@ -108,10 +107,12 @@ namespace SabreTools.DatTools
logger.User($"Checking hash '{hash}'");
// Get the extension path for the hash
string subpath = Utilities.GetDepotPath(hash, datFile.Header.InputDepot.Depth);
string? subpath = Utilities.GetDepotPath(hash, datFile.Header.InputDepot?.Depth ?? 0);
if (subpath == null)
continue;
// Find the first depot that includes the hash
string foundpath = null;
string? foundpath = null;
foreach (string directory in directories)
{
if (System.IO.File.Exists(Path.Combine(directory, subpath)))
@@ -127,7 +128,7 @@ namespace SabreTools.DatTools
// If we have a path, we want to try to get the rom information
GZipArchive archive = new(foundpath);
BaseFile fileinfo = archive.GetTorrentGZFileInfo();
BaseFile? fileinfo = archive.GetTorrentGZFileInfo();
// If the file information is null, then we continue
if (fileinfo == null)
@@ -137,16 +138,17 @@ namespace SabreTools.DatTools
datFile.Items.BucketBy(ItemKey.SHA1, DedupeType.None);
// If there are no items in the hash, we continue
if (datFile.Items[hash] == null || datFile.Items[hash].Count == 0)
var items = datFile.Items[hash];
if (items == null || items.Count == 0)
continue;
// Otherwise, we rebuild that file to all locations that we need to
bool usedInternally;
if (datFile.Items[hash][0].ItemType == ItemType.Disk)
if (items[0].ItemType == ItemType.Disk)
usedInternally = RebuildIndividualFile(datFile, new Disk(fileinfo), foundpath, outDir, date, inverse, outputFormat, isZip: false);
else if (datFile.Items[hash][0].ItemType == ItemType.File)
else if (items[0].ItemType == ItemType.File)
usedInternally = RebuildIndividualFile(datFile, new DatItems.Formats.File(fileinfo), foundpath, outDir, date, inverse, outputFormat, isZip: false);
else if (datFile.Items[hash][0].ItemType == ItemType.Media)
else if (items[0].ItemType == ItemType.Media)
usedInternally = RebuildIndividualFile(datFile, new Media(fileinfo), foundpath, outDir, date, inverse, outputFormat, isZip: false);
else
usedInternally = RebuildIndividualFile(datFile, new Rom(fileinfo), foundpath, outDir, date, inverse, outputFormat, isZip: false);
@@ -284,7 +286,7 @@ namespace SabreTools.DatTools
bool usedExternally = false, usedInternally = false;
// Create an empty list of BaseFile for archive entries
List<BaseFile> entries = null;
List<BaseFile>? entries = null;
// Get the TGZ and TXZ status for later
GZipArchive tgz = new(file);
@@ -292,7 +294,7 @@ namespace SabreTools.DatTools
bool isSingleTorrent = tgz.IsTorrent() || txz.IsTorrent();
// Get the base archive first
BaseArchive archive = BaseArchive.Create(file);
BaseArchive? archive = BaseArchive.Create(file);
// Now get all extracted items from the archive
if (archive != null)
@@ -304,25 +306,31 @@ namespace SabreTools.DatTools
// If the entries list is null, we encountered an error or have a file and should scan externally
if (entries == null && System.IO.File.Exists(file))
{
BaseFile internalFileInfo = BaseFile.GetInfo(file, asFiles: asFiles);
BaseFile? internalFileInfo = BaseFile.GetInfo(file, asFiles: asFiles);
// Create the correct DatItem
DatItem internalDatItem;
if (internalFileInfo.Type == FileType.AaruFormat && !asFiles.HasFlag(TreatAsFile.AaruFormat))
DatItem? internalDatItem;
if (internalFileInfo == null)
internalDatItem = null;
else if (internalFileInfo.Type == FileType.AaruFormat && !asFiles.HasFlag(TreatAsFile.AaruFormat))
internalDatItem = new Media(internalFileInfo);
else if (internalFileInfo.Type == FileType.CHD && !asFiles.HasFlag(TreatAsFile.CHD))
internalDatItem = new Disk(internalFileInfo);
else
internalDatItem = new Rom(internalFileInfo);
usedExternally = RebuildIndividualFile(datFile, internalDatItem, file, outDir, date, inverse, outputFormat);
if (internalDatItem != null)
usedExternally = RebuildIndividualFile(datFile, internalDatItem, file, outDir, date, inverse, outputFormat);
}
// Otherwise, loop through the entries and try to match
else
else if (entries != null)
{
foreach (BaseFile entry in entries)
{
DatItem internalDatItem = DatItem.Create(entry);
DatItem? internalDatItem = DatItem.Create(entry);
if (internalDatItem == null)
continue;
usedInternally |= RebuildIndividualFile(datFile, internalDatItem, file, outDir, date, inverse, outputFormat, !isSingleTorrent /* isZip */);
}
}
@@ -364,18 +372,18 @@ namespace SabreTools.DatTools
}
// If we have a Disk, File, or Media, change it into a Rom for later use
if (datItem.ItemType == ItemType.Disk)
datItem = (datItem as Disk).ConvertToRom();
else if (datItem.ItemType == ItemType.File)
datItem = (datItem as DatItems.Formats.File).ConvertToRom();
else if (datItem.ItemType == ItemType.Media)
datItem = (datItem as Media).ConvertToRom();
if (datItem is Disk disk)
datItem = disk.ConvertToRom();
else if (datItem is DatItems.Formats.File fileItem)
datItem = fileItem.ConvertToRom();
else if (datItem is Media media)
datItem = media.ConvertToRom();
// Prepopluate a key string
string crc = (datItem as Rom).CRC ?? string.Empty;
string crc = (datItem as Rom)!.CRC ?? string.Empty;
// Try to get the stream for the file
if (!GetFileStream(datItem, file, isZip, out Stream fileStream))
if (!GetFileStream(datItem, file, isZip, out Stream? fileStream))
return false;
// If either we have duplicates or we're filtering
@@ -403,17 +411,22 @@ namespace SabreTools.DatTools
// Now loop through the list and rebuild accordingly
foreach (DatItem item in dupes)
{
// If we don't have a proper machine
if (item.Machine?.Name == null || !datFile.Items.ContainsKey(item.Machine.Name))
continue;
// If we should check for the items in the machine
if (shouldCheck && datFile.Items[item.Machine.Name].Count > 1)
var items = datFile.Items[item.Machine.Name];
if (shouldCheck && items!.Count > 1)
outputFormat = OutputFormat.Folder;
else if (shouldCheck && datFile.Items[item.Machine.Name].Count == 1)
else if (shouldCheck && items!.Count == 1)
outputFormat = OutputFormat.ParentFolder;
// Get the output archive, if possible
Folder outputArchive = GetPreconfiguredFolder(datFile, date, outputFormat);
Folder? outputArchive = GetPreconfiguredFolder(datFile, date, outputFormat);
// Now rebuild to the output file
outputArchive.Write(fileStream, outDir, (item as Rom).ConvertToBaseFile());
outputArchive!.Write(fileStream, outDir, (item as Rom)!.ConvertToBaseFile());
}
// Close the input stream
@@ -451,12 +464,12 @@ namespace SabreTools.DatTools
datItem.SetName($"{datItem.GetName()}_{crc}");
// Get the output archive, if possible
Folder outputArchive = GetPreconfiguredFolder(datFile, date, outputFormat);
Folder? outputArchive = GetPreconfiguredFolder(datFile, date, outputFormat);
// Now rebuild to the output file
bool eitherSuccess = false;
eitherSuccess |= outputArchive.Write(transformStream, outDir, (item as Rom).ConvertToBaseFile());
eitherSuccess |= outputArchive.Write(fileStream, outDir, (datItem as Rom).ConvertToBaseFile());
eitherSuccess |= outputArchive!.Write(transformStream, outDir, (item as Rom)!.ConvertToBaseFile());
eitherSuccess |= outputArchive.Write(fileStream, outDir, (datItem as Rom)!.ConvertToBaseFile());
// Now add the success of either rebuild
rebuilt &= eitherSuccess;
@@ -484,7 +497,7 @@ namespace SabreTools.DatTools
/// <param name="inverse">True if the DAT should be used as a filter instead of a template, false otherwise</param>
/// <param name="dupes">Output list of duplicate items to rebuild to</param>
/// <returns>True if the item should be rebuilt, false otherwise</returns>
private static bool ShouldRebuild(DatFile datFile, DatItem datItem, Stream stream, bool inverse, out ConcurrentList<DatItem> dupes)
private static bool ShouldRebuild(DatFile datFile, DatItem datItem, Stream? stream, bool inverse, out ConcurrentList<DatItem> dupes)
{
// Find if the file has duplicates in the DAT
dupes = datFile.Items.GetDuplicates(datItem);
@@ -505,7 +518,7 @@ namespace SabreTools.DatTools
// If we have no duplicates and we're filtering
else if (!hasDuplicates && inverse)
{
string machinename = null;
string? machinename = null;
// Get the item from the current file
Rom item = new(BaseFile.GetInfo(stream, keepReadOpen: true));
@@ -544,20 +557,22 @@ namespace SabreTools.DatTools
{
// If we have a very specific TGZ->TGZ case, just copy it accordingly
GZipArchive tgz = new(file);
BaseFile tgzRom = tgz.GetTorrentGZFileInfo();
BaseFile? tgzRom = tgz.GetTorrentGZFileInfo();
if (isZip == false && tgzRom != null && (outputFormat == OutputFormat.TorrentGzip || outputFormat == OutputFormat.TorrentGzipRomba))
{
logger.User($"Matches found for '{Path.GetFileName(datItem.GetName() ?? string.Empty)}', rebuilding accordingly...");
// Get the proper output path
string sha1 = (datItem as Rom).SHA1 ?? string.Empty;
string sha1 = (datItem as Rom)!.SHA1 ?? string.Empty;
if (outputFormat == OutputFormat.TorrentGzipRomba)
outDir = Path.Combine(outDir, Utilities.GetDepotPath(sha1, datFile.Header.OutputDepot.Depth));
outDir = Path.Combine(outDir, Utilities.GetDepotPath(sha1, datFile.Header.OutputDepot?.Depth ?? 0) ?? string.Empty);
else
outDir = Path.Combine(outDir, sha1 + ".gz");
// Make sure the output folder is created
Directory.CreateDirectory(Path.GetDirectoryName(outDir));
string? dir = Path.GetDirectoryName(outDir);
if (dir != null)
Directory.CreateDirectory(dir);
// Now copy the file over
try
@@ -588,20 +603,22 @@ namespace SabreTools.DatTools
{
// If we have a very specific TGZ->TGZ case, just copy it accordingly
XZArchive txz = new(file);
BaseFile txzRom = txz.GetTorrentXZFileInfo();
BaseFile? txzRom = txz.GetTorrentXZFileInfo();
if (isZip == false && txzRom != null && (outputFormat == OutputFormat.TorrentXZ || outputFormat == OutputFormat.TorrentXZRomba))
{
logger.User($"Matches found for '{Path.GetFileName(datItem.GetName() ?? string.Empty)}', rebuilding accordingly...");
// Get the proper output path
string sha1 = (datItem as Rom).SHA1 ?? string.Empty;
string sha1 = (datItem as Rom)!.SHA1 ?? string.Empty;
if (outputFormat == OutputFormat.TorrentXZRomba)
outDir = Path.Combine(outDir, Utilities.GetDepotPath(sha1, datFile.Header.OutputDepot.Depth)).Replace(".gz", ".xz");
outDir = Path.Combine(outDir, Utilities.GetDepotPath(sha1, datFile.Header.OutputDepot?.Depth ?? 0) ?? string.Empty).Replace(".gz", ".xz");
else
outDir = Path.Combine(outDir, sha1 + ".xz");
// Make sure the output folder is created
Directory.CreateDirectory(Path.GetDirectoryName(outDir));
string? dir = Path.GetDirectoryName(outDir);
if (dir != null)
Directory.CreateDirectory(dir);
// Now copy the file over
try
@@ -626,7 +643,7 @@ namespace SabreTools.DatTools
/// <param name="isZip">Non-null if the input file is an archive</param>
/// <param name="stream">Output stream representing the opened file</param>
/// <returns>True if the stream opening succeeded, false otherwise</returns>
private static bool GetFileStream(DatItem datItem, string file, bool? isZip, out Stream stream)
private static bool GetFileStream(DatItem datItem, string file, bool? isZip, out Stream? stream)
{
// Get a generic stream for the file
stream = null;
@@ -634,7 +651,7 @@ namespace SabreTools.DatTools
// If we have a zipfile, extract the stream to memory
if (isZip != null)
{
BaseArchive archive = BaseArchive.Create(file);
BaseArchive? archive = BaseArchive.Create(file);
if (archive != null)
(stream, _) = archive.CopyToStream(datItem.GetName() ?? datItem.ItemType.ToString());
}
@@ -678,17 +695,17 @@ namespace SabreTools.DatTools
/// <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>
/// <returns>Folder configured with proper flags</returns>
private static Folder GetPreconfiguredFolder(DatFile datFile, bool date, OutputFormat outputFormat)
private static Folder? GetPreconfiguredFolder(DatFile datFile, bool date, OutputFormat outputFormat)
{
Folder outputArchive = Folder.Create(outputFormat);
Folder? outputArchive = Folder.Create(outputFormat);
if (outputArchive is BaseArchive baseArchive && date)
baseArchive.UseDates = date;
// Set the depth fields where appropriate
if (outputArchive is GZipArchive gzipArchive)
gzipArchive.Depth = datFile.Header.OutputDepot.Depth;
gzipArchive.Depth = datFile.Header.OutputDepot?.Depth ?? 0;
else if (outputArchive is XZArchive xzArchive)
xzArchive.Depth = datFile.Header.OutputDepot.Depth;
xzArchive.Depth = datFile.Header.OutputDepot?.Depth ?? 0;
return outputArchive;
}
@@ -698,7 +715,7 @@ namespace SabreTools.DatTools
/// </summary>
/// <param name="itemType">OutputFormat to get value from</param>
/// <returns>String value corresponding to the OutputFormat</returns>
private static string FromOutputFormat(OutputFormat itemType)
private static string? FromOutputFormat(OutputFormat itemType)
{
return itemType switch
{

View File

@@ -20,7 +20,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="SabreTools.IO" Version="1.2.0" />
<PackageReference Include="SabreTools.IO" Version="1.3.0" />
</ItemGroup>
</Project>

View File

@@ -4,14 +4,13 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using NaturalSort;
using SabreTools.Core;
using SabreTools.DatFiles;
using SabreTools.DatItems;
using SabreTools.DatItems.Formats;
using SabreTools.IO;
using SabreTools.Logging;
using NaturalSort;
namespace SabreTools.DatTools
{
@@ -37,7 +36,7 @@ namespace SabreTools.DatTools
/// <param name="extA">List of extensions to split on (first DAT)</param>
/// <param name="extB">List of extensions to split on (second DAT)</param>
/// <returns>Extension Set A and Extension Set B DatFiles</returns>
public static (DatFile extADat, DatFile extBDat) SplitByExtension(DatFile datFile, List<string> extA, List<string> extB)
public static (DatFile? extADat, DatFile? extBDat) SplitByExtension(DatFile datFile, List<string> extA, List<string> extB)
{
// If roms is empty, return false
if (datFile.Items.TotalCount == 0)
@@ -66,7 +65,10 @@ namespace SabreTools.DatTools
// Now separate the roms accordingly
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
{
ConcurrentList<DatItem> items = datFile.Items[key];
ConcurrentList<DatItem>? items = datFile.Items[key];
if (items == null)
return;
foreach (DatItem item in items)
{
if (newExtA.Contains((item.GetName() ?? string.Empty).GetNormalizedExtension()))
@@ -101,7 +103,7 @@ namespace SabreTools.DatTools
InternalStopwatch watch = new($"Splitting DAT by best available hashes");
// Create the set of field-to-dat mappings
Dictionary<DatItemField, DatFile> fieldDats = new();
Dictionary<DatItemField, DatFile> fieldDats = [];
// TODO: Can this be made into a loop?
fieldDats[DatItemField.Status] = DatFile.Create(datFile.Header.CloneStandard());
@@ -147,7 +149,10 @@ namespace SabreTools.DatTools
// Now populate each of the DAT objects in turn
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
{
ConcurrentList<DatItem> items = datFile.Items[key];
ConcurrentList<DatItem>? items = datFile.Items[key];
if (items == null)
return;
foreach (DatItem item in items)
{
// If the file is not a Disk, Media, or Rom, continue
@@ -155,49 +160,49 @@ namespace SabreTools.DatTools
return;
// If the file is a nodump
if ((item.ItemType == ItemType.Rom && (item as Rom).ItemStatus == ItemStatus.Nodump)
|| (item.ItemType == ItemType.Disk && (item as Disk).ItemStatus == ItemStatus.Nodump))
if ((item.ItemType == ItemType.Rom && (item as Rom)!.ItemStatus == ItemStatus.Nodump)
|| (item.ItemType == ItemType.Disk && (item as Disk)!.ItemStatus == ItemStatus.Nodump))
{
fieldDats[DatItemField.Status].Items.Add(key, item);
}
// If the file has a SHA-512
else if ((item.ItemType == ItemType.Rom && !string.IsNullOrWhiteSpace((item as Rom).SHA512)))
else if ((item.ItemType == ItemType.Rom && !string.IsNullOrWhiteSpace((item as Rom)!.SHA512)))
{
fieldDats[DatItemField.SHA512].Items.Add(key, item);
}
// If the file has a SHA-384
else if ((item.ItemType == ItemType.Rom && !string.IsNullOrWhiteSpace((item as Rom).SHA384)))
else if ((item.ItemType == ItemType.Rom && !string.IsNullOrWhiteSpace((item as Rom)!.SHA384)))
{
fieldDats[DatItemField.SHA384].Items.Add(key, item);
}
// If the file has a SHA-256
else if ((item.ItemType == ItemType.Media && !string.IsNullOrWhiteSpace((item as Media).SHA256))
|| (item.ItemType == ItemType.Rom && !string.IsNullOrWhiteSpace((item as Rom).SHA256)))
else if ((item.ItemType == ItemType.Media && !string.IsNullOrWhiteSpace((item as Media)!.SHA256))
|| (item.ItemType == ItemType.Rom && !string.IsNullOrWhiteSpace((item as Rom)!.SHA256)))
{
fieldDats[DatItemField.SHA256].Items.Add(key, item);
}
// If the file has a SHA-1
else if ((item.ItemType == ItemType.Disk && !string.IsNullOrWhiteSpace((item as Disk).SHA1))
|| (item.ItemType == ItemType.Media && !string.IsNullOrWhiteSpace((item as Media).SHA1))
|| (item.ItemType == ItemType.Rom && !string.IsNullOrWhiteSpace((item as Rom).SHA1)))
else if ((item.ItemType == ItemType.Disk && !string.IsNullOrWhiteSpace((item as Disk)!.SHA1))
|| (item.ItemType == ItemType.Media && !string.IsNullOrWhiteSpace((item as Media)!.SHA1))
|| (item.ItemType == ItemType.Rom && !string.IsNullOrWhiteSpace((item as Rom)!.SHA1)))
{
fieldDats[DatItemField.SHA1].Items.Add(key, item);
}
// If the file has an MD5
else if ((item.ItemType == ItemType.Disk && !string.IsNullOrWhiteSpace((item as Disk).MD5))
|| (item.ItemType == ItemType.Media && !string.IsNullOrWhiteSpace((item as Media).MD5))
|| (item.ItemType == ItemType.Rom && !string.IsNullOrWhiteSpace((item as Rom).MD5)))
else if ((item.ItemType == ItemType.Disk && !string.IsNullOrWhiteSpace((item as Disk)!.MD5))
|| (item.ItemType == ItemType.Media && !string.IsNullOrWhiteSpace((item as Media)!.MD5))
|| (item.ItemType == ItemType.Rom && !string.IsNullOrWhiteSpace((item as Rom)!.MD5)))
{
fieldDats[DatItemField.MD5].Items.Add(key, item);
}
// If the file has a CRC
else if ((item.ItemType == ItemType.Rom && !string.IsNullOrWhiteSpace((item as Rom).CRC)))
else if ((item.ItemType == ItemType.Rom && !string.IsNullOrWhiteSpace((item as Rom)!.CRC)))
{
fieldDats[DatItemField.CRC].Items.Add(key, item);
}
@@ -233,7 +238,7 @@ namespace SabreTools.DatTools
tempDat.Header.Name = null;
// Sort the input keys
List<string> keys = datFile.Items.Keys.ToList();
List<string> keys = [.. datFile.Items.Keys];
keys.Sort(SplitByLevelSort);
// Then, we loop over the games
@@ -248,7 +253,10 @@ namespace SabreTools.DatTools
}
// Clean the input list and set all games to be pathless
ConcurrentList<DatItem> items = datFile.Items[key];
ConcurrentList<DatItem>? items = datFile.Items[key];
if (items == null)
return;
items.ForEach(item => item.Machine.Name = Path.GetFileName(item.Machine.Name));
items.ForEach(item => item.Machine.Description = Path.GetFileName(item.Machine.Description));
@@ -292,8 +300,8 @@ namespace SabreTools.DatTools
private static void SplitByLevelHelper(DatFile datFile, DatFile newDatFile, string outDir, bool shortname, bool restore)
{
// Get the name from the DAT to use separately
string name = newDatFile.Header.Name;
string expName = name.Replace("/", " - ").Replace("\\", " - ");
string? name = newDatFile.Header.Name;
string? expName = name?.Replace("/", " - ")?.Replace("\\", " - ");
// Now set the new output values
newDatFile.Header.FileName = WebUtility.HtmlDecode(string.IsNullOrWhiteSpace(name)
@@ -336,7 +344,10 @@ namespace SabreTools.DatTools
// Now populate each of the DAT objects in turn
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
{
ConcurrentList<DatItem> items = datFile.Items[key];
ConcurrentList<DatItem>? items = datFile.Items[key];
if (items == null)
return;
foreach (DatItem item in items)
{
// If the file is not a Rom, it automatically goes in the "lesser" dat
@@ -344,15 +355,15 @@ namespace SabreTools.DatTools
lessThan.Items.Add(key, item);
// If the file is a Rom and has no size, put it in the "lesser" dat
else if (item.ItemType == ItemType.Rom && (item as Rom).Size == null)
else if (item.ItemType == ItemType.Rom && (item as Rom)!.Size == null)
lessThan.Items.Add(key, item);
// If the file is a Rom and less than the radix, put it in the "lesser" dat
else if (item.ItemType == ItemType.Rom && (item as Rom).Size < radix)
else if (item.ItemType == ItemType.Rom && (item as Rom)!.Size < radix)
lessThan.Items.Add(key, item);
// If the file is a Rom and greater than or equal to the radix, put it in the "greater" dat
else if (item.ItemType == ItemType.Rom && (item as Rom).Size >= radix)
else if (item.ItemType == ItemType.Rom && (item as Rom)!.Size >= radix)
greaterThan.Items.Add(key, item);
}
});
@@ -372,7 +383,7 @@ namespace SabreTools.DatTools
{
// If the size is invalid, just return
if (chunkSize <= 0)
return new List<DatFile>();
return [];
// Create each of the respective output DATs
InternalStopwatch watch = new($"Splitting DAT by total size");
@@ -384,7 +395,7 @@ namespace SabreTools.DatTools
var keys = datFile.Items.SortedKeys;
// Get the output list
List<DatFile> datFiles = new();
List<DatFile> datFiles = [];
// Initialize everything
long currentSize = 0;
@@ -462,16 +473,16 @@ namespace SabreTools.DatTools
InternalStopwatch watch = new($"Splitting DAT by item type");
// Create the set of type-to-dat mappings
Dictionary<ItemType, DatFile> typeDats = new();
Dictionary<ItemType, DatFile> typeDats = [];
// We only care about a subset of types
List<ItemType> outputTypes = new()
{
List<ItemType> outputTypes =
[
ItemType.Disk,
ItemType.Media,
ItemType.Rom,
ItemType.Sample,
};
];
// Setup all of the DatFiles
foreach (ItemType itemType in outputTypes)

View File

@@ -4,7 +4,6 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using SabreTools.Core;
using SabreTools.DatFiles;
using SabreTools.IO;
@@ -16,7 +15,7 @@ namespace SabreTools.DatTools
/// <summary>
/// Helper methods for dealing with DatFile statistics
/// </summary>
public class Statistics
{
#region Logging
@@ -37,7 +36,7 @@ namespace SabreTools.DatTools
public static List<DatStatistics> CalculateStatistics(List<string> inputs, bool single, bool throwOnError = false)
{
// Create the output list
List<DatStatistics> stats = new();
List<DatStatistics> stats = [];
// Make sure we have all files and then order them
List<ParentablePath> files = PathTool.GetFilesOnly(inputs);
@@ -49,17 +48,17 @@ namespace SabreTools.DatTools
// Init total
DatStatistics totalStats = new()
{
Statistics = new ItemDictionary(),
Statistics = [],
DisplayName = "DIR: All DATs",
MachineCount = 0,
IsDirectory = true,
};
// Init directory-level variables
string lastdir = null;
string? lastdir = null;
DatStatistics dirStats = new()
{
Statistics = new ItemDictionary(),
Statistics = [],
MachineCount = 0,
IsDirectory = true,
};
@@ -68,7 +67,7 @@ namespace SabreTools.DatTools
foreach (ParentablePath file in files)
{
// Get the directory for the current file
string thisdir = Path.GetDirectoryName(file.CurrentPath);
string? thisdir = Path.GetDirectoryName(file.CurrentPath);
// If we don't have the first file and the directory has changed, show the previous directory stats and reset
if (lastdir != null && thisdir != lastdir && single)
@@ -78,7 +77,7 @@ namespace SabreTools.DatTools
stats.Add(dirStats);
dirStats = new DatStatistics
{
Statistics = new ItemDictionary(),
Statistics = [],
MachineCount = 0,
IsDirectory = true,
};
@@ -86,7 +85,7 @@ namespace SabreTools.DatTools
InternalStopwatch watch = new($"Collecting statistics for '{file.CurrentPath}'");
List<string> machines = new();
List<string> machines = [];
DatFile datdata = Parser.CreateAndParse(file.CurrentPath, statsOnly: true, throwOnError: throwOnError);
// Add single DAT stats (if asked)
@@ -208,7 +207,7 @@ namespace SabreTools.DatTools
/// <returns>Dictionary of output formats mapped to file names</returns>
private static Dictionary<StatReportFormat, string> CreateOutStatsNames(string outDir, StatReportFormat statDatFormat, string reportName, bool overwrite = true)
{
Dictionary<StatReportFormat, string> output = new();
Dictionary<StatReportFormat, string> output = [];
// First try to create the output directory if we need to
if (!Directory.Exists(outDir))

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SabreTools.Core;
using SabreTools.Core.Tools;
using SabreTools.DatFiles;
@@ -40,7 +39,7 @@ namespace SabreTools.DatTools
InternalStopwatch watch = new("Verifying all from supplied depots");
// Now loop through and get only directories from the input paths
List<string> directories = new();
List<string> directories = [];
foreach (string input in inputs)
{
// Add to the list if the input is a directory
@@ -69,10 +68,12 @@ namespace SabreTools.DatTools
logger.User($"Checking hash '{hash}'");
// Get the extension path for the hash
string subpath = Utilities.GetDepotPath(hash, datFile.Header.InputDepot.Depth);
string? subpath = Utilities.GetDepotPath(hash, datFile.Header.InputDepot?.Depth ?? 0);
if (subpath == null)
continue;
// Find the first depot that includes the hash
string foundpath = null;
string? foundpath = null;
foreach (string directory in directories)
{
if (System.IO.File.Exists(Path.Combine(directory, subpath)))
@@ -88,7 +89,7 @@ namespace SabreTools.DatTools
// If we have a path, we want to try to get the rom information
GZipArchive tgz = new(foundpath);
BaseFile fileinfo = tgz.GetTorrentGZFileInfo();
BaseFile? fileinfo = tgz.GetTorrentGZFileInfo();
// If the file information is null, then we continue
if (fileinfo == null)
@@ -133,11 +134,14 @@ namespace SabreTools.DatTools
var keys = datFile.Items.SortedKeys.ToList();
foreach (string key in keys)
{
ConcurrentList<DatItem> items = datFile.Items[key];
ConcurrentList<DatItem>? items = datFile.Items[key];
if (items == null)
continue;
for (int i = 0; i < items.Count; i++)
{
// Unmatched items will have a source ID of int.MaxValue, remove all others
if (items[i].Source.Index != int.MaxValue)
if (items[i].Source?.Index != int.MaxValue)
items[i].Remove = true;
}

View File

@@ -118,7 +118,7 @@ namespace SabreTools.DatTools
var statsList = new List<DatStatistics>
{
new DatStatistics
new()
{
Statistics = datFile.Items,
DisplayName = datFile.Header.FileName,
@@ -127,7 +127,7 @@ namespace SabreTools.DatTools
},
};
var consoleOutput = BaseReport.Create(StatReportFormat.None, statsList);
consoleOutput.WriteToFile(null, true, true);
consoleOutput!.WriteToFile(null, true, true);
}
/// <summary>