DatItems of destiny

This commit is contained in:
Matt Nadareski
2020-08-17 17:28:32 -07:00
parent fafac31ea8
commit 5660da7b0e
8 changed files with 521 additions and 294 deletions

View File

@@ -5,6 +5,7 @@ namespace SabreTools.Library.DatFiles
/// <summary> /// <summary>
/// Determines how the current dictionary is bucketed by /// Determines how the current dictionary is bucketed by
/// </summary> /// </summary>
/// TODO: Can we use "Field" instead of this? How much more stupidly complex would that make things?
public enum BucketedBy public enum BucketedBy
{ {
Default = 0, Default = 0,

View File

@@ -1,6 +1,4 @@
using SabreTools.Library.Data; namespace SabreTools.Library.DatItems
namespace SabreTools.Library.DatItems
{ {
/// <summary> /// <summary>
/// Represents generic archive files to be included in a set /// Represents generic archive files to be included in a set

View File

@@ -1,4 +1,5 @@
using SabreTools.Library.Data; using System.Collections.Generic;
using System.Security.Permissions;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace SabreTools.Library.DatItems namespace SabreTools.Library.DatItems
@@ -24,6 +25,42 @@ namespace SabreTools.Library.DatItems
#endregion #endregion
#region Accessors
/// <summary>
/// Get the value of that field as a string, if possible
/// </summary>
public override string GetField(Field field, List<Field> excludeFields)
{
// If the field is to be excluded, return empty string
if (excludeFields.Contains(field))
return string.Empty;
// Handle BiosSet-specific fields
string fieldValue;
switch (field)
{
case Field.Default:
fieldValue = Default?.ToString();
break;
case Field.BiosDescription:
fieldValue = Description;
break;
// For everything else, use the base method
default:
return base.GetField(field, excludeFields);
}
// Make sure we don't return null
if (string.IsNullOrEmpty(fieldValue))
fieldValue = string.Empty;
return fieldValue;
}
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>

View File

@@ -615,7 +615,7 @@ namespace SabreTools.Library.DatItems
/// <summary> /// <summary>
/// Get the value of that field as a string, if possible /// Get the value of that field as a string, if possible
/// </summary> /// </summary>
public string GetField(Field field, List<Field> excludeFields) public virtual string GetField(Field field, List<Field> excludeFields)
{ {
// If the field is to be excluded, return empty string // If the field is to be excluded, return empty string
if (excludeFields.Contains(field)) if (excludeFields.Contains(field))
@@ -625,196 +625,80 @@ namespace SabreTools.Library.DatItems
switch (field) switch (field)
{ {
case Field.Name: case Field.Name:
fieldValue = this.Name; fieldValue = Name;
break; break;
case Field.PartName: case Field.PartName:
fieldValue = this.PartName; fieldValue = PartName;
break; break;
case Field.PartInterface: case Field.PartInterface:
fieldValue = this.PartInterface; fieldValue = PartInterface;
break; break;
case Field.Features: case Field.Features:
fieldValue = string.Join(";", (this.Features ?? new List<KeyValuePair<string, string>>()).Select(f => $"{f.Key}={f.Value}")); fieldValue = string.Join(";", (Features ?? new List<KeyValuePair<string, string>>()).Select(f => $"{f.Key}={f.Value}"));
break; break;
case Field.AreaName: case Field.AreaName:
fieldValue = this.AreaName; fieldValue = AreaName;
break; break;
case Field.AreaSize: case Field.AreaSize:
fieldValue = this.AreaSize?.ToString(); fieldValue = AreaSize?.ToString();
break; break;
case Field.MachineName: case Field.MachineName:
fieldValue = this.MachineName; fieldValue = MachineName;
break; break;
case Field.Comment: case Field.Comment:
fieldValue = this.Comment; fieldValue = Comment;
break; break;
case Field.Description: case Field.Description:
fieldValue = this.MachineDescription; fieldValue = MachineDescription;
break; break;
case Field.Year: case Field.Year:
fieldValue = this.Year; fieldValue = Year;
break; break;
case Field.Manufacturer: case Field.Manufacturer:
fieldValue = this.Manufacturer; fieldValue = Manufacturer;
break; break;
case Field.Publisher: case Field.Publisher:
fieldValue = this.Publisher; fieldValue = Publisher;
break; break;
case Field.Category: case Field.Category:
fieldValue = this.Category; fieldValue = Category;
break; break;
case Field.RomOf: case Field.RomOf:
fieldValue = this.RomOf; fieldValue = RomOf;
break; break;
case Field.CloneOf: case Field.CloneOf:
fieldValue = this.CloneOf; fieldValue = CloneOf;
break; break;
case Field.SampleOf: case Field.SampleOf:
fieldValue = this.SampleOf; fieldValue = SampleOf;
break; break;
case Field.Supported: case Field.Supported:
fieldValue = this.Supported?.ToString(); fieldValue = Supported?.ToString();
break; break;
case Field.SourceFile: case Field.SourceFile:
fieldValue = this.SourceFile; fieldValue = SourceFile;
break; break;
case Field.Runnable: case Field.Runnable:
fieldValue = this.Runnable?.ToString(); fieldValue = Runnable?.ToString();
break; break;
case Field.Board: case Field.Board:
fieldValue = this.Board; fieldValue = Board;
break; break;
case Field.RebuildTo: case Field.RebuildTo:
fieldValue = this.RebuildTo; fieldValue = RebuildTo;
break; break;
case Field.Devices: case Field.Devices:
fieldValue = string.Join(";", this.Devices ?? new List<string>()); fieldValue = string.Join(";", Devices ?? new List<string>());
break; break;
case Field.SlotOptions: case Field.SlotOptions:
fieldValue = string.Join(";", this.SlotOptions ?? new List<string>()); fieldValue = string.Join(";", SlotOptions ?? new List<string>());
break; break;
case Field.Infos: case Field.Infos:
fieldValue = string.Join(";", (this.Infos ?? new List<KeyValuePair<string, string>>()).Select(i => $"{i.Key}={i.Value}")); fieldValue = string.Join(";", (Infos ?? new List<KeyValuePair<string, string>>()).Select(i => $"{i.Key}={i.Value}"));
break; break;
case Field.MachineType: case Field.MachineType:
fieldValue = this.MachineType.ToString(); fieldValue = MachineType.ToString();
break;
case Field.Default:
if (ItemType == ItemType.BiosSet)
fieldValue = (this as BiosSet).Default?.ToString();
else if (ItemType == ItemType.Release)
fieldValue = (this as Release).Default?.ToString();
break;
case Field.BiosDescription:
if (ItemType == ItemType.BiosSet)
fieldValue = (this as BiosSet).Description;
break;
case Field.MD5:
if (ItemType == ItemType.Disk)
fieldValue = (this as Disk).MD5;
else if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).MD5;
break;
#if NET_FRAMEWORK
case Field.RIPEMD160:
if (ItemType == ItemType.Disk)
fieldValue = (this as Disk).RIPEMD160;
else if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).RIPEMD160;
break;
#endif
case Field.SHA1:
if (ItemType == ItemType.Disk)
fieldValue = (this as Disk).SHA1;
else if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).SHA1;
break;
case Field.SHA256:
if (ItemType == ItemType.Disk)
fieldValue = (this as Disk).SHA256;
else if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).SHA256;
break;
case Field.SHA384:
if (ItemType == ItemType.Disk)
fieldValue = (this as Disk).SHA384;
else if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).SHA384;
break;
case Field.SHA512:
if (ItemType == ItemType.Disk)
fieldValue = (this as Disk).SHA512;
else if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).SHA512;
break;
case Field.Merge:
if (ItemType == ItemType.Disk)
fieldValue = (this as Disk).MergeTag;
else if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).MergeTag;
break;
case Field.Region:
if (ItemType == ItemType.Disk)
fieldValue = (this as Disk).Region;
else if (ItemType == ItemType.Release)
fieldValue = (this as Release).Region;
else if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).Region;
break;
case Field.Index:
if (ItemType == ItemType.Disk)
fieldValue = (this as Disk).Index;
break;
case Field.Writable:
if (ItemType == ItemType.Disk)
fieldValue = (this as Disk).Writable?.ToString();
break;
case Field.Optional:
if (ItemType == ItemType.Disk)
fieldValue = (this as Disk).Optional?.ToString();
else if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).Optional?.ToString();
break;
case Field.Status:
if (ItemType == ItemType.Disk)
fieldValue = (this as Disk).ItemStatus.ToString();
else if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).ItemStatus.ToString();
break;
case Field.Language:
if (ItemType == ItemType.Release)
fieldValue = (this as Release).Language;
break;
case Field.Date:
if (ItemType == ItemType.Release)
fieldValue = (this as Release).Date;
else if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).Date;
break;
case Field.Bios:
if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).Bios;
break;
case Field.Size:
if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).Size.ToString();
break;
case Field.CRC:
if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).CRC;
break;
case Field.Offset:
if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).Offset;
break;
case Field.Inverted:
if (ItemType == ItemType.Rom)
fieldValue = (this as Rom).Inverted?.ToString();
break; break;
case Field.NULL: case Field.NULL:
@@ -949,10 +833,10 @@ namespace SabreTools.Library.DatItems
{ {
try try
{ {
if (this.Name == other.Name) if (Name == other.Name)
return this.Equals(other) ? 0 : 1; return Equals(other) ? 0 : 1;
return String.Compare(this.Name, other.Name); return string.Compare(Name, other.Name);
} }
catch catch
{ {
@@ -977,13 +861,13 @@ namespace SabreTools.Library.DatItems
DupeType output = 0x00; DupeType output = 0x00;
// If we don't have a duplicate at all, return none // If we don't have a duplicate at all, return none
if (!this.Equals(lastItem)) if (!Equals(lastItem))
return output; return output;
// If the duplicate is external already or should be, set it // If the duplicate is external already or should be, set it
if (lastItem.DupeType.HasFlag(DupeType.External) || lastItem.IndexId != this.IndexId) if (lastItem.DupeType.HasFlag(DupeType.External) || lastItem.IndexId != IndexId)
{ {
if (lastItem.MachineName == this.MachineName && lastItem.Name == this.Name) if (lastItem.MachineName == MachineName && lastItem.Name == Name)
output = DupeType.External | DupeType.All; output = DupeType.External | DupeType.All;
else else
output = DupeType.External | DupeType.Hash; output = DupeType.External | DupeType.Hash;
@@ -992,7 +876,7 @@ namespace SabreTools.Library.DatItems
// Otherwise, it's considered an internal dupe // Otherwise, it's considered an internal dupe
else else
{ {
if (lastItem.MachineName == this.MachineName && lastItem.Name == this.Name) if (lastItem.MachineName == MachineName && lastItem.Name == Name)
output = DupeType.Internal | DupeType.All; output = DupeType.Internal | DupeType.All;
else else
output = DupeType.Internal | DupeType.Hash; output = DupeType.Internal | DupeType.Hash;
@@ -1012,7 +896,7 @@ namespace SabreTools.Library.DatItems
/// <param name="lower">True if the key should be lowercased (default), false otherwise</param> /// <param name="lower">True if the key should be lowercased (default), false otherwise</param>
/// <param name="norename">True if games should only be compared on game and file name, false if system and source are counted</param> /// <param name="norename">True if games should only be compared on game and file name, false if system and source are counted</param>
/// <returns>String representing the key to be used for the DatItem</returns> /// <returns>String representing the key to be used for the DatItem</returns>
public string GetKey(BucketedBy bucketedBy, bool lower = true, bool norename = true) public virtual string GetKey(BucketedBy bucketedBy, bool lower = true, bool norename = true)
{ {
// Set the output key as the default blank string // Set the output key as the default blank string
string key = string.Empty; string key = string.Empty;
@@ -1021,16 +905,16 @@ namespace SabreTools.Library.DatItems
switch (bucketedBy) switch (bucketedBy)
{ {
case BucketedBy.CRC: case BucketedBy.CRC:
key = (this.ItemType == ItemType.Rom ? ((Rom)this).CRC : Constants.CRCZero); key = Constants.CRCZero;
break; break;
case BucketedBy.Game: case BucketedBy.Game:
key = (norename ? string.Empty key = (norename ? string.Empty
: this.IndexId.ToString().PadLeft(10, '0') : IndexId.ToString().PadLeft(10, '0')
+ "-") + "-")
+ (string.IsNullOrWhiteSpace(this.MachineName) + (string.IsNullOrWhiteSpace(MachineName)
? "Default" ? "Default"
: this.MachineName); : MachineName);
if (lower) if (lower)
key = key.ToLowerInvariant(); key = key.ToLowerInvariant();
@@ -1041,53 +925,29 @@ namespace SabreTools.Library.DatItems
break; break;
case BucketedBy.MD5: case BucketedBy.MD5:
key = (this.ItemType == ItemType.Rom key = Constants.MD5Zero;
? ((Rom)this).MD5
: (this.ItemType == ItemType.Disk
? ((Disk)this).MD5
: Constants.MD5Zero));
break; break;
#if NET_FRAMEWORK #if NET_FRAMEWORK
case BucketedBy.RIPEMD160: case BucketedBy.RIPEMD160:
key = (this.ItemType == ItemType.Rom key = Constants.RIPEMD160Zero;
? ((Rom)this).RIPEMD160
: (this.ItemType == ItemType.Disk
? ((Disk)this).RIPEMD160
: Constants.RIPEMD160Zero));
break; break;
#endif #endif
case BucketedBy.SHA1: case BucketedBy.SHA1:
key = (this.ItemType == ItemType.Rom key = Constants.SHA1Zero;
? ((Rom)this).SHA1
: (this.ItemType == ItemType.Disk
? ((Disk)this).SHA1
: Constants.SHA1Zero));
break; break;
case BucketedBy.SHA256: case BucketedBy.SHA256:
key = (this.ItemType == ItemType.Rom key = Constants.SHA256Zero;
? ((Rom)this).SHA256
: (this.ItemType == ItemType.Disk
? ((Disk)this).SHA256
: Constants.SHA256Zero));
break; break;
case BucketedBy.SHA384: case BucketedBy.SHA384:
key = (this.ItemType == ItemType.Rom key = Constants.SHA384Zero;
? ((Rom)this).SHA384
: (this.ItemType == ItemType.Disk
? ((Disk)this).SHA384
: Constants.SHA384Zero));
break; break;
case BucketedBy.SHA512: case BucketedBy.SHA512:
key = (this.ItemType == ItemType.Rom key = Constants.SHA512Zero;
? ((Rom)this).SHA512
: (this.ItemType == ItemType.Disk
? ((Disk)this).SHA512
: Constants.SHA512Zero));
break; break;
} }
@@ -1151,13 +1011,13 @@ namespace SabreTools.Library.DatItems
continue; continue;
// If it's a nodump, add and skip // If it's a nodump, add and skip
if (file.ItemType == ItemType.Rom && ((Rom)file).ItemStatus == ItemStatus.Nodump) if (file.ItemType == ItemType.Rom && (file as Rom).ItemStatus == ItemStatus.Nodump)
{ {
outfiles.Add(file); outfiles.Add(file);
nodumpCount++; nodumpCount++;
continue; continue;
} }
else if (file.ItemType == ItemType.Disk && ((Disk)file).ItemStatus == ItemStatus.Nodump) else if (file.ItemType == ItemType.Disk && (file as Disk).ItemStatus == ItemStatus.Nodump)
{ {
outfiles.Add(file); outfiles.Add(file);
nodumpCount++; nodumpCount++;
@@ -1172,7 +1032,7 @@ namespace SabreTools.Library.DatItems
// Check if the rom is a duplicate // Check if the rom is a duplicate
DupeType dupetype = 0x00; DupeType dupetype = 0x00;
DatItem saveditem = new Rom(); DatItem saveditem = new Blank();
int pos = -1; int pos = -1;
for (int i = 0; i < outfiles.Count; i++) for (int i = 0; i < outfiles.Count; i++)
{ {
@@ -1187,59 +1047,11 @@ namespace SabreTools.Library.DatItems
saveditem = lastrom; saveditem = lastrom;
pos = i; pos = i;
// Roms have more infomration to save // Disks and Roms have more information to fill
if (file.ItemType == ItemType.Rom) if (file.ItemType == ItemType.Disk)
{ (saveditem as Disk).FillMissingInformation(file as Disk);
((Rom)saveditem).Size = (((Rom)saveditem).Size == -1 && ((Rom)file).Size != -1 else if (file.ItemType == ItemType.Rom)
? ((Rom)file).Size (saveditem as Rom).FillMissingInformation(file as Rom);
: ((Rom)saveditem).Size);
((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)file).MD5
: ((Rom)saveditem).MD5);
#if NET_FRAMEWORK
((Rom)saveditem).RIPEMD160 = (string.IsNullOrWhiteSpace(((Rom)saveditem).RIPEMD160) && !string.IsNullOrWhiteSpace(((Rom)file).RIPEMD160)
? ((Rom)file).RIPEMD160
: ((Rom)saveditem).RIPEMD160);
#endif
((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)file).SHA256
: ((Rom)saveditem).SHA256);
((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)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)file).MD5
: ((Disk)saveditem).MD5);
#if NET_FRAMEWORK
((Disk)saveditem).RIPEMD160 = (string.IsNullOrWhiteSpace(((Disk)saveditem).RIPEMD160) && !string.IsNullOrWhiteSpace(((Disk)file).RIPEMD160)
? ((Disk)file).RIPEMD160
: ((Disk)saveditem).RIPEMD160);
#endif
((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)file).SHA256
: ((Disk)saveditem).SHA256);
((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)file).SHA512
: ((Disk)saveditem).SHA512);
}
saveditem.DupeType = dupetype; saveditem.DupeType = dupetype;
@@ -1370,29 +1182,9 @@ namespace SabreTools.Library.DatItems
private static string GetDuplicateSuffix(DatItem datItem) private static string GetDuplicateSuffix(DatItem datItem)
{ {
if (datItem.ItemType == ItemType.Disk) if (datItem.ItemType == ItemType.Disk)
{ return (datItem as Disk).GetDuplicateSuffix();
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) else if (datItem.ItemType == ItemType.Rom)
{ return (datItem as Rom).GetDuplicateSuffix();
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"; return "_1";
} }
@@ -1414,31 +1206,22 @@ namespace SabreTools.Library.DatItems
{ {
if (x.MachineName == y.MachineName) if (x.MachineName == y.MachineName)
{ {
if ((x.ItemType == ItemType.Rom || x.ItemType == ItemType.Disk) && (y.ItemType == ItemType.Rom || y.ItemType == ItemType.Disk)) // Special case for comparing a Disk or Rom to another item type
if ((x.ItemType == ItemType.Disk || x.ItemType == ItemType.Rom) ^ (y.ItemType == ItemType.Disk || y.ItemType == ItemType.Rom))
{ {
if (Path.GetDirectoryName(Sanitizer.RemovePathUnsafeCharacters(x.Name)) == Path.GetDirectoryName(Sanitizer.RemovePathUnsafeCharacters(y.Name))) if (x.ItemType == ItemType.Disk || x.ItemType == ItemType.Rom)
{ return -1;
return nc.Compare(Path.GetFileName(Sanitizer.RemovePathUnsafeCharacters(x.Name)), Path.GetFileName(Sanitizer.RemovePathUnsafeCharacters(y.Name))); else
} return 1;
}
return nc.Compare(Path.GetDirectoryName(Sanitizer.RemovePathUnsafeCharacters(x.Name)), Path.GetDirectoryName(Sanitizer.RemovePathUnsafeCharacters(y.Name))); // Otherwise, we compare names naturally
}
else if ((x.ItemType == ItemType.Rom || x.ItemType == ItemType.Disk) && (y.ItemType != ItemType.Rom && y.ItemType != ItemType.Disk))
{
return -1;
}
else if ((x.ItemType != ItemType.Rom && x.ItemType != ItemType.Disk) && (y.ItemType == ItemType.Rom || y.ItemType == ItemType.Disk))
{
return 1;
}
else else
{ {
if (Path.GetDirectoryName(x.Name) == Path.GetDirectoryName(y.Name)) if (Path.GetDirectoryName(Sanitizer.RemovePathUnsafeCharacters(x.Name)) == Path.GetDirectoryName(Sanitizer.RemovePathUnsafeCharacters(y.Name)))
{ return nc.Compare(Path.GetFileName(Sanitizer.RemovePathUnsafeCharacters(x.Name)), Path.GetFileName(Sanitizer.RemovePathUnsafeCharacters(y.Name)));
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(Path.GetDirectoryName(Sanitizer.RemovePathUnsafeCharacters(x.Name)), Path.GetDirectoryName(Sanitizer.RemovePathUnsafeCharacters(y.Name)));
} }
} }

View File

@@ -1,5 +1,5 @@
using System.Linq; using System.Collections.Generic;
using SabreTools.Library.DatFiles;
using SabreTools.Library.FileTypes; using SabreTools.Library.FileTypes;
using SabreTools.Library.Tools; using SabreTools.Library.Tools;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -126,6 +126,74 @@ namespace SabreTools.Library.DatItems
#endregion #endregion
#region Accessors
/// <summary>
/// Get the value of that field as a string, if possible
/// </summary>
public override string GetField(Field field, List<Field> excludeFields)
{
// If the field is to be excluded, return empty string
if (excludeFields.Contains(field))
return string.Empty;
// Handle Disk-specific fields
string fieldValue;
switch (field)
{
case Field.MD5:
fieldValue = MD5;
break;
#if NET_FRAMEWORK
case Field.RIPEMD160:
fieldValue = RIPEMD160;
break;
#endif
case Field.SHA1:
fieldValue = SHA1;
break;
case Field.SHA256:
fieldValue = SHA256;
break;
case Field.SHA384:
fieldValue = SHA384;
break;
case Field.SHA512:
fieldValue = SHA512;
break;
case Field.Merge:
fieldValue = MergeTag;
break;
case Field.Region:
fieldValue = Region;
break;
case Field.Index:
fieldValue = Index;
break;
case Field.Writable:
fieldValue = Writable?.ToString();
break;
case Field.Optional:
fieldValue = Optional?.ToString();
break;
case Field.Status:
fieldValue = ItemStatus.ToString();
break;
// For everything else, use the base method
default:
return base.GetField(field, excludeFields);
}
// Make sure we don't return null
if (string.IsNullOrEmpty(fieldValue))
fieldValue = string.Empty;
return fieldValue;
}
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
@@ -305,6 +373,53 @@ namespace SabreTools.Library.DatItems
return dupefound; return dupefound;
} }
/// <summary>
/// Fill any missing size and hash information from another Disk
/// </summary>
/// <param name="other">Disk to fill information from</param>
public void FillMissingInformation(Disk other)
{
if (_md5.IsNullOrEmpty() && !other._md5.IsNullOrEmpty())
_md5 = other._md5;
#if NET_FRAMEWORK
if (_ripemd160.IsNullOrEmpty() && !other._ripemd160.IsNullOrEmpty())
_ripemd160 = other._ripemd160;
#endif
if (_sha1.IsNullOrEmpty() && !other._sha1.IsNullOrEmpty())
_sha1 = other._sha1;
if (_sha256.IsNullOrEmpty() && !other._sha256.IsNullOrEmpty())
_sha256 = other._sha256;
if (_sha384.IsNullOrEmpty() && !other._sha384.IsNullOrEmpty())
_sha384 = other._sha384;
if (_sha512.IsNullOrEmpty() && !other._sha512.IsNullOrEmpty())
_sha512 = other._sha512;
}
/// <summary>
/// Get unique duplicate suffix on name collision
/// </summary>
/// <returns>String representing the suffix</returns>
public string GetDuplicateSuffix()
{
if (!_md5.IsNullOrEmpty())
return $"_{MD5}";
else if (!_sha1.IsNullOrEmpty())
return $"_{SHA1}";
else if (!_sha256.IsNullOrEmpty())
return $"_{SHA256}";
else if (!_sha384.IsNullOrEmpty())
return $"_{SHA384}";
else if (!_sha512.IsNullOrEmpty())
return $"_{SHA512}";
else
return "_1";
}
/// <summary> /// <summary>
/// Returns if there are no, non-empty hashes in common with another Disk /// Returns if there are no, non-empty hashes in common with another Disk
/// </summary> /// </summary>
@@ -365,5 +480,62 @@ namespace SabreTools.Library.DatItems
} }
#endregion #endregion
#region Sorting and Merging
/// <summary>
/// Get the dictionary key that should be used for a given item and bucketing type
/// </summary>
/// <param name="bucketedBy">BucketedBy enum representing what key to get</param>
/// <param name="lower">True if the key should be lowercased (default), false otherwise</param>
/// <param name="norename">True if games should only be compared on game and file name, false if system and source are counted</param>
/// <returns>String representing the key to be used for the DatItem</returns>
public override string GetKey(BucketedBy bucketedBy, bool lower = true, bool norename = true)
{
// Set the output key as the default blank string
string key = string.Empty;
// Now determine what the key should be based on the bucketedBy value
switch (bucketedBy)
{
case BucketedBy.MD5:
key = MD5;
break;
#if NET_FRAMEWORK
case BucketedBy.RIPEMD160:
key = RIPEMD160;
break;
#endif
case BucketedBy.SHA1:
key = SHA1;
break;
case BucketedBy.SHA256:
key = SHA256;
break;
case BucketedBy.SHA384:
key = SHA384;
break;
case BucketedBy.SHA512:
key = SHA512;
break;
// Let the base handle generic stuff
default:
return base.GetKey(bucketedBy, lower, norename);
}
// Double and triple check the key for corner cases
if (key == null)
key = string.Empty;
return key;
}
#endregion
} }
} }

View File

@@ -1,4 +1,4 @@
using SabreTools.Library.Data; using System.Collections.Generic;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace SabreTools.Library.DatItems namespace SabreTools.Library.DatItems
@@ -36,6 +36,48 @@ namespace SabreTools.Library.DatItems
#endregion #endregion
#region Accessors
/// <summary>
/// Get the value of that field as a string, if possible
/// </summary>
public override string GetField(Field field, List<Field> excludeFields)
{
// If the field is to be excluded, return empty string
if (excludeFields.Contains(field))
return string.Empty;
// Handle Release-specific fields
string fieldValue;
switch (field)
{
case Field.Region:
fieldValue = Region;
break;
case Field.Language:
fieldValue = Language;
break;
case Field.Date:
fieldValue = Date;
break;
case Field.Default:
fieldValue = Default?.ToString();
break;
// For everything else, use the base method
default:
return base.GetField(field, excludeFields);
}
// Make sure we don't return null
if (string.IsNullOrEmpty(fieldValue))
fieldValue = string.Empty;
return fieldValue;
}
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>

View File

@@ -1,6 +1,6 @@
using System.Linq; using System.Collections.Generic;
using SabreTools.Library.Data; using SabreTools.Library.Data;
using SabreTools.Library.DatFiles;
using SabreTools.Library.FileTypes; using SabreTools.Library.FileTypes;
using SabreTools.Library.Tools; using SabreTools.Library.Tools;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -156,6 +156,86 @@ namespace SabreTools.Library.DatItems
#endregion #endregion
#region Accessors
/// <summary>
/// Get the value of that field as a string, if possible
/// </summary>
public override string GetField(Field field, List<Field> excludeFields)
{
// If the field is to be excluded, return empty string
if (excludeFields.Contains(field))
return string.Empty;
// Handle Rom-specific fields
string fieldValue;
switch (field)
{
case Field.Bios:
fieldValue = Bios;
break;
case Field.Size:
fieldValue = Size.ToString();
break;
case Field.CRC:
fieldValue = CRC;
break;
case Field.MD5:
fieldValue = MD5;
break;
#if NET_FRAMEWORK
case Field.RIPEMD160:
fieldValue = RIPEMD160;
break;
#endif
case Field.SHA1:
fieldValue = SHA1;
break;
case Field.SHA256:
fieldValue = SHA256;
break;
case Field.SHA384:
fieldValue = SHA384;
break;
case Field.SHA512:
fieldValue = SHA512;
break;
case Field.Merge:
fieldValue = MergeTag;
break;
case Field.Region:
fieldValue = Region;
break;
case Field.Offset:
fieldValue = Offset;
break;
case Field.Date:
fieldValue = Date;
break;
case Field.Status:
fieldValue = ItemStatus.ToString();
break;
case Field.Optional:
fieldValue = Optional?.ToString();
break;
case Field.Inverted:
fieldValue = Inverted?.ToString();
break;
// For everything else, use the base method
default:
return base.GetField(field, excludeFields);
}
// Make sure we don't return null
if (string.IsNullOrEmpty(fieldValue))
fieldValue = string.Empty;
return fieldValue;
}
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
@@ -307,6 +387,61 @@ namespace SabreTools.Library.DatItems
return dupefound; return dupefound;
} }
/// <summary>
/// Fill any missing size and hash information from another Rom
/// </summary>
/// <param name="other">Rom to fill information from</param>
public void FillMissingInformation(Rom other)
{
if (Size == -1 && other.Size != -1)
Size = other.Size;
if (_crc.IsNullOrEmpty() && !other._crc.IsNullOrEmpty())
_crc = other._crc;
if (_md5.IsNullOrEmpty() && !other._md5.IsNullOrEmpty())
_md5 = other._md5;
#if NET_FRAMEWORK
if (_ripemd160.IsNullOrEmpty() && !other._ripemd160.IsNullOrEmpty())
_ripemd160 = other._ripemd160;
#endif
if (_sha1.IsNullOrEmpty() && !other._sha1.IsNullOrEmpty())
_sha1 = other._sha1;
if (_sha256.IsNullOrEmpty() && !other._sha256.IsNullOrEmpty())
_sha256 = other._sha256;
if (_sha384.IsNullOrEmpty() && !other._sha384.IsNullOrEmpty())
_sha384 = other._sha384;
if (_sha512.IsNullOrEmpty() && !other._sha512.IsNullOrEmpty())
_sha512 = other._sha512;
}
/// <summary>
/// Get unique duplicate suffix on name collision
/// </summary>
/// <returns>String representing the suffix</returns>
public string GetDuplicateSuffix()
{
if (!_crc.IsNullOrEmpty())
return $"_{CRC}";
else if (!_md5.IsNullOrEmpty())
return $"_{MD5}";
else if (!_sha1.IsNullOrEmpty())
return $"_{SHA1}";
else if (!_sha256.IsNullOrEmpty())
return $"_{SHA256}";
else if (!_sha384.IsNullOrEmpty())
return $"_{SHA384}";
else if (!_sha512.IsNullOrEmpty())
return $"_{SHA512}";
else
return "_1";
}
/// <summary> /// <summary>
/// Returns if there are no, non-empty hashes in common with another Rom /// Returns if there are no, non-empty hashes in common with another Rom
/// </summary> /// </summary>
@@ -370,5 +505,66 @@ namespace SabreTools.Library.DatItems
} }
#endregion #endregion
#region Sorting and Merging
/// <summary>
/// Get the dictionary key that should be used for a given item and bucketing type
/// </summary>
/// <param name="bucketedBy">BucketedBy enum representing what key to get</param>
/// <param name="lower">True if the key should be lowercased (default), false otherwise</param>
/// <param name="norename">True if games should only be compared on game and file name, false if system and source are counted</param>
/// <returns>String representing the key to be used for the DatItem</returns>
public override string GetKey(BucketedBy bucketedBy, bool lower = true, bool norename = true)
{
// Set the output key as the default blank string
string key = string.Empty;
// Now determine what the key should be based on the bucketedBy value
switch (bucketedBy)
{
case BucketedBy.CRC:
key = CRC;
break;
case BucketedBy.MD5:
key = MD5;
break;
#if NET_FRAMEWORK
case BucketedBy.RIPEMD160:
key = RIPEMD160;
break;
#endif
case BucketedBy.SHA1:
key = SHA1;
break;
case BucketedBy.SHA256:
key = SHA256;
break;
case BucketedBy.SHA384:
key = SHA384;
break;
case BucketedBy.SHA512:
key = SHA512;
break;
// Let the base handle generic stuff
default:
return base.GetKey(bucketedBy, lower, norename);
}
// Double and triple check the key for corner cases
if (key == null)
key = string.Empty;
return key;
}
#endregion
} }
} }

View File

@@ -1,6 +1,4 @@
using SabreTools.Library.Data; namespace SabreTools.Library.DatItems
namespace SabreTools.Library.DatItems
{ {
/// <summary> /// <summary>
/// Represents a (usually WAV-formatted) sample to be included for use in the set /// Represents a (usually WAV-formatted) sample to be included for use in the set