mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-09-22 23:05:12 +00:00
DictionaryBase is no more, bon voyage
This commit is contained in:
@@ -2515,7 +2515,7 @@ namespace SabreTools.Data.Extensions.Test
|
||||
var other = new Disk();
|
||||
|
||||
self.FillMissingHashes(other);
|
||||
Assert.Empty(self);
|
||||
Assert.False(self.HasHashes());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -2537,7 +2537,7 @@ namespace SabreTools.Data.Extensions.Test
|
||||
var self = new Media();
|
||||
var other = new Media();
|
||||
self.FillMissingHashes(other);
|
||||
Assert.Empty(self);
|
||||
Assert.False(self.HasHashes());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -2561,7 +2561,7 @@ namespace SabreTools.Data.Extensions.Test
|
||||
var self = new Rom();
|
||||
var other = new Rom();
|
||||
self.FillMissingHashes(other);
|
||||
Assert.Empty(self);
|
||||
Assert.False(self.HasHashes());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace SabreTools.Data.Models.Metadata
|
||||
/// <summary>
|
||||
/// Format-agnostic representation of item data
|
||||
/// </summary>
|
||||
public class DatItem : DictionaryBase
|
||||
public class DatItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Quick accessor to item type, if it exists
|
||||
|
||||
@@ -1,263 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SabreTools.Data.Models.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Specialized dictionary base for item types
|
||||
/// </summary>
|
||||
public abstract class DictionaryBase : Dictionary<string, object?>
|
||||
{
|
||||
#region Read
|
||||
|
||||
/// <summary>
|
||||
/// Read a key as the specified type, returning null on error
|
||||
/// </summary>
|
||||
public T? Read<T>(string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ValidateReadKey(key))
|
||||
return default;
|
||||
if (this[key] is not T)
|
||||
return default;
|
||||
return (T?)this[key];
|
||||
}
|
||||
catch
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a key as a bool, returning null on error
|
||||
/// </summary>
|
||||
/// TODO: Determine if this can be removed
|
||||
public bool? ReadBool(string key)
|
||||
{
|
||||
if (!ValidateReadKey(key))
|
||||
return null;
|
||||
|
||||
bool? asBool = Read<bool?>(key);
|
||||
if (asBool is not null)
|
||||
return asBool;
|
||||
|
||||
string? asString = Read<string>(key);
|
||||
return asString?.ToLowerInvariant() switch
|
||||
{
|
||||
"true" or "yes" => true,
|
||||
"false" or "no" => false,
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a key as a double, returning null on error
|
||||
/// </summary>
|
||||
/// TODO: Determine if this can be removed
|
||||
public double? ReadDouble(string key)
|
||||
{
|
||||
if (!ValidateReadKey(key))
|
||||
return null;
|
||||
|
||||
double? asDouble = Read<double?>(key);
|
||||
if (asDouble is not null)
|
||||
return asDouble;
|
||||
|
||||
float? asFloat = Read<float?>(key);
|
||||
if (asFloat is not null)
|
||||
return asFloat;
|
||||
|
||||
#if NET5_0_OR_GREATER
|
||||
System.Half? asHalf = Read<System.Half?>(key);
|
||||
if (asHalf is not null)
|
||||
return (double?)asHalf;
|
||||
#endif
|
||||
|
||||
string? asString = Read<string>(key);
|
||||
if (asString is not null && double.TryParse(asString, out double asStringDouble))
|
||||
return asStringDouble;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a key as a long, returning null on error
|
||||
/// </summary>
|
||||
/// <remarks>TODO: Add logic to convert SI suffixes and hex</remarks>
|
||||
/// TODO: Determine if this can be removed
|
||||
public long? ReadLong(string key)
|
||||
{
|
||||
if (!ValidateReadKey(key))
|
||||
return null;
|
||||
|
||||
long? asLong = Read<long?>(key);
|
||||
if (asLong is not null)
|
||||
return asLong;
|
||||
|
||||
int? asInt = Read<int?>(key);
|
||||
if (asInt is not null)
|
||||
return asInt;
|
||||
|
||||
short? asShort = Read<short?>(key);
|
||||
if (asShort is not null)
|
||||
return asShort;
|
||||
|
||||
string? asString = Read<string>(key);
|
||||
if (asString is not null && long.TryParse(asString, out long asStringLong))
|
||||
return asStringLong;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a key as a string, returning null on error
|
||||
/// </summary>
|
||||
public string? ReadString(string key)
|
||||
{
|
||||
if (!ValidateReadKey(key))
|
||||
return null;
|
||||
|
||||
string? asString = Read<string>(key);
|
||||
if (asString is not null)
|
||||
return asString;
|
||||
|
||||
string[]? asArray = Read<string[]>(key);
|
||||
if (asArray is not null)
|
||||
#if NETFRAMEWORK || NETSTANDARD2_0
|
||||
return string.Join(",", asArray);
|
||||
#else
|
||||
return string.Join(',', asArray);
|
||||
#endif
|
||||
|
||||
// TODO: Add byte array conversion here
|
||||
// TODO: Add byte array read helper
|
||||
|
||||
return this[key]!.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a key as a T[], returning null on error
|
||||
/// </summary>
|
||||
public T[]? ReadArray<T>(string key)
|
||||
{
|
||||
if (!ValidateReadKey(key))
|
||||
return null;
|
||||
|
||||
var items = Read<T[]>(key);
|
||||
if (items is not null)
|
||||
return items;
|
||||
|
||||
var single = Read<T>(key);
|
||||
if (single is not null)
|
||||
return [single];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a key as a string[], returning null on error
|
||||
/// </summary>
|
||||
/// TODO: Determine if this can be removed
|
||||
public string[]? ReadStringArray(string key)
|
||||
{
|
||||
if (!ValidateReadKey(key))
|
||||
return null;
|
||||
|
||||
string[]? asArray = Read<string[]>(key);
|
||||
if (asArray is not null)
|
||||
return asArray;
|
||||
|
||||
string? asString = Read<string>(key);
|
||||
if (asString is not null)
|
||||
return [asString];
|
||||
|
||||
asString = this[key]!.ToString();
|
||||
if (asString is not null)
|
||||
return [asString];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a key is valid for read
|
||||
/// </summary>
|
||||
private bool ValidateReadKey(string key)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key))
|
||||
return false;
|
||||
else if (!ContainsKey(key))
|
||||
return false;
|
||||
else if (this[key] is null)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Write
|
||||
|
||||
/// <summary>
|
||||
/// Remove a key, if possible
|
||||
/// </summary>
|
||||
public new bool Remove(string? fieldName)
|
||||
{
|
||||
// If the item or field name are missing, we can't do anything
|
||||
if (string.IsNullOrEmpty(fieldName))
|
||||
return false;
|
||||
|
||||
// If the key doesn't exist, then it's already removed
|
||||
if (!ContainsKey(fieldName!))
|
||||
return true;
|
||||
|
||||
// Remove the key
|
||||
base.Remove(fieldName!);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace a field from another item
|
||||
/// </summary>
|
||||
public bool Replace(DictionaryBase? from, string fieldName)
|
||||
{
|
||||
// If the source item is invalid
|
||||
if (from is null)
|
||||
return false;
|
||||
|
||||
// If the field name is missing, we can't do anything
|
||||
if (string.IsNullOrEmpty(fieldName))
|
||||
return false;
|
||||
|
||||
// If the types of the items are not the same, we can't do anything
|
||||
if (from.GetType() != GetType())
|
||||
return false;
|
||||
|
||||
// If the key doesn't exist in the source, we can't do anything
|
||||
if (!from.TryGetValue(fieldName!, out var value))
|
||||
return false;
|
||||
|
||||
// Set the key
|
||||
this[fieldName!] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a key as the specified type, returning false on error
|
||||
/// </summary>
|
||||
/// <param name="fieldName">Field to set</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <returns>True if the value was set, false otherwise</returns>
|
||||
public bool Write<T>(string fieldName, T? value)
|
||||
{
|
||||
// Invalid field cannot be processed
|
||||
if (fieldName is null)
|
||||
return false;
|
||||
|
||||
// Set the value based on the type
|
||||
this[fieldName] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace SabreTools.Data.Models.Metadata
|
||||
/// <summary>
|
||||
/// Format-agnostic representation of metadata header data
|
||||
/// </summary>
|
||||
public class Header : DictionaryBase, ICloneable, IEquatable<Header>
|
||||
public class Header : ICloneable, IEquatable<Header>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
@@ -37,6 +37,8 @@ namespace SabreTools.Data.Models.Metadata
|
||||
|
||||
public string? EmulatorVersion { get; set; }
|
||||
|
||||
public string? FileName { get; set; }
|
||||
|
||||
/// <remarks>(none|split|merged|nonmerged|fullmerged|device|full) "split"</remarks>
|
||||
public MergingFlag ForceMerging { get; set; }
|
||||
|
||||
@@ -135,6 +137,7 @@ namespace SabreTools.Data.Models.Metadata
|
||||
obj.Description = Description;
|
||||
obj.Email = Email;
|
||||
obj.EmulatorVersion = EmulatorVersion;
|
||||
obj.FileName = FileName;
|
||||
obj.ForceMerging = ForceMerging;
|
||||
obj.ForceNodump = ForceNodump;
|
||||
obj.ForcePacking = ForcePacking;
|
||||
@@ -231,6 +234,11 @@ namespace SabreTools.Data.Models.Metadata
|
||||
else if (EmulatorVersion is not null && !EmulatorVersion.Equals(other.EmulatorVersion, StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
if ((FileName is null) ^ (other.FileName is null))
|
||||
return false;
|
||||
else if (FileName is not null && !FileName.Equals(other.FileName, StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
if (ForceMerging != other.ForceMerging)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -4,13 +4,8 @@ using Newtonsoft.Json;
|
||||
namespace SabreTools.Data.Models.Metadata
|
||||
{
|
||||
[JsonObject("infosource"), XmlRoot("infosource")]
|
||||
public class InfoSource : DictionaryBase
|
||||
public class InfoSource
|
||||
{
|
||||
#region Keys
|
||||
|
||||
/// <remarks>string[]</remarks>
|
||||
public const string SourceKey = "source";
|
||||
|
||||
#endregion
|
||||
public string[]? Source { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace SabreTools.Data.Models.Metadata
|
||||
/// <summary>
|
||||
/// Format-agnostic representation of game, machine, and set data
|
||||
/// </summary>
|
||||
public class Machine : DictionaryBase, ICloneable, IEquatable<Machine>
|
||||
public class Machine : ICloneable, IEquatable<Machine>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace SabreTools.Data.Models.Metadata
|
||||
/// </summary>
|
||||
/// TODO: ICloneable
|
||||
/// TODO: IComparable<MetadataFile>
|
||||
public class MetadataFile : DictionaryBase
|
||||
public class MetadataFile
|
||||
{
|
||||
public Header? Header { get; set; }
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
||||
[Fact]
|
||||
public void ConvertFromMetadata_Empty()
|
||||
{
|
||||
Data.Models.Metadata.MetadataFile? item = [];
|
||||
Data.Models.Metadata.MetadataFile? item = new Data.Models.Metadata.MetadataFile();
|
||||
|
||||
DatFile datFile = new Formats.Logiqx(null, useGame: false);
|
||||
datFile.ConvertFromMetadata(item, "filename", indexId: 0, keep: true, statsOnly: false, filterRunner: null);
|
||||
@@ -211,6 +211,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
||||
Description = "description",
|
||||
Email = "email",
|
||||
EmulatorVersion = "emulatorversion",
|
||||
FileName = "filename",
|
||||
ForceMerging = Data.Models.Metadata.MergingFlag.Merged,
|
||||
ForceNodump = Data.Models.Metadata.NodumpFlag.Required,
|
||||
ForcePacking = Data.Models.Metadata.PackingFlag.Zip,
|
||||
@@ -549,7 +550,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
||||
{
|
||||
Endianness = Data.Models.Metadata.Endianness.Big,
|
||||
Name = "name",
|
||||
Rom = [[]],
|
||||
Rom = [new Data.Models.Metadata.Rom()],
|
||||
Size = 12345,
|
||||
Width = Data.Models.Metadata.Width.Long,
|
||||
};
|
||||
@@ -575,7 +576,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
||||
{
|
||||
return new Data.Models.Metadata.DiskArea
|
||||
{
|
||||
Disk = [[]],
|
||||
Disk = [new Data.Models.Metadata.Disk()],
|
||||
Name = "name",
|
||||
};
|
||||
}
|
||||
@@ -716,7 +717,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
||||
{
|
||||
DataArea = [CreateMetadataDataArea()],
|
||||
DiskArea = [CreateMetadataDiskArea()],
|
||||
DipSwitch = [[]],
|
||||
DipSwitch = [new Data.Models.Metadata.DipSwitch()],
|
||||
Feature = [CreateMetadataFeature()],
|
||||
Interface = "interface",
|
||||
Name = "name",
|
||||
|
||||
@@ -360,6 +360,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
||||
Assert.Equal("description", header.Description);
|
||||
Assert.Equal("email", header.Email);
|
||||
Assert.Equal("emulatorversion", header.EmulatorVersion);
|
||||
Assert.Equal("filename", header.FileName);
|
||||
Assert.Equal(Data.Models.Metadata.MergingFlag.Merged, header.ForceMerging);
|
||||
Assert.Equal(Data.Models.Metadata.NodumpFlag.Required, header.ForceNodump);
|
||||
Assert.Equal(Data.Models.Metadata.PackingFlag.Zip, header.ForcePacking);
|
||||
|
||||
@@ -239,7 +239,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
// Convert items in the machine
|
||||
if (item.Adjuster is not null)
|
||||
{
|
||||
var items = item.Adjuster ?? [];
|
||||
var items = item.Adjuster;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -251,7 +251,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Archive is not null)
|
||||
{
|
||||
var items = item.Archive ?? [];
|
||||
var items = item.Archive;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -263,7 +263,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.BiosSet is not null)
|
||||
{
|
||||
var items = item.BiosSet ?? [];
|
||||
var items = item.BiosSet;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -275,7 +275,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Chip is not null)
|
||||
{
|
||||
var items = item.Chip ?? [];
|
||||
var items = item.Chip;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -287,7 +287,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Configuration is not null)
|
||||
{
|
||||
var items = item.Configuration ?? [];
|
||||
var items = item.Configuration;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -299,7 +299,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Device is not null)
|
||||
{
|
||||
var items = item.Device ?? [];
|
||||
var items = item.Device;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -311,7 +311,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.DeviceRef is not null)
|
||||
{
|
||||
var items = item.DeviceRef ?? [];
|
||||
var items = item.DeviceRef;
|
||||
// Do not filter these due to later use
|
||||
Array.ForEach(items, item =>
|
||||
{
|
||||
@@ -323,7 +323,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.DipSwitch is not null)
|
||||
{
|
||||
var items = item.DipSwitch ?? [];
|
||||
var items = item.DipSwitch;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -335,7 +335,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Disk is not null)
|
||||
{
|
||||
var items = item.Disk ?? [];
|
||||
var items = item.Disk;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -347,7 +347,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Display is not null)
|
||||
{
|
||||
var items = item.Display ?? [];
|
||||
var items = item.Display;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -366,7 +366,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Dump is not null)
|
||||
{
|
||||
var items = item.Dump ?? [];
|
||||
var items = item.Dump;
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
{
|
||||
var datItem = new Rom(items[i], machine, source, i);
|
||||
@@ -391,7 +391,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Feature is not null)
|
||||
{
|
||||
var items = item.Feature ?? [];
|
||||
var items = item.Feature;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -403,7 +403,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Info is not null)
|
||||
{
|
||||
var items = item.Info ?? [];
|
||||
var items = item.Info;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -422,7 +422,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Media is not null)
|
||||
{
|
||||
var items = item.Media ?? [];
|
||||
var items = item.Media;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -434,13 +434,13 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Part is not null)
|
||||
{
|
||||
var items = item.Part ?? [];
|
||||
var items = item.Part;
|
||||
ProcessItems(items, machine, machineIndex: 0, source, sourceIndex, statsOnly, filterRunner);
|
||||
}
|
||||
|
||||
if (item.Port is not null)
|
||||
{
|
||||
var items = item.Port ?? [];
|
||||
var items = item.Port;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -452,7 +452,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.RamOption is not null)
|
||||
{
|
||||
var items = item.RamOption ?? [];
|
||||
var items = item.RamOption;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -464,7 +464,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Release is not null)
|
||||
{
|
||||
var items = item.Release ?? [];
|
||||
var items = item.Release;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -476,7 +476,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Rom is not null)
|
||||
{
|
||||
var items = item.Rom ?? [];
|
||||
var items = item.Rom;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -491,7 +491,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Sample is not null)
|
||||
{
|
||||
var items = item.Sample ?? [];
|
||||
var items = item.Sample;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -503,7 +503,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.SharedFeat is not null)
|
||||
{
|
||||
var items = item.SharedFeat ?? [];
|
||||
var items = item.SharedFeat;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -515,7 +515,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Slot is not null)
|
||||
{
|
||||
var items = item.Slot ?? [];
|
||||
var items = item.Slot;
|
||||
// Do not filter these due to later use
|
||||
Array.ForEach(items, item =>
|
||||
{
|
||||
@@ -527,7 +527,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.SoftwareList is not null)
|
||||
{
|
||||
var items = item.SoftwareList ?? [];
|
||||
var items = item.SoftwareList;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
@@ -546,7 +546,7 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
if (item.Video is not null)
|
||||
{
|
||||
var items = item.Video ?? [];
|
||||
var items = item.Video;
|
||||
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
|
||||
Array.ForEach(filtered, item =>
|
||||
{
|
||||
|
||||
@@ -270,25 +270,19 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
// Create the part in the dictionary, if needed
|
||||
if (!partItems.ContainsKey(partName))
|
||||
partItems[partName] = [];
|
||||
partItems[partName] = new();
|
||||
|
||||
// Copy over string values
|
||||
partItems[partName].Name = partName;
|
||||
if (partItems[partName].Interface == null)
|
||||
partItems[partName].Interface = partItem.Interface;
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(partItems[partName]);
|
||||
|
||||
// If the item has a DataArea mapping
|
||||
if (dataAreaMappings.TryGetValue(partItem, out (Data.Models.Metadata.DataArea, Data.Models.Metadata.Rom) dataAreaMap))
|
||||
{
|
||||
// Get the mapped items
|
||||
var (dataArea, romItem) = dataAreaMap;
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(romItem);
|
||||
|
||||
// Get the data area name and skip if there's none
|
||||
string? dataAreaName = dataArea.Name;
|
||||
if (dataAreaName is not null)
|
||||
@@ -306,16 +300,15 @@ namespace SabreTools.Metadata.DatFiles
|
||||
}
|
||||
else
|
||||
{
|
||||
aggregateDataArea = [];
|
||||
aggregateDataArea.Endianness = dataArea.Endianness;
|
||||
aggregateDataArea.Name = dataArea.Name;
|
||||
aggregateDataArea.Size = dataArea.Size;
|
||||
aggregateDataArea.Width = dataArea.Width;
|
||||
aggregateDataArea = new()
|
||||
{
|
||||
Endianness = dataArea.Endianness,
|
||||
Name = dataArea.Name,
|
||||
Size = dataArea.Size,
|
||||
Width = dataArea.Width,
|
||||
};
|
||||
}
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(aggregateDataArea);
|
||||
|
||||
// Get existing roms as a list
|
||||
var romsArr = aggregateDataArea.Rom ?? [];
|
||||
List<Data.Models.Metadata.Rom> roms = [.. romsArr];
|
||||
@@ -343,9 +336,6 @@ namespace SabreTools.Metadata.DatFiles
|
||||
// Get the mapped items
|
||||
var (diskArea, diskItem) = diskAreaMap;
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(diskItem);
|
||||
|
||||
// Get the disk area name and skip if there's none
|
||||
string? diskAreaName = diskArea.Name;
|
||||
if (diskAreaName is not null)
|
||||
@@ -363,13 +353,10 @@ namespace SabreTools.Metadata.DatFiles
|
||||
}
|
||||
else
|
||||
{
|
||||
aggregateDiskArea = [];
|
||||
aggregateDiskArea = new();
|
||||
aggregateDiskArea.Name = diskArea.Name;
|
||||
}
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(aggregateDiskArea);
|
||||
|
||||
// Get existing disks as a list
|
||||
var disksArr = aggregateDiskArea.Disk ?? [];
|
||||
List<Data.Models.Metadata.Disk> disks = [.. disksArr];
|
||||
@@ -398,9 +385,6 @@ namespace SabreTools.Metadata.DatFiles
|
||||
var dipSwitchesArr = partItems[partName].DipSwitch ?? [];
|
||||
List<Data.Models.Metadata.DipSwitch> dipSwitches = [.. dipSwitchesArr];
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(dipSwitchItem);
|
||||
|
||||
// Add the dipswitch
|
||||
dipSwitches.Add(dipSwitchItem);
|
||||
|
||||
@@ -415,9 +399,6 @@ namespace SabreTools.Metadata.DatFiles
|
||||
var featuresArr = partItems[partName].Feature ?? [];
|
||||
List<Data.Models.Metadata.Feature> features = [.. featuresArr];
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(featureItem);
|
||||
|
||||
// Add the feature
|
||||
features.Add(featureItem);
|
||||
|
||||
@@ -646,25 +627,19 @@ namespace SabreTools.Metadata.DatFiles
|
||||
|
||||
// Create the part in the dictionary, if needed
|
||||
if (!partItems.ContainsKey(partName))
|
||||
partItems[partName] = [];
|
||||
partItems[partName] = new();
|
||||
|
||||
// Copy over string values
|
||||
partItems[partName].Name = partName;
|
||||
if (partItems[partName].Interface == null)
|
||||
partItems[partName].Interface = partItem.Interface;
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(partItems[partName]);
|
||||
|
||||
// If the item has a DataArea mapping
|
||||
if (dataAreaMappings.TryGetValue(partItem, out (Data.Models.Metadata.DataArea, Data.Models.Metadata.Rom) dataAreaMap))
|
||||
{
|
||||
// Get the mapped items
|
||||
var (dataArea, romItem) = dataAreaMap;
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(romItem);
|
||||
|
||||
// Get the data area name and skip if there's none
|
||||
string? dataAreaName = dataArea.Name;
|
||||
if (dataAreaName is not null)
|
||||
@@ -682,16 +657,13 @@ namespace SabreTools.Metadata.DatFiles
|
||||
}
|
||||
else
|
||||
{
|
||||
aggregateDataArea = [];
|
||||
aggregateDataArea = new();
|
||||
aggregateDataArea.Endianness = dataArea.Endianness;
|
||||
aggregateDataArea.Name = dataArea.Name;
|
||||
aggregateDataArea.Size = dataArea.Size;
|
||||
aggregateDataArea.Width = dataArea.Width;
|
||||
}
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(aggregateDataArea);
|
||||
|
||||
// Get existing roms as a list
|
||||
var romsArr = aggregateDataArea.Rom ?? [];
|
||||
List<Data.Models.Metadata.Rom> roms = [.. romsArr];
|
||||
@@ -719,9 +691,6 @@ namespace SabreTools.Metadata.DatFiles
|
||||
// Get the mapped items
|
||||
var (diskArea, diskItem) = diskAreaMap;
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(diskItem);
|
||||
|
||||
// Get the disk area name and skip if there's none
|
||||
string? diskAreaName = diskArea.Name;
|
||||
if (diskAreaName is not null)
|
||||
@@ -739,13 +708,10 @@ namespace SabreTools.Metadata.DatFiles
|
||||
}
|
||||
else
|
||||
{
|
||||
aggregateDiskArea = [];
|
||||
aggregateDiskArea = new();
|
||||
aggregateDiskArea.Name = diskArea.Name;
|
||||
}
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(aggregateDiskArea);
|
||||
|
||||
// Get existing disks as a list
|
||||
var disksArr = aggregateDiskArea.Disk ?? [];
|
||||
List<Data.Models.Metadata.Disk> disks = [.. disksArr];
|
||||
@@ -774,9 +740,6 @@ namespace SabreTools.Metadata.DatFiles
|
||||
var dipSwitchesArr = partItems[partName].DipSwitch ?? [];
|
||||
List<Data.Models.Metadata.DipSwitch> dipSwitches = [.. dipSwitchesArr];
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(dipSwitchItem);
|
||||
|
||||
// Add the dipswitch
|
||||
dipSwitches.Add(dipSwitchItem);
|
||||
|
||||
@@ -791,9 +754,6 @@ namespace SabreTools.Metadata.DatFiles
|
||||
var featuresArr = partItems[partName].Feature ?? [];
|
||||
List<Data.Models.Metadata.Feature> features = [.. featuresArr];
|
||||
|
||||
// Clear any empty fields
|
||||
ClearEmptyKeys(featureItem);
|
||||
|
||||
// Add the feature
|
||||
features.Add(featureItem);
|
||||
|
||||
@@ -953,19 +913,6 @@ namespace SabreTools.Metadata.DatFiles
|
||||
return romItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear empty keys from a DictionaryBase object
|
||||
/// </summary>
|
||||
private static void ClearEmptyKeys(Data.Models.Metadata.DictionaryBase obj)
|
||||
{
|
||||
string[] fieldNames = [.. obj.Keys];
|
||||
foreach (string fieldName in fieldNames)
|
||||
{
|
||||
if (obj[fieldName] is null)
|
||||
obj.Remove(fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,10 +96,11 @@ namespace SabreTools.Metadata.DatFiles
|
||||
set => _internal.EmulatorVersion = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// External name of the DAT
|
||||
/// </summary>
|
||||
public string? FileName { get; set; }
|
||||
public string? FileName
|
||||
{
|
||||
get => _internal.FileName;
|
||||
set => _internal.FileName = value;
|
||||
}
|
||||
|
||||
public MergingFlag ForceMerging
|
||||
{
|
||||
@@ -332,7 +333,6 @@ namespace SabreTools.Metadata.DatFiles
|
||||
public object Clone() => new DatHeader(GetInternalClone())
|
||||
{
|
||||
DatFormat = DatFormat,
|
||||
FileName = FileName,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace SabreTools.Metadata.DatItems.Test
|
||||
/// <inheritdoc/>
|
||||
public override TestDatItemModel GetInternalClone()
|
||||
{
|
||||
return (_internal as TestDatItemModel)?.Clone() as TestDatItemModel ?? [];
|
||||
return (_internal as TestDatItemModel)?.Clone() as TestDatItemModel ?? new();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Adjuster GetInternalClone()
|
||||
{
|
||||
var adjusterItem = (_internal as Data.Models.Metadata.Adjuster)?.Clone() as Data.Models.Metadata.Adjuster ?? [];
|
||||
var adjusterItem = (_internal as Data.Models.Metadata.Adjuster)?.Clone() as Data.Models.Metadata.Adjuster ?? new();
|
||||
|
||||
if (Condition is not null)
|
||||
adjusterItem.Condition = Condition.GetInternalClone();
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Analog GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Analog)?.Clone() as Data.Models.Metadata.Analog ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Analog)?.Clone() as Data.Models.Metadata.Analog ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Archive GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Archive)?.Clone() as Data.Models.Metadata.Archive ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Archive)?.Clone() as Data.Models.Metadata.Archive ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.BiosSet GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.BiosSet)?.Clone() as Data.Models.Metadata.BiosSet ?? [];
|
||||
=> (_internal as Data.Models.Metadata.BiosSet)?.Clone() as Data.Models.Metadata.BiosSet ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Blank GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Blank)?.Clone() as Data.Models.Metadata.Blank ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Blank)?.Clone() as Data.Models.Metadata.Blank ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Chip GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Chip)?.Clone() as Data.Models.Metadata.Chip ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Chip)?.Clone() as Data.Models.Metadata.Chip ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Condition GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Condition)?.Clone() as Data.Models.Metadata.Condition ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Condition)?.Clone() as Data.Models.Metadata.Condition ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.ConfLocation GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.ConfLocation)?.Clone() as Data.Models.Metadata.ConfLocation ?? [];
|
||||
=> (_internal as Data.Models.Metadata.ConfLocation)?.Clone() as Data.Models.Metadata.ConfLocation ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.ConfSetting GetInternalClone()
|
||||
{
|
||||
var confSettingItem = (_internal as Data.Models.Metadata.ConfSetting)?.Clone() as Data.Models.Metadata.ConfSetting ?? [];
|
||||
var confSettingItem = (_internal as Data.Models.Metadata.ConfSetting)?.Clone() as Data.Models.Metadata.ConfSetting ?? new();
|
||||
|
||||
if (Condition is not null)
|
||||
confSettingItem.Condition = Condition.GetInternalClone();
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Configuration GetInternalClone()
|
||||
{
|
||||
var configurationItem = (_internal as Data.Models.Metadata.Configuration)?.Clone() as Data.Models.Metadata.Configuration ?? [];
|
||||
var configurationItem = (_internal as Data.Models.Metadata.Configuration)?.Clone() as Data.Models.Metadata.Configuration ?? new();
|
||||
|
||||
if (Condition is not null)
|
||||
configurationItem.Condition = Condition.GetInternalClone();
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Control GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Control)?.Clone() as Data.Models.Metadata.Control ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Control)?.Clone() as Data.Models.Metadata.Control ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
public override Data.Models.Metadata.DataArea GetInternalClone()
|
||||
{
|
||||
var partItem = (_internal as Data.Models.Metadata.DataArea)?.Clone() as Data.Models.Metadata.DataArea ?? [];
|
||||
var partItem = (_internal as Data.Models.Metadata.DataArea)?.Clone() as Data.Models.Metadata.DataArea ?? new();
|
||||
|
||||
if (Rom is not null)
|
||||
partItem.Rom = Array.ConvertAll(Rom, rom => rom.GetInternalClone());
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Device GetInternalClone()
|
||||
{
|
||||
var deviceItem = (_internal as Data.Models.Metadata.Device)?.Clone() as Data.Models.Metadata.Device ?? [];
|
||||
var deviceItem = (_internal as Data.Models.Metadata.Device)?.Clone() as Data.Models.Metadata.Device ?? new();
|
||||
|
||||
deviceItem.DeviceType = DeviceType;
|
||||
deviceItem.FixedImage = FixedImage;
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.DeviceRef GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.DeviceRef)?.Clone() as Data.Models.Metadata.DeviceRef ?? [];
|
||||
=> (_internal as Data.Models.Metadata.DeviceRef)?.Clone() as Data.Models.Metadata.DeviceRef ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.DipLocation GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.DipLocation)?.Clone() as Data.Models.Metadata.DipLocation ?? [];
|
||||
=> (_internal as Data.Models.Metadata.DipLocation)?.Clone() as Data.Models.Metadata.DipLocation ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.DipSwitch GetInternalClone()
|
||||
{
|
||||
var dipSwitchItem = (_internal as Data.Models.Metadata.DipSwitch)?.Clone() as Data.Models.Metadata.DipSwitch ?? [];
|
||||
var dipSwitchItem = (_internal as Data.Models.Metadata.DipSwitch)?.Clone() as Data.Models.Metadata.DipSwitch ?? new();
|
||||
|
||||
if (Condition is not null)
|
||||
dipSwitchItem.Condition = Condition.GetInternalClone();
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.DipValue GetInternalClone()
|
||||
{
|
||||
var dipValueItem = (_internal as Data.Models.Metadata.DipValue)?.Clone() as Data.Models.Metadata.DipValue ?? [];
|
||||
var dipValueItem = (_internal as Data.Models.Metadata.DipValue)?.Clone() as Data.Models.Metadata.DipValue ?? new();
|
||||
|
||||
if (Condition is not null)
|
||||
dipValueItem.Condition = Condition.GetInternalClone();
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Disk GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Disk)?.Clone() as Data.Models.Metadata.Disk ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Disk)?.Clone() as Data.Models.Metadata.Disk ?? new();
|
||||
|
||||
/// <summary>
|
||||
/// Convert a disk to the closest Rom approximation
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
public override Data.Models.Metadata.DiskArea GetInternalClone()
|
||||
{
|
||||
var partItem = (_internal as Data.Models.Metadata.DiskArea)?.Clone() as Data.Models.Metadata.DiskArea ?? [];
|
||||
var partItem = (_internal as Data.Models.Metadata.DiskArea)?.Clone() as Data.Models.Metadata.DiskArea ?? new();
|
||||
|
||||
if (Disk is not null)
|
||||
partItem.Disk = Array.ConvertAll(Disk, rom => rom.GetInternalClone());
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Display GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Display)?.Clone() as Data.Models.Metadata.Display ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Display)?.Clone() as Data.Models.Metadata.Display ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Driver GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Driver)?.Clone() as Data.Models.Metadata.Driver ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Driver)?.Clone() as Data.Models.Metadata.Driver ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Extension GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Extension)?.Clone() as Data.Models.Metadata.Extension ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Extension)?.Clone() as Data.Models.Metadata.Extension ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Feature GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Feature)?.Clone() as Data.Models.Metadata.Feature ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Feature)?.Clone() as Data.Models.Metadata.Feature ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Info GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Info)?.Clone() as Data.Models.Metadata.Info ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Info)?.Clone() as Data.Models.Metadata.Info ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Input GetInternalClone()
|
||||
{
|
||||
var inputItem = (_internal as Data.Models.Metadata.Input)?.Clone() as Data.Models.Metadata.Input ?? [];
|
||||
var inputItem = (_internal as Data.Models.Metadata.Input)?.Clone() as Data.Models.Metadata.Input ?? new();
|
||||
|
||||
if (Control is not null)
|
||||
inputItem.Control = Array.ConvertAll(Control, control => control.GetInternalClone());
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Instance GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Instance)?.Clone() as Data.Models.Metadata.Instance ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Instance)?.Clone() as Data.Models.Metadata.Instance ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Media GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Media)?.Clone() as Data.Models.Metadata.Media ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Media)?.Clone() as Data.Models.Metadata.Media ?? new();
|
||||
|
||||
/// <summary>
|
||||
/// Convert a media to the closest Rom approximation
|
||||
|
||||
@@ -35,6 +35,6 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
/// Internal Original model
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
private readonly Data.Models.Metadata.Original _internal = [];
|
||||
private readonly Data.Models.Metadata.Original _internal = new();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Part GetInternalClone()
|
||||
{
|
||||
var partItem = (_internal as Data.Models.Metadata.Part)?.Clone() as Data.Models.Metadata.Part ?? [];
|
||||
var partItem = (_internal as Data.Models.Metadata.Part)?.Clone() as Data.Models.Metadata.Part ?? new();
|
||||
|
||||
if (DataArea is not null)
|
||||
partItem.DataArea = Array.ConvertAll(DataArea, dataArea => dataArea.GetInternalClone());
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Feature GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Feature)?.Clone() as Data.Models.Metadata.Feature ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Feature)?.Clone() as Data.Models.Metadata.Feature ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Port GetInternalClone()
|
||||
{
|
||||
var portItem = (_internal as Data.Models.Metadata.Port)?.Clone() as Data.Models.Metadata.Port ?? [];
|
||||
var portItem = (_internal as Data.Models.Metadata.Port)?.Clone() as Data.Models.Metadata.Port ?? new();
|
||||
|
||||
if (Analog is not null)
|
||||
portItem.Analog = Array.ConvertAll(Analog, analog => analog.GetInternalClone());
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.RamOption GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.RamOption)?.Clone() as Data.Models.Metadata.RamOption ?? [];
|
||||
=> (_internal as Data.Models.Metadata.RamOption)?.Clone() as Data.Models.Metadata.RamOption ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Release GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Release)?.Clone() as Data.Models.Metadata.Release ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Release)?.Clone() as Data.Models.Metadata.Release ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.ReleaseDetails GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.ReleaseDetails)?.Clone() as Data.Models.Metadata.ReleaseDetails ?? [];
|
||||
=> (_internal as Data.Models.Metadata.ReleaseDetails)?.Clone() as Data.Models.Metadata.ReleaseDetails ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -899,7 +899,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Rom GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Rom)?.Clone() as Data.Models.Metadata.Rom ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Rom)?.Clone() as Data.Models.Metadata.Rom ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Sample GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Sample)?.Clone() as Data.Models.Metadata.Sample ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Sample)?.Clone() as Data.Models.Metadata.Sample ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Serials GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Serials)?.Clone() as Data.Models.Metadata.Serials ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Serials)?.Clone() as Data.Models.Metadata.Serials ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.SharedFeat GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.SharedFeat)?.Clone() as Data.Models.Metadata.SharedFeat ?? [];
|
||||
=> (_internal as Data.Models.Metadata.SharedFeat)?.Clone() as Data.Models.Metadata.SharedFeat ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Slot GetInternalClone()
|
||||
{
|
||||
var slotItem = (_internal as Data.Models.Metadata.Slot)?.Clone() as Data.Models.Metadata.Slot ?? [];
|
||||
var slotItem = (_internal as Data.Models.Metadata.Slot)?.Clone() as Data.Models.Metadata.Slot ?? new();
|
||||
|
||||
if (SlotOption is not null)
|
||||
slotItem.SlotOption = Array.ConvertAll(SlotOption, slotOption => slotOption.GetInternalClone());
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.SlotOption GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.SlotOption)?.Clone() as Data.Models.Metadata.SlotOption ?? [];
|
||||
=> (_internal as Data.Models.Metadata.SlotOption)?.Clone() as Data.Models.Metadata.SlotOption ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.SoftwareList GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.SoftwareList)?.Clone() as Data.Models.Metadata.SoftwareList ?? [];
|
||||
=> (_internal as Data.Models.Metadata.SoftwareList)?.Clone() as Data.Models.Metadata.SoftwareList ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.Sound GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.Sound)?.Clone() as Data.Models.Metadata.Sound ?? [];
|
||||
=> (_internal as Data.Models.Metadata.Sound)?.Clone() as Data.Models.Metadata.Sound ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ namespace SabreTools.Metadata.DatItems.Formats
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Data.Models.Metadata.SourceDetails GetInternalClone()
|
||||
=> (_internal as Data.Models.Metadata.SourceDetails)?.Clone() as Data.Models.Metadata.SourceDetails ?? [];
|
||||
=> (_internal as Data.Models.Metadata.SourceDetails)?.Clone() as Data.Models.Metadata.SourceDetails ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -386,12 +386,12 @@ namespace SabreTools.Metadata.DatItems
|
||||
|
||||
public Machine()
|
||||
{
|
||||
_internal = [];
|
||||
_internal = new();
|
||||
}
|
||||
|
||||
public Machine(Data.Models.Metadata.Machine machine)
|
||||
{
|
||||
_internal = machine.Clone() as Data.Models.Metadata.Machine ?? [];
|
||||
_internal = machine.Clone() as Data.Models.Metadata.Machine ?? new();
|
||||
|
||||
// Clear all lists
|
||||
_internal.Adjuster = null;
|
||||
@@ -449,7 +449,7 @@ namespace SabreTools.Metadata.DatItems
|
||||
/// <summary>
|
||||
/// Get a clone of the current internal model
|
||||
/// </summary>
|
||||
public Data.Models.Metadata.Machine GetInternalClone() => (_internal.Clone() as Data.Models.Metadata.Machine) ?? [];
|
||||
public Data.Models.Metadata.Machine GetInternalClone() => (_internal.Clone() as Data.Models.Metadata.Machine) ?? new();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using SabreTools.Data.Models.Metadata;
|
||||
|
||||
namespace SabreTools.Metadata.Filter
|
||||
{
|
||||
@@ -65,14 +64,14 @@ namespace SabreTools.Metadata.Filter
|
||||
#region Matching
|
||||
|
||||
/// <summary>
|
||||
/// Determine if a DictionaryBase object matches the group
|
||||
/// Determine if a object matches the group
|
||||
/// </summary>
|
||||
public bool Matches(DictionaryBase dictionaryBase)
|
||||
public bool Matches(object obj)
|
||||
{
|
||||
return GroupType switch
|
||||
{
|
||||
GroupType.AND => MatchesAnd(dictionaryBase),
|
||||
GroupType.OR => MatchesOr(dictionaryBase),
|
||||
GroupType.AND => MatchesAnd(obj),
|
||||
GroupType.OR => MatchesOr(obj),
|
||||
|
||||
GroupType.NONE => false,
|
||||
_ => false,
|
||||
@@ -82,13 +81,13 @@ namespace SabreTools.Metadata.Filter
|
||||
/// <summary>
|
||||
/// Determines if a value matches all filters
|
||||
/// </summary>
|
||||
private bool MatchesAnd(DictionaryBase dictionaryBase)
|
||||
private bool MatchesAnd(object obj)
|
||||
{
|
||||
// Run standalone filters
|
||||
foreach (var filter in _subfilters)
|
||||
{
|
||||
// One failed match fails the group
|
||||
if (!filter.Matches(dictionaryBase))
|
||||
if (!filter.Matches(obj))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -96,7 +95,7 @@ namespace SabreTools.Metadata.Filter
|
||||
foreach (var group in _subgroups)
|
||||
{
|
||||
// One failed match fails the group
|
||||
if (!group.Matches(dictionaryBase))
|
||||
if (!group.Matches(obj))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -106,13 +105,13 @@ namespace SabreTools.Metadata.Filter
|
||||
/// <summary>
|
||||
/// Determines if a value matches any filters
|
||||
/// </summary>
|
||||
private bool MatchesOr(DictionaryBase dictionaryBase)
|
||||
private bool MatchesOr(object obj)
|
||||
{
|
||||
// Run standalone filters
|
||||
foreach (var filter in _subfilters)
|
||||
{
|
||||
// One successful match passes the group
|
||||
if (filter.Matches(dictionaryBase))
|
||||
if (filter.Matches(obj))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -120,7 +119,7 @@ namespace SabreTools.Metadata.Filter
|
||||
foreach (var group in _subgroups)
|
||||
{
|
||||
// One successful match passes the group
|
||||
if (group.Matches(dictionaryBase))
|
||||
if (group.Matches(obj))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,18 +54,18 @@ namespace SabreTools.Metadata.Filter
|
||||
#region Matching
|
||||
|
||||
/// <summary>
|
||||
/// Determine if a DictionaryBase object matches the key and value
|
||||
/// Determine if a object matches the key and value
|
||||
/// </summary>
|
||||
public bool Matches(DictionaryBase dictionaryBase)
|
||||
public bool Matches(object obj)
|
||||
{
|
||||
return Operation switch
|
||||
{
|
||||
Operation.Equals => MatchesEqual(dictionaryBase),
|
||||
Operation.NotEquals => MatchesNotEqual(dictionaryBase),
|
||||
Operation.GreaterThan => MatchesGreaterThan(dictionaryBase),
|
||||
Operation.GreaterThanOrEqual => MatchesGreaterThanOrEqual(dictionaryBase),
|
||||
Operation.LessThan => MatchesLessThan(dictionaryBase),
|
||||
Operation.LessThanOrEqual => MatchesLessThanOrEqual(dictionaryBase),
|
||||
Operation.Equals => MatchesEqual(obj),
|
||||
Operation.NotEquals => MatchesNotEqual(obj),
|
||||
Operation.GreaterThan => MatchesGreaterThan(obj),
|
||||
Operation.GreaterThanOrEqual => MatchesGreaterThanOrEqual(obj),
|
||||
Operation.LessThan => MatchesLessThan(obj),
|
||||
Operation.LessThanOrEqual => MatchesLessThanOrEqual(obj),
|
||||
|
||||
Operation.NONE => false,
|
||||
_ => false,
|
||||
@@ -75,10 +75,10 @@ namespace SabreTools.Metadata.Filter
|
||||
/// <summary>
|
||||
/// Determines if a value matches exactly
|
||||
/// </summary>
|
||||
private bool MatchesEqual(DictionaryBase dictionaryBase)
|
||||
private bool MatchesEqual(object obj)
|
||||
{
|
||||
// Process the check value
|
||||
if (!GetCheckValue(dictionaryBase, Key.FieldName, out string? checkValue))
|
||||
if (!GetCheckValue(obj, Key.FieldName, out string? checkValue))
|
||||
return string.IsNullOrEmpty(Value);
|
||||
|
||||
// If a null value is expected
|
||||
@@ -117,10 +117,10 @@ namespace SabreTools.Metadata.Filter
|
||||
/// <summary>
|
||||
/// Determines if a value does not match exactly
|
||||
/// </summary>
|
||||
private bool MatchesNotEqual(DictionaryBase dictionaryBase)
|
||||
private bool MatchesNotEqual(object obj)
|
||||
{
|
||||
// Process the check value
|
||||
if (!GetCheckValue(dictionaryBase, Key.FieldName, out string? checkValue))
|
||||
if (!GetCheckValue(obj, Key.FieldName, out string? checkValue))
|
||||
return string.IsNullOrEmpty(Value);
|
||||
|
||||
// If a null value is expected
|
||||
@@ -159,10 +159,10 @@ namespace SabreTools.Metadata.Filter
|
||||
/// <summary>
|
||||
/// Determines if a value is strictly greater than
|
||||
/// </summary>
|
||||
private bool MatchesGreaterThan(DictionaryBase dictionaryBase)
|
||||
private bool MatchesGreaterThan(object obj)
|
||||
{
|
||||
// Process the check value
|
||||
if (!GetCheckValue(dictionaryBase, Key.FieldName, out string? checkValue))
|
||||
if (!GetCheckValue(obj, Key.FieldName, out string? checkValue))
|
||||
return string.IsNullOrEmpty(Value);
|
||||
|
||||
// Null is always failure
|
||||
@@ -191,10 +191,10 @@ namespace SabreTools.Metadata.Filter
|
||||
/// <summary>
|
||||
/// Determines if a value is greater than or equal
|
||||
/// </summary>
|
||||
private bool MatchesGreaterThanOrEqual(DictionaryBase dictionaryBase)
|
||||
private bool MatchesGreaterThanOrEqual(object obj)
|
||||
{
|
||||
// Process the check value
|
||||
if (!GetCheckValue(dictionaryBase, Key.FieldName, out string? checkValue))
|
||||
if (!GetCheckValue(obj, Key.FieldName, out string? checkValue))
|
||||
return string.IsNullOrEmpty(Value);
|
||||
|
||||
// Null is always failure
|
||||
@@ -223,10 +223,10 @@ namespace SabreTools.Metadata.Filter
|
||||
/// <summary>
|
||||
/// Determines if a value is strictly less than
|
||||
/// </summary>
|
||||
private bool MatchesLessThan(DictionaryBase dictionaryBase)
|
||||
private bool MatchesLessThan(object obj)
|
||||
{
|
||||
// Process the check value
|
||||
if (!GetCheckValue(dictionaryBase, Key.FieldName, out string? checkValue))
|
||||
if (!GetCheckValue(obj, Key.FieldName, out string? checkValue))
|
||||
return string.IsNullOrEmpty(Value);
|
||||
|
||||
// Null is always failure
|
||||
@@ -255,10 +255,10 @@ namespace SabreTools.Metadata.Filter
|
||||
/// <summary>
|
||||
/// Determines if a value is less than or equal
|
||||
/// </summary>
|
||||
private bool MatchesLessThanOrEqual(DictionaryBase dictionaryBase)
|
||||
private bool MatchesLessThanOrEqual(object obj)
|
||||
{
|
||||
// Process the check value
|
||||
if (!GetCheckValue(dictionaryBase, Key.FieldName, out string? checkValue))
|
||||
if (!GetCheckValue(obj, Key.FieldName, out string? checkValue))
|
||||
return string.IsNullOrEmpty(Value);
|
||||
|
||||
// Null is always failure
|
||||
@@ -334,12 +334,13 @@ namespace SabreTools.Metadata.Filter
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the check value for a field from a DictionaryBase
|
||||
/// Get the check value for a field
|
||||
/// </summary>
|
||||
private static bool GetCheckValue(DictionaryBase dictionaryBase, string fieldName, out string? checkValue)
|
||||
/// TODO: Figure out how to not have this hardcoded
|
||||
private static bool GetCheckValue(object obj, string fieldName, out string? checkValue)
|
||||
{
|
||||
// Handle type-specific properties
|
||||
switch (dictionaryBase)
|
||||
switch (obj)
|
||||
{
|
||||
case Adjuster item when fieldName == "default":
|
||||
checkValue = item.Default.FromYesNo();
|
||||
@@ -802,6 +803,9 @@ namespace SabreTools.Metadata.Filter
|
||||
case Header item when fieldName == "emulatorversion":
|
||||
checkValue = item.EmulatorVersion;
|
||||
return true;
|
||||
case Header item when fieldName == "filename":
|
||||
checkValue = item.FileName;
|
||||
return true;
|
||||
case Header item when fieldName == "forcemerging":
|
||||
checkValue = item.ForceMerging.AsStringValue();
|
||||
return true;
|
||||
@@ -1689,15 +1693,8 @@ namespace SabreTools.Metadata.Filter
|
||||
}
|
||||
|
||||
// If the key doesn't exist, we count it as null
|
||||
if (!dictionaryBase.ContainsKey(fieldName))
|
||||
{
|
||||
checkValue = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the value in the dictionary is null
|
||||
checkValue = dictionaryBase.ReadString(fieldName);
|
||||
return true;
|
||||
checkValue = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -30,15 +30,15 @@ namespace SabreTools.Metadata.Filter
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run filtering on a DictionaryBase item
|
||||
/// Run filtering on an item
|
||||
/// </summary>
|
||||
public bool Run(DictionaryBase dictionaryBase)
|
||||
public bool Run(object obj)
|
||||
{
|
||||
string? itemName = dictionaryBase switch
|
||||
string? itemName = obj switch
|
||||
{
|
||||
Header => "header",
|
||||
Machine => "machine",
|
||||
DatItem => TypeHelper.GetXmlRootAttributeElementName(dictionaryBase.GetType()),
|
||||
DatItem => TypeHelper.GetXmlRootAttributeElementName(obj.GetType()),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace SabreTools.Metadata.Filter
|
||||
continue;
|
||||
|
||||
// If we don't get a match, it's a failure
|
||||
bool matchOne = Filters[filterKey].Matches(dictionaryBase);
|
||||
bool matchOne = Filters[filterKey].Matches(obj);
|
||||
if (!matchOne)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,257 +0,0 @@
|
||||
using SabreTools.Data.Models.Metadata;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.Metadata.Test
|
||||
{
|
||||
public class ModelBackedItemTests
|
||||
{
|
||||
#region Private Testing Classes
|
||||
|
||||
/// <summary>
|
||||
/// Testing implementation of DictionaryBase
|
||||
/// </summary>
|
||||
private class TestDictionaryBase : DictionaryBase
|
||||
{
|
||||
public const string NameKey = "__NAME__";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Testing implementation of ModelBackedItem
|
||||
/// </summary>
|
||||
private class TestModelBackedItem : ModelBackedItem<TestDictionaryBase>
|
||||
{
|
||||
#region Comparision Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(ModelBackedItem? other)
|
||||
{
|
||||
// If other is null
|
||||
if (other is null)
|
||||
return false;
|
||||
|
||||
// If the type is mismatched
|
||||
if (other is not TestModelBackedItem otherItem)
|
||||
return false;
|
||||
|
||||
// Compare internal models
|
||||
return _internal.Equals(otherItem._internal);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(ModelBackedItem<TestDictionaryBase>? other)
|
||||
{
|
||||
// If other is null
|
||||
if (other is null)
|
||||
return false;
|
||||
|
||||
// If the type is mismatched
|
||||
if (other is not TestModelBackedItem otherItem)
|
||||
return false;
|
||||
|
||||
// Compare internal models
|
||||
return _internal.Equals(otherItem._internal);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alternate testing implementation of ModelBackedItem
|
||||
/// </summary>
|
||||
private class TestModelAltBackedItem : ModelBackedItem<TestDictionaryBase>
|
||||
{
|
||||
#region Comparision Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(ModelBackedItem? other)
|
||||
{
|
||||
// If other is null
|
||||
if (other is null)
|
||||
return false;
|
||||
|
||||
// If the type is mismatched
|
||||
if (other is not TestModelAltBackedItem otherItem)
|
||||
return false;
|
||||
|
||||
// Compare internal models
|
||||
return _internal[TestDictionaryBase.NameKey] == otherItem._internal[TestDictionaryBase.NameKey];
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(ModelBackedItem<TestDictionaryBase>? other)
|
||||
{
|
||||
// If other is null
|
||||
if (other is null)
|
||||
return false;
|
||||
|
||||
// If the type is mismatched
|
||||
if (other is not TestModelAltBackedItem otherItem)
|
||||
return false;
|
||||
|
||||
// Compare internal models
|
||||
return _internal[TestDictionaryBase.NameKey] == otherItem._internal[TestDictionaryBase.NameKey];
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Remove
|
||||
|
||||
[Fact]
|
||||
public void Remove_NullItem_False()
|
||||
{
|
||||
TestModelBackedItem? modelBackedItem = null;
|
||||
string? fieldName = TestDictionaryBase.NameKey;
|
||||
bool? actual = modelBackedItem?.Remove(fieldName);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Remove_EmptyFieldName_False()
|
||||
{
|
||||
var modelBackedItem = new TestModelBackedItem();
|
||||
string? fieldName = string.Empty;
|
||||
bool actual = modelBackedItem.Remove(fieldName);
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Remove_MissingKey_True()
|
||||
{
|
||||
var modelBackedItem = new TestModelBackedItem();
|
||||
string? fieldName = TestDictionaryBase.NameKey;
|
||||
bool actual = modelBackedItem.Remove(fieldName);
|
||||
Assert.True(actual);
|
||||
Assert.Null(modelBackedItem.ReadString(fieldName));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Remove_ValidKey_True()
|
||||
{
|
||||
var modelBackedItem = new TestModelBackedItem();
|
||||
modelBackedItem.Write(TestDictionaryBase.NameKey, "value");
|
||||
string? fieldName = TestDictionaryBase.NameKey;
|
||||
bool actual = modelBackedItem.Remove(fieldName);
|
||||
Assert.True(actual);
|
||||
Assert.Null(modelBackedItem.ReadString(fieldName));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Replace
|
||||
|
||||
[Fact]
|
||||
public void Replace_NullFrom_False()
|
||||
{
|
||||
TestModelBackedItem? from = null;
|
||||
var to = new TestModelBackedItem();
|
||||
string? fieldName = TestDictionaryBase.NameKey;
|
||||
bool actual = to.Replace(from, fieldName);
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Replace_NullTo_False()
|
||||
{
|
||||
TestModelBackedItem? from = null;
|
||||
TestModelBackedItem? to = new TestModelBackedItem();
|
||||
string? fieldName = TestDictionaryBase.NameKey;
|
||||
bool actual = to.Replace(from, fieldName);
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Replace_EmptyFieldName_False()
|
||||
{
|
||||
TestModelBackedItem? from = new TestModelBackedItem();
|
||||
TestModelBackedItem? to = new TestModelBackedItem();
|
||||
string? fieldName = string.Empty;
|
||||
bool actual = to.Replace(from, fieldName);
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Replace_MissingKey_False()
|
||||
{
|
||||
TestModelBackedItem? from = new TestModelBackedItem();
|
||||
TestModelBackedItem? to = new TestModelBackedItem();
|
||||
string? fieldName = TestDictionaryBase.NameKey;
|
||||
bool actual = to.Replace(from, fieldName);
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Replace_ValidKey_True()
|
||||
{
|
||||
TestModelBackedItem? from = new TestModelBackedItem();
|
||||
from.Write(TestDictionaryBase.NameKey, "value");
|
||||
TestModelBackedItem? to = new TestModelBackedItem();
|
||||
string? fieldName = TestDictionaryBase.NameKey;
|
||||
bool actual = to.Replace(from, fieldName);
|
||||
Assert.True(actual);
|
||||
Assert.Equal("value", to.ReadString(TestDictionaryBase.NameKey));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region WriteWithValidation
|
||||
|
||||
[Fact]
|
||||
public void WriteWithValidation_NullItem_False()
|
||||
{
|
||||
TestModelBackedItem? modelBackedItem = null;
|
||||
string? fieldName = TestDictionaryBase.NameKey;
|
||||
object value = "value";
|
||||
bool? actual = modelBackedItem?.WriteWithValidation(fieldName, value);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WriteWithValidation_EmptyFieldName_False()
|
||||
{
|
||||
TestModelBackedItem? modelBackedItem = new TestModelBackedItem();
|
||||
string? fieldName = string.Empty;
|
||||
object value = "value";
|
||||
bool actual = modelBackedItem.WriteWithValidation(fieldName, value);
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WriteWithValidation_MissingKey_False()
|
||||
{
|
||||
TestModelBackedItem? modelBackedItem = new TestModelBackedItem();
|
||||
string? fieldName = "sha1";
|
||||
object value = "value";
|
||||
bool actual = modelBackedItem.WriteWithValidation(fieldName, value);
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WriteWithValidation_InvalidKey_True()
|
||||
{
|
||||
TestModelBackedItem? modelBackedItem = new TestModelBackedItem();
|
||||
modelBackedItem.Write(TestDictionaryBase.NameKey, "old");
|
||||
string? fieldName = "INVALID";
|
||||
object value = "value";
|
||||
bool actual = modelBackedItem.WriteWithValidation(fieldName, value);
|
||||
Assert.False(actual);
|
||||
Assert.Null(modelBackedItem.ReadString(fieldName));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WriteWithValidation_ValidKey_True()
|
||||
{
|
||||
TestModelBackedItem? modelBackedItem = new TestModelBackedItem();
|
||||
modelBackedItem.Write(TestDictionaryBase.NameKey, "old");
|
||||
string? fieldName = TestDictionaryBase.NameKey;
|
||||
object value = "value";
|
||||
bool actual = modelBackedItem.WriteWithValidation(fieldName, value);
|
||||
Assert.True(actual);
|
||||
Assert.Equal(value, modelBackedItem.ReadString(fieldName));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace SabreTools.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an item that's backed by a DictionaryBase item
|
||||
/// Represents an item that's backed by a constructable item
|
||||
/// </summary>
|
||||
public abstract class ModelBackedItem : IEquatable<ModelBackedItem>
|
||||
{
|
||||
|
||||
@@ -5,9 +5,9 @@ using Newtonsoft.Json;
|
||||
namespace SabreTools.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an item that's backed by a DictionaryBase item
|
||||
/// Represents an item that's backed by a constructable item
|
||||
/// </summary>
|
||||
public abstract class ModelBackedItem<T> : ModelBackedItem, IEquatable<ModelBackedItem<T>> where T : Data.Models.Metadata.DictionaryBase
|
||||
public abstract class ModelBackedItem<T> : ModelBackedItem, IEquatable<ModelBackedItem<T>> where T : new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal model wrapped by this DatItem
|
||||
@@ -19,98 +19,7 @@ namespace SabreTools.Metadata
|
||||
|
||||
public ModelBackedItem()
|
||||
{
|
||||
_internal = Activator.CreateInstance<T>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Accessors
|
||||
|
||||
/// <summary>
|
||||
/// Get the value from a field based on the type provided
|
||||
/// </summary>
|
||||
/// <typeparam name="U">Type of the value to get from the internal model</typeparam>
|
||||
/// <param name="fieldName">Field to retrieve</param>
|
||||
/// <returns>Value from the field, if possible</returns>
|
||||
public U? Read<U>(string fieldName)
|
||||
=> _internal.Read<U>(fieldName);
|
||||
|
||||
/// <summary>
|
||||
/// Get the value from a field based on the type provided
|
||||
/// </summary>
|
||||
/// <param name="fieldName">Field to retrieve</param>
|
||||
/// <returns>Value from the field, if possible</returns>
|
||||
/// TODO: Determine if this can be removed
|
||||
public bool? ReadBool(string fieldName)
|
||||
=> _internal.ReadBool(fieldName);
|
||||
|
||||
/// <summary>
|
||||
/// Get the value from a field based on the type provided
|
||||
/// </summary>
|
||||
/// <param name="fieldName">Field to retrieve</param>
|
||||
/// <returns>Value from the field, if possible</returns>
|
||||
/// TODO: Determine if this can be removed
|
||||
public double? ReadDouble(string fieldName)
|
||||
=> _internal.ReadDouble(fieldName);
|
||||
|
||||
/// <summary>
|
||||
/// Get the value from a field based on the type provided
|
||||
/// </summary>
|
||||
/// <param name="fieldName">Field to retrieve</param>
|
||||
/// <returns>Value from the field, if possible</returns>
|
||||
/// TODO: Determine if this can be removed
|
||||
public long? ReadLong(string fieldName)
|
||||
=> _internal.ReadLong(fieldName);
|
||||
|
||||
/// <summary>
|
||||
/// Get the value from a field based on the type provided
|
||||
/// </summary>
|
||||
/// <param name="fieldName">Field to retrieve</param>
|
||||
/// <returns>Value from the field, if possible</returns>
|
||||
public string? ReadString(string fieldName)
|
||||
=> _internal.ReadString(fieldName);
|
||||
|
||||
/// <summary>
|
||||
/// Get the value from a field based on the type provided
|
||||
/// </summary>
|
||||
/// <param name="fieldName">Field to retrieve</param>
|
||||
/// <returns>Value from the field, if possible</returns>
|
||||
/// TODO: Determine if this can be removed
|
||||
public string[]? ReadStringArray(string fieldName)
|
||||
=> _internal.ReadStringArray(fieldName);
|
||||
|
||||
/// <summary>
|
||||
/// Set the value from a field based on the type provided
|
||||
/// </summary>
|
||||
/// <typeparam name="U">Type of the value to set in the internal model</typeparam>
|
||||
/// <param name="fieldName">Field to set</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <returns>True if the value was set, false otherwise</returns>
|
||||
public bool Write<U>(string fieldName, U? value)
|
||||
=> _internal.Write(fieldName, value);
|
||||
|
||||
/// <summary>
|
||||
/// Set a field from the backing item validating the field is expected
|
||||
/// </summary>
|
||||
/// TODO: Figure out how to add this to DictionaryBase
|
||||
public bool WriteWithValidation(string fieldName, object value)
|
||||
{
|
||||
// If the item or field name are missing, we can't do anything
|
||||
if (string.IsNullOrEmpty(fieldName))
|
||||
return false;
|
||||
|
||||
// Retrieve the list of valid fields for the item
|
||||
var constants = TypeHelper.GetConstants(_internal.GetType());
|
||||
if (constants is null)
|
||||
return false;
|
||||
|
||||
// Get the value that matches the field name provided
|
||||
string? realField = Array.Find(constants, c => string.Equals(c, fieldName, StringComparison.OrdinalIgnoreCase));
|
||||
if (realField is null)
|
||||
return false;
|
||||
|
||||
// Set the field with the new value
|
||||
return _internal.Write(realField, value);
|
||||
_internal = new T();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -121,21 +30,5 @@ namespace SabreTools.Metadata
|
||||
public abstract bool Equals(ModelBackedItem<T>? other);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Manipulation
|
||||
|
||||
/// <summary>
|
||||
/// Remove a field from the backing item
|
||||
/// </summary>
|
||||
public bool Remove(string fieldName)
|
||||
=> _internal.Remove(fieldName);
|
||||
|
||||
/// <summary>
|
||||
/// Replace a field from another ModelBackedItem
|
||||
/// </summary>
|
||||
public bool Replace(ModelBackedItem<T>? from, string fieldName)
|
||||
=> _internal.Replace(from?._internal, fieldName);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,7 +352,7 @@ namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
var info = new Info();
|
||||
|
||||
var sources = item.Read<string[]>(Data.Models.Metadata.InfoSource.SourceKey);
|
||||
var sources = item.Source;
|
||||
if (sources is not null && sources.Length > 0)
|
||||
info.Source = [.. sources];
|
||||
|
||||
|
||||
@@ -337,10 +337,7 @@ namespace SabreTools.Serialization.CrossModel
|
||||
|
||||
var sources = item.Source;
|
||||
if (sources is not null && sources.Length > 0)
|
||||
{
|
||||
string[] sourcesCopy = [.. sources];
|
||||
infoSource[Data.Models.Metadata.InfoSource.SourceKey] = sourcesCopy;
|
||||
}
|
||||
infoSource.Source = [.. sources];
|
||||
|
||||
return infoSource;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace SabreTools.Serialization.CrossModel
|
||||
/// </summary>
|
||||
private static Data.Models.Metadata.Header ConvertHeaderToInternalModel(Datafile item)
|
||||
{
|
||||
var header = item.Header is not null ? ConvertHeaderToInternalModel(item.Header) : [];
|
||||
var header = item.Header is not null ? ConvertHeaderToInternalModel(item.Header) : new();
|
||||
|
||||
header.Build = item.Build;
|
||||
header.Debug = item.Debug;
|
||||
|
||||
@@ -66,8 +66,7 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
}
|
||||
|
||||
if (item.RefName != null
|
||||
|| item.EmulatorVersion != null)
|
||||
if (item.RefName != null || item.EmulatorVersion != null)
|
||||
{
|
||||
metadataFile.Emulator = new Emulator
|
||||
{
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
var row = new Row
|
||||
{
|
||||
FileName = header?.ReadString("FILENAME"), // TODO: Make this an actual key to retrieve
|
||||
FileName = header?.FileName,
|
||||
InternalName = header?.Name,
|
||||
Description = header?.Description,
|
||||
GameName = parent.Name,
|
||||
@@ -104,7 +104,7 @@ namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
var row = new Row
|
||||
{
|
||||
FileName = header?.ReadString("FILENAME"), // TODO: Make this an actual key to retrieve on an item -- OriginalFilename
|
||||
FileName = header?.FileName,
|
||||
InternalName = header?.Name,
|
||||
Description = header?.Description,
|
||||
GameName = parent.Name,
|
||||
@@ -131,7 +131,7 @@ namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
var row = new Row
|
||||
{
|
||||
FileName = header?.ReadString("FILENAME"), // TODO: Make this an actual key to retrieve
|
||||
FileName = header?.FileName,
|
||||
InternalName = header?.Name,
|
||||
Description = header?.Description,
|
||||
GameName = parent.Name,
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace SabreTools.Serialization.CrossModel
|
||||
if (item.Row is not null && item.Row.Length > 0)
|
||||
{
|
||||
var first = item.Row[0];
|
||||
header["FILENAME"] = first.FileName; // TODO: Make this an actual key to retrieve on an item -- OriginalFilename
|
||||
header.FileName = first.FileName;
|
||||
header.Name = first.FileName;
|
||||
header.Description = first.Description;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user