Cleanup and overhaul (#21)

* Syntax cleanup

* More minor cleanup, use Linq

* Fix broken features by using correct values

* Feature flags the same

* Features are modular

* No AlphaFS, more .NET versions

* Fix appveyor

* Put back identifiers, for some reason

* String interpolation, modernization

* Better use of GetField

* XmlTextWriter to remove possible issues

* Fix header for OpenMSX
This commit is contained in:
Matt Nadareski
2020-06-10 22:37:19 -07:00
committed by GitHub
parent f01e47444c
commit 4ad77d6be6
75 changed files with 6945 additions and 7249 deletions

View File

@@ -1,15 +1,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SabreTools.Library.Data;
using SabreTools.Library.DatFiles;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
#endif
using NaturalSort;
using System.Runtime.CompilerServices;
namespace SabreTools.Library.DatItems
{
@@ -564,6 +562,189 @@ namespace SabreTools.Library.DatItems
#region Instance Methods
#region Accessors
/// <summary>
/// Get the value of that field as a string, if possible
/// </summary>
public string GetField(Field field, bool[] excludeFields)
{
// If the field is to be excluded, return empty string
if (excludeFields[(int)field])
return string.Empty;
switch (field)
{
case Field.Name:
return this.Name;
case Field.PartName:
return this.PartName;
case Field.PartInterface:
return this.PartInterface;
case Field.Features:
return string.Join(", ", this.Features.Select(f => $"{f.Item1}={f.Item2}"));
case Field.AreaName:
return this.AreaName;
case Field.AreaSize:
return this.AreaSize?.ToString() ?? string.Empty;
case Field.MachineName:
return this.MachineName;
case Field.Comment:
return this.Comment;
case Field.Description:
return this.MachineDescription;
case Field.Year:
return this.Year;
case Field.Manufacturer:
return this.Manufacturer;
case Field.Publisher:
return this.Publisher;
case Field.RomOf:
return this.RomOf;
case Field.CloneOf:
return this.CloneOf;
case Field.SampleOf:
return this.SampleOf;
case Field.Supported:
return this.Supported?.ToString() ?? string.Empty;
case Field.SourceFile:
return this.SourceFile;
case Field.Runnable:
return this.Runnable?.ToString() ?? string.Empty;
case Field.Board:
return this.Board;
case Field.RebuildTo:
return this.RebuildTo;
case Field.Devices:
return string.Join(", ", this.Devices);
case Field.SlotOptions:
return string.Join(", ", this.SlotOptions);
case Field.Infos:
return string.Join(", ", this.Infos.Select(i => $"{i.Item1}={i.Item2}"));
case Field.MachineType:
return this.MachineType.ToString();
case Field.Default:
if (ItemType == ItemType.BiosSet)
return (this as BiosSet).Default?.ToString() ?? string.Empty;
else if (ItemType == ItemType.Release)
return (this as Release).Default?.ToString() ?? string.Empty;
break;
case Field.BiosDescription:
if (ItemType == ItemType.BiosSet)
return (this as BiosSet).Description;
break;
case Field.MD5:
if (ItemType == ItemType.Disk)
return (this as Disk).MD5;
else if (ItemType == ItemType.Rom)
return (this as Rom).MD5;
break;
case Field.RIPEMD160:
if (ItemType == ItemType.Disk)
return (this as Disk).RIPEMD160;
else if (ItemType == ItemType.Rom)
return (this as Rom).RIPEMD160;
break;
case Field.SHA1:
if (ItemType == ItemType.Disk)
return (this as Disk).SHA1;
else if (ItemType == ItemType.Rom)
return (this as Rom).SHA1;
break;
case Field.SHA256:
if (ItemType == ItemType.Disk)
return (this as Disk).SHA256;
else if (ItemType == ItemType.Rom)
return (this as Rom).SHA256;
break;
case Field.SHA384:
if (ItemType == ItemType.Disk)
return (this as Disk).SHA384;
else if (ItemType == ItemType.Rom)
return (this as Rom).SHA384;
break;
case Field.SHA512:
if (ItemType == ItemType.Disk)
return (this as Disk).SHA512;
else if (ItemType == ItemType.Rom)
return (this as Rom).SHA512;
break;
case Field.Merge:
if (ItemType == ItemType.Disk)
return (this as Disk).MergeTag;
else if (ItemType == ItemType.Rom)
return (this as Rom).MergeTag;
break;
case Field.Region:
if (ItemType == ItemType.Disk)
return (this as Disk).Region;
else if (ItemType == ItemType.Release)
return (this as Release).Region;
else if (ItemType == ItemType.Rom)
return (this as Rom).Region;
break;
case Field.Index:
if (ItemType == ItemType.Disk)
return (this as Disk).Index;
break;
case Field.Writable:
if (ItemType == ItemType.Disk)
return (this as Disk).Writable?.ToString() ?? string.Empty;
break;
case Field.Optional:
if (ItemType == ItemType.Disk)
return (this as Disk).Optional?.ToString() ?? string.Empty;
else if (ItemType == ItemType.Rom)
return (this as Rom).Optional?.ToString() ?? string.Empty;
break;
case Field.Status:
if (ItemType == ItemType.Disk)
return (this as Disk).ItemStatus.ToString();
else if (ItemType == ItemType.Rom)
return (this as Rom).ItemStatus.ToString();
break;
case Field.Language:
if (ItemType == ItemType.Release)
return (this as Release).Language;
break;
case Field.Date:
if (ItemType == ItemType.Release)
return (this as Release).Date;
else if (ItemType == ItemType.Rom)
return (this as Rom).Date;
break;
case Field.Bios:
if (ItemType == ItemType.Rom)
return (this as Rom).Bios;
break;
case Field.Size:
if (ItemType == ItemType.Rom)
return (this as Rom).Size.ToString();
break;
case Field.CRC:
if (ItemType == ItemType.Rom)
return (this as Rom).CRC;
break;
case Field.Offset:
if (ItemType == ItemType.Rom)
return (this as Rom).Offset;
break;
case Field.NULL:
default:
return string.Empty;
}
return string.Empty;
}
#endregion
#region Cloning Methods
/// <summary>
@@ -601,9 +782,8 @@ namespace SabreTools.Library.DatItems
try
{
if (this.Name == other.Name)
{
ret = (this.Equals(other) ? 0 : 1);
}
ret = String.Compare(this.Name, other.Name);
}
catch
@@ -632,34 +812,24 @@ namespace SabreTools.Library.DatItems
// If we don't have a duplicate at all, return none
if (!this.Equals(lastItem))
{
return output;
}
// If the duplicate is external already or should be, set it
if ((lastItem.DupeType & DupeType.External) != 0 || lastItem.SystemID != this.SystemID || lastItem.SourceID != this.SourceID)
{
if (lastItem.MachineName == this.MachineName && lastItem.Name == this.Name)
{
output = DupeType.External | DupeType.All;
}
else
{
output = DupeType.External | DupeType.Hash;
}
}
// Otherwise, it's considered an internal dupe
else
{
if (lastItem.MachineName == this.MachineName && lastItem.Name == this.Name)
{
output = DupeType.Internal | DupeType.All;
}
else
{
output = DupeType.Internal | DupeType.Hash;
}
}
return output;
@@ -679,31 +849,18 @@ namespace SabreTools.Library.DatItems
{
// Check for an empty rom list first
if (datdata.Count == 0)
{
return false;
}
// We want to get the proper key for the DatItem
string key = SortAndGetKey(datdata, sorted);
// If the key doesn't exist, return the empty list
if (!datdata.Contains(key))
{
return false;
}
// Try to find duplicates
List<DatItem> roms = datdata[key];
foreach (DatItem rom in roms)
{
if (this.Equals(rom))
{
return true;
}
}
return false;
return roms.Any(r => this.Equals(r));
}
/// <summary>
@@ -767,9 +924,7 @@ namespace SabreTools.Library.DatItems
{
// If we're not already sorted, take care of it
if (!sorted)
{
datdata.BucketByBestAvailable();
}
// Now that we have the sorted type, we get the proper key
return Utilities.GetKeyFromDatItem(this, datdata.SortedBy);
@@ -792,9 +947,7 @@ namespace SabreTools.Library.DatItems
{
// Check for null or blank roms first
if (infiles == null || infiles.Count == 0)
{
return new List<DatItem>();
}
// Create output list
List<DatItem> outfiles = new List<DatItem>();
@@ -805,9 +958,7 @@ namespace SabreTools.Library.DatItems
{
// If we don't have a Rom or a Disk, we skip checking for duplicates
if (file.ItemType != ItemType.Rom && file.ItemType != ItemType.Disk)
{
continue;
}
// If it's a nodump, add and skip
if (file.ItemType == ItemType.Rom && ((Rom)file).ItemStatus == ItemStatus.Nodump)
@@ -852,46 +1003,46 @@ namespace SabreTools.Library.DatItems
((Rom)saveditem).Size = (((Rom)saveditem).Size == -1 && ((Rom)file).Size != -1
? ((Rom)file).Size
: ((Rom)saveditem).Size);
((Rom)saveditem).CRC = (String.IsNullOrWhiteSpace(((Rom)saveditem).CRC) && !String.IsNullOrWhiteSpace(((Rom)file).CRC)
((Rom)saveditem).CRC = (string.IsNullOrWhiteSpace(((Rom)saveditem).CRC) && !string.IsNullOrWhiteSpace(((Rom)file).CRC)
? ((Rom)file).CRC
: ((Rom)saveditem).CRC);
((Rom)saveditem).MD5 = (String.IsNullOrWhiteSpace(((Rom)saveditem).MD5) && !String.IsNullOrWhiteSpace(((Rom)file).MD5)
((Rom)saveditem).MD5 = (string.IsNullOrWhiteSpace(((Rom)saveditem).MD5) && !string.IsNullOrWhiteSpace(((Rom)file).MD5)
? ((Rom)file).MD5
: ((Rom)saveditem).MD5);
((Rom)saveditem).RIPEMD160 = (String.IsNullOrWhiteSpace(((Rom)saveditem).RIPEMD160) && !String.IsNullOrWhiteSpace(((Rom)file).RIPEMD160)
((Rom)saveditem).RIPEMD160 = (string.IsNullOrWhiteSpace(((Rom)saveditem).RIPEMD160) && !string.IsNullOrWhiteSpace(((Rom)file).RIPEMD160)
? ((Rom)file).RIPEMD160
: ((Rom)saveditem).RIPEMD160);
((Rom)saveditem).SHA1 = (String.IsNullOrWhiteSpace(((Rom)saveditem).SHA1) && !String.IsNullOrWhiteSpace(((Rom)file).SHA1)
((Rom)saveditem).SHA1 = (string.IsNullOrWhiteSpace(((Rom)saveditem).SHA1) && !string.IsNullOrWhiteSpace(((Rom)file).SHA1)
? ((Rom)file).SHA1
: ((Rom)saveditem).SHA1);
((Rom)saveditem).SHA256 = (String.IsNullOrWhiteSpace(((Rom)saveditem).SHA256) && !String.IsNullOrWhiteSpace(((Rom)file).SHA256)
((Rom)saveditem).SHA256 = (string.IsNullOrWhiteSpace(((Rom)saveditem).SHA256) && !string.IsNullOrWhiteSpace(((Rom)file).SHA256)
? ((Rom)file).SHA256
: ((Rom)saveditem).SHA256);
((Rom)saveditem).SHA384 = (String.IsNullOrWhiteSpace(((Rom)saveditem).SHA384) && !String.IsNullOrWhiteSpace(((Rom)file).SHA384)
((Rom)saveditem).SHA384 = (string.IsNullOrWhiteSpace(((Rom)saveditem).SHA384) && !string.IsNullOrWhiteSpace(((Rom)file).SHA384)
? ((Rom)file).SHA384
: ((Rom)saveditem).SHA384);
((Rom)saveditem).SHA512 = (String.IsNullOrWhiteSpace(((Rom)saveditem).SHA512) && !String.IsNullOrWhiteSpace(((Rom)file).SHA512)
((Rom)saveditem).SHA512 = (string.IsNullOrWhiteSpace(((Rom)saveditem).SHA512) && !string.IsNullOrWhiteSpace(((Rom)file).SHA512)
? ((Rom)file).SHA512
: ((Rom)saveditem).SHA512);
}
else if (file.ItemType == ItemType.Disk)
{
((Disk)saveditem).MD5 = (String.IsNullOrWhiteSpace(((Disk)saveditem).MD5) && !String.IsNullOrWhiteSpace(((Disk)file).MD5)
((Disk)saveditem).MD5 = (string.IsNullOrWhiteSpace(((Disk)saveditem).MD5) && !string.IsNullOrWhiteSpace(((Disk)file).MD5)
? ((Disk)file).MD5
: ((Disk)saveditem).MD5);
((Disk)saveditem).RIPEMD160 = (String.IsNullOrWhiteSpace(((Disk)saveditem).RIPEMD160) && !String.IsNullOrWhiteSpace(((Disk)file).RIPEMD160)
((Disk)saveditem).RIPEMD160 = (string.IsNullOrWhiteSpace(((Disk)saveditem).RIPEMD160) && !string.IsNullOrWhiteSpace(((Disk)file).RIPEMD160)
? ((Disk)file).RIPEMD160
: ((Disk)saveditem).RIPEMD160);
((Disk)saveditem).SHA1 = (String.IsNullOrWhiteSpace(((Disk)saveditem).SHA1) && !String.IsNullOrWhiteSpace(((Disk)file).SHA1)
((Disk)saveditem).SHA1 = (string.IsNullOrWhiteSpace(((Disk)saveditem).SHA1) && !string.IsNullOrWhiteSpace(((Disk)file).SHA1)
? ((Disk)file).SHA1
: ((Disk)saveditem).SHA1);
((Disk)saveditem).SHA256 = (String.IsNullOrWhiteSpace(((Disk)saveditem).SHA256) && !String.IsNullOrWhiteSpace(((Disk)file).SHA256)
((Disk)saveditem).SHA256 = (string.IsNullOrWhiteSpace(((Disk)saveditem).SHA256) && !string.IsNullOrWhiteSpace(((Disk)file).SHA256)
? ((Disk)file).SHA256
: ((Disk)saveditem).SHA256);
((Disk)saveditem).SHA384 = (String.IsNullOrWhiteSpace(((Disk)saveditem).SHA384) && !String.IsNullOrWhiteSpace(((Disk)file).SHA384)
((Disk)saveditem).SHA384 = (string.IsNullOrWhiteSpace(((Disk)saveditem).SHA384) && !string.IsNullOrWhiteSpace(((Disk)file).SHA384)
? ((Disk)file).SHA384
: ((Disk)saveditem).SHA384);
((Disk)saveditem).SHA512 = (String.IsNullOrWhiteSpace(((Disk)saveditem).SHA512) && !String.IsNullOrWhiteSpace(((Disk)file).SHA512)
((Disk)saveditem).SHA512 = (string.IsNullOrWhiteSpace(((Disk)saveditem).SHA512) && !string.IsNullOrWhiteSpace(((Disk)file).SHA512)
? ((Disk)file).SHA512
: ((Disk)saveditem).SHA512);
}
@@ -976,37 +1127,18 @@ namespace SabreTools.Library.DatItems
// If the current item exactly matches the last item, then we don't add it
if ((datItem.GetDuplicateStatus(lastItem) & DupeType.All) != 0)
{
Globals.Logger.Verbose("Exact duplicate found for '{0}'", datItem.Name);
Globals.Logger.Verbose($"Exact duplicate found for '{datItem.Name}'");
continue;
}
// If the current name matches the previous name, rename the current item
else if (datItem.Name == lastItem.Name)
{
Globals.Logger.Verbose("Name duplicate found for '{0}'", datItem.Name);
Globals.Logger.Verbose($"Name duplicate found for '{datItem.Name}'");
if (datItem.ItemType == ItemType.Disk)
if (datItem.ItemType == ItemType.Disk || datItem.ItemType == ItemType.Rom)
{
Disk disk = (Disk)datItem;
disk.Name += "_" + (!String.IsNullOrWhiteSpace(disk.MD5)
? disk.MD5
: !String.IsNullOrWhiteSpace(disk.SHA1)
? disk.SHA1
: "1");
datItem = disk;
lastrenamed = lastrenamed ?? datItem.Name;
}
else if (datItem.ItemType == ItemType.Rom)
{
Rom rom = (Rom)datItem;
rom.Name += "_" + (!String.IsNullOrWhiteSpace(rom.CRC)
? rom.CRC
: !String.IsNullOrWhiteSpace(rom.MD5)
? rom.MD5
: !String.IsNullOrWhiteSpace(rom.SHA1)
? rom.SHA1
: "1");
datItem = rom;
datItem.Name += GetDuplicateSuffix(datItem);
lastrenamed = lastrenamed ?? datItem.Name;
}
@@ -1014,7 +1146,7 @@ namespace SabreTools.Library.DatItems
if (datItem.Name == lastrenamed)
{
lastrenamed = datItem.Name;
datItem.Name += (lastid == 0 ? "" : "_" + lastid);
datItem.Name += (lastid == 0 ? string.Empty : "_" + lastid);
lastid++;
}
// If we have no conflict, then we want to reset the lastrenamed and id
@@ -1043,6 +1175,39 @@ namespace SabreTools.Library.DatItems
return output;
}
/// <summary>
/// Get duplicate suffix based on the item type
/// </summary>
private static string GetDuplicateSuffix(DatItem datItem)
{
if (datItem.ItemType == ItemType.Disk)
{
Disk disk = datItem as Disk;
if (string.IsNullOrWhiteSpace(disk.MD5))
return $"_{disk.MD5}";
else if (string.IsNullOrWhiteSpace(disk.SHA1))
return $"_{disk.SHA1}";
else
return "_1";
}
else if (datItem.ItemType == ItemType.Rom)
{
Rom rom = datItem as Rom;
if (string.IsNullOrWhiteSpace(rom.CRC))
return $"_{rom.CRC}";
else if (string.IsNullOrWhiteSpace(rom.MD5))
return $"_{rom.MD5}";
else if (string.IsNullOrWhiteSpace(rom.SHA1))
return $"_{rom.SHA1}";
else
return "_1";
}
return "_1";
}
/// <summary>
/// Sort a list of File objects by SystemID, SourceID, Game, and Name (in order)
/// </summary>
@@ -1068,6 +1233,7 @@ namespace SabreTools.Library.DatItems
{
return nc.Compare(Path.GetFileName(Utilities.RemovePathUnsafeCharacters(x.Name)), Path.GetFileName(Utilities.RemovePathUnsafeCharacters(y.Name)));
}
return nc.Compare(Path.GetDirectoryName(Utilities.RemovePathUnsafeCharacters(x.Name)), Path.GetDirectoryName(Utilities.RemovePathUnsafeCharacters(y.Name)));
}
else if ((x.ItemType == ItemType.Rom || x.ItemType == ItemType.Disk) && (y.ItemType != ItemType.Rom && y.ItemType != ItemType.Disk))
@@ -1084,13 +1250,17 @@ namespace SabreTools.Library.DatItems
{
return nc.Compare(Path.GetFileName(x.Name), Path.GetFileName(y.Name));
}
return nc.Compare(Path.GetDirectoryName(x.Name), Path.GetDirectoryName(y.Name));
}
}
return nc.Compare(x.MachineName, y.MachineName);
}
return (norename ? nc.Compare(x.MachineName, y.MachineName) : x.SourceID - y.SourceID);
}
return (norename ? nc.Compare(x.MachineName, y.MachineName) : x.SystemID - y.SystemID);
}
catch (Exception)