Add nullable context to SabreTools.Core

This commit is contained in:
Matt Nadareski
2023-08-12 00:55:41 -04:00
parent 12ee5895f9
commit ce6a64d4cd
18 changed files with 362 additions and 315 deletions

View File

@@ -18,7 +18,7 @@ namespace SabreTools.Core
set { lock (_lock) _list[index] = value; } set { lock (_lock) _list[index] = value; }
} }
object IList.this[int index] object? IList.this[int index]
{ {
get { lock (_lock) return ((IList)_list)[index]; } get { lock (_lock) return ((IList)_list)[index]; }
set { lock (_lock) ((IList)_list)[index] = value; } set { lock (_lock) ((IList)_list)[index] = value; }
@@ -43,7 +43,7 @@ namespace SabreTools.Core
_list.Add(item); _list.Add(item);
} }
public int Add(object value) public int Add(object? value)
{ {
lock (_lock) lock (_lock)
return ((IList)_list).Add(value); return ((IList)_list).Add(value);
@@ -67,7 +67,7 @@ namespace SabreTools.Core
return _list.Contains(item); return _list.Contains(item);
} }
public bool Contains(object value) public bool Contains(object? value)
{ {
lock (_lock) lock (_lock)
return ((IList)_list).Contains(value); return ((IList)_list).Contains(value);
@@ -109,7 +109,7 @@ namespace SabreTools.Core
return _list.IndexOf(item); return _list.IndexOf(item);
} }
public int IndexOf(object value) public int IndexOf(object? value)
{ {
lock (_lock) lock (_lock)
return ((IList)_list).IndexOf(value); return ((IList)_list).IndexOf(value);
@@ -121,7 +121,7 @@ namespace SabreTools.Core
_list.Insert(index, item); _list.Insert(index, item);
} }
public void Insert(int index, object value) public void Insert(int index, object? value)
{ {
lock (_lock) lock (_lock)
((IList)_list).Insert(index, value); ((IList)_list).Insert(index, value);
@@ -133,7 +133,7 @@ namespace SabreTools.Core
return _list.Remove(item); return _list.Remove(item);
} }
public void Remove(object value) public void Remove(object? value)
{ {
lock (_lock) lock (_lock)
((IList)_list).Remove(value); ((IList)_list).Remove(value);

View File

@@ -14,82 +14,91 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
// TODO: Split into separate library
namespace NaturalSort namespace NaturalSort
{ {
public class NaturalComparer : Comparer<string>, IDisposable public class NaturalComparer : Comparer<string>, IDisposable
{ {
private Dictionary<string, string[]> table; private readonly Dictionary<string, string[]> table;
public NaturalComparer() public NaturalComparer()
{ {
table = new Dictionary<string, string[]>(); table = new Dictionary<string, string[]>();
} }
public void Dispose() public void Dispose()
{ {
table.Clear(); table.Clear();
table = null; }
}
public override int Compare(string x, string y) public override int Compare(string? x, string? y)
{ {
if (x.ToLowerInvariant() == y.ToLowerInvariant()) if (x == null || y == null)
{ {
return x.CompareTo(y); if (x == null && y != null)
} return -1;
if (!table.TryGetValue(x, out string[] x1)) else if (x != null && y == null)
{ return 1;
//x1 = Regex.Split(x.Replace(" ", string.Empty), "([0-9]+)"); else
x1 = Regex.Split(x.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray(); return 0;
table.Add(x, x1); }
} if (x.ToLowerInvariant() == y.ToLowerInvariant())
if (!table.TryGetValue(y, out string[] y1)) {
{ return x.CompareTo(y);
//y1 = Regex.Split(y.Replace(" ", string.Empty), "([0-9]+)"); }
y1 = Regex.Split(y.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray(); if (!table.TryGetValue(x, out string[]? x1))
table.Add(y, y1); {
} //x1 = Regex.Split(x.Replace(" ", string.Empty), "([0-9]+)");
x1 = Regex.Split(x.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
table.Add(x, x1);
}
if (!table.TryGetValue(y, out string[]? y1))
{
//y1 = Regex.Split(y.Replace(" ", string.Empty), "([0-9]+)");
y1 = Regex.Split(y.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
table.Add(y, y1);
}
for (int i = 0; i < x1.Length && i < y1.Length; i++) for (int i = 0; i < x1.Length && i < y1.Length; i++)
{ {
if (x1[i] != y1[i]) if (x1[i] != y1[i])
{ {
return PartCompare(x1[i], y1[i]); return PartCompare(x1[i], y1[i]);
} }
} }
if (y1.Length > x1.Length) if (y1.Length > x1.Length)
{ {
return 1; return 1;
} }
else if (x1.Length > y1.Length) else if (x1.Length > y1.Length)
{ {
return -1; return -1;
} }
else else
{ {
return x.CompareTo(y); return x.CompareTo(y);
} }
} }
private static int PartCompare(string left, string right) private static int PartCompare(string left, string right)
{ {
if (!long.TryParse(left, out long x)) if (!long.TryParse(left, out long x))
{ {
return NaturalComparerUtil.CompareNumeric(left, right); return NaturalComparerUtil.CompareNumeric(left, right);
} }
if (!long.TryParse(right, out long y)) if (!long.TryParse(right, out long y))
{ {
return NaturalComparerUtil.CompareNumeric(left, right); return NaturalComparerUtil.CompareNumeric(left, right);
} }
// If we have an equal part, then make sure that "longer" ones are taken into account // If we have an equal part, then make sure that "longer" ones are taken into account
if (x.CompareTo(y) == 0) if (x.CompareTo(y) == 0)
{ {
return left.Length - right.Length; return left.Length - right.Length;
} }
return x.CompareTo(y); return x.CompareTo(y);
} }
} }
} }

View File

@@ -1,78 +1,79 @@
using System.IO; using System.IO;
// TODO: Split into separate library
namespace NaturalSort namespace NaturalSort
{ {
public static class NaturalComparerUtil public static class NaturalComparerUtil
{ {
public static int CompareNumeric(string s1, string s2) public static int CompareNumeric(string s1, string s2)
{ {
// Save the orginal strings, for later comparison // Save the orginal strings, for later comparison
string s1orig = s1; string s1orig = s1;
string s2orig = s2; string s2orig = s2;
// We want to normalize the strings, so we set both to lower case // We want to normalize the strings, so we set both to lower case
s1 = s1.ToLowerInvariant(); s1 = s1.ToLowerInvariant();
s2 = s2.ToLowerInvariant(); s2 = s2.ToLowerInvariant();
// If the strings are the same exactly, return // If the strings are the same exactly, return
if (s1 == s2) if (s1 == s2)
return s1orig.CompareTo(s2orig); return s1orig.CompareTo(s2orig);
// If one is null, then say that's less than // If one is null, then say that's less than
if (s1 == null) if (s1 == null)
return -1; return -1;
if (s2 == null) if (s2 == null)
return 1; return 1;
// Now split into path parts after converting AltDirSeparator to DirSeparator // Now split into path parts after converting AltDirSeparator to DirSeparator
s1 = s1.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); s1 = s1.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
s2 = s2.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); s2 = s2.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
string[] s1parts = s1.Split(Path.DirectorySeparatorChar); string[] s1parts = s1.Split(Path.DirectorySeparatorChar);
string[] s2parts = s2.Split(Path.DirectorySeparatorChar); string[] s2parts = s2.Split(Path.DirectorySeparatorChar);
// Then compare each part in turn // Then compare each part in turn
for (int j = 0; j < s1parts.Length && j < s2parts.Length; j++) for (int j = 0; j < s1parts.Length && j < s2parts.Length; j++)
{ {
int compared = CompareNumericPart(s1parts[j], s2parts[j]); int compared = CompareNumericPart(s1parts[j], s2parts[j]);
if (compared != 0) if (compared != 0)
return compared; return compared;
} }
// If we got out here, then it looped through at least one of the strings // If we got out here, then it looped through at least one of the strings
if (s1parts.Length > s2parts.Length) if (s1parts.Length > s2parts.Length)
return 1; return 1;
if (s1parts.Length < s2parts.Length) if (s1parts.Length < s2parts.Length)
return -1; return -1;
return s1orig.CompareTo(s2orig); return s1orig.CompareTo(s2orig);
} }
private static int CompareNumericPart(string s1, string s2) private static int CompareNumericPart(string s1, string s2)
{ {
// Otherwise, loop through until we have an answer // Otherwise, loop through until we have an answer
for (int i = 0; i < s1.Length && i < s2.Length; i++) for (int i = 0; i < s1.Length && i < s2.Length; i++)
{ {
int s1c = s1[i]; int s1c = s1[i];
int s2c = s2[i]; int s2c = s2[i];
// If the characters are the same, continue // If the characters are the same, continue
if (s1c == s2c) if (s1c == s2c)
continue; continue;
// If they're different, check which one was larger // If they're different, check which one was larger
if (s1c > s2c) if (s1c > s2c)
return 1; return 1;
if (s1c < s2c) if (s1c < s2c)
return -1; return -1;
} }
// If we got out here, then it looped through at least one of the strings // If we got out here, then it looped through at least one of the strings
if (s1.Length > s2.Length) if (s1.Length > s2.Length)
return 1; return 1;
if (s1.Length < s2.Length) if (s1.Length < s2.Length)
return -1; return -1;
return 0; return 0;
} }
} }
} }

View File

@@ -14,82 +14,91 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
// TODO: Split into separate library
namespace NaturalSort namespace NaturalSort
{ {
public class NaturalReversedComparer : Comparer<string>, IDisposable public class NaturalReversedComparer : Comparer<string>, IDisposable
{ {
private Dictionary<string, string[]> table; private readonly Dictionary<string, string[]> table;
public NaturalReversedComparer() public NaturalReversedComparer()
{ {
table = new Dictionary<string, string[]>(); table = new Dictionary<string, string[]>();
} }
public void Dispose() public void Dispose()
{ {
table.Clear(); table.Clear();
table = null; }
}
public override int Compare(string x, string y) public override int Compare(string? x, string? y)
{ {
if (y.ToLowerInvariant() == x.ToLowerInvariant()) if (x == null || y == null)
{ {
return y.CompareTo(x); if (x == null && y != null)
} return -1;
if (!table.TryGetValue(x, out string[] x1)) else if (x != null && y == null)
{ return 1;
//x1 = Regex.Split(x.Replace(" ", string.Empty), "([0-9]+)"); else
x1 = Regex.Split(x.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray(); return 0;
table.Add(x, x1); }
} if (y.ToLowerInvariant() == x.ToLowerInvariant())
if (!table.TryGetValue(y, out string[] y1)) {
{ return y.CompareTo(x);
//y1 = Regex.Split(y.Replace(" ", string.Empty), "([0-9]+)"); }
y1 = Regex.Split(y.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray(); if (!table.TryGetValue(x, out string[]? x1))
table.Add(y, y1); {
} //x1 = Regex.Split(x.Replace(" ", string.Empty), "([0-9]+)");
x1 = Regex.Split(x.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
table.Add(x, x1);
}
if (!table.TryGetValue(y, out string[]? y1))
{
//y1 = Regex.Split(y.Replace(" ", string.Empty), "([0-9]+)");
y1 = Regex.Split(y.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
table.Add(y, y1);
}
for (int i = 0; i < x1.Length && i < y1.Length; i++) for (int i = 0; i < x1.Length && i < y1.Length; i++)
{ {
if (x1[i] != y1[i]) if (x1[i] != y1[i])
{ {
return PartCompare(x1[i], y1[i]); return PartCompare(x1[i], y1[i]);
} }
} }
if (y1.Length > x1.Length) if (y1.Length > x1.Length)
{ {
return 1; return 1;
} }
else if (x1.Length > y1.Length) else if (x1.Length > y1.Length)
{ {
return -1; return -1;
} }
else else
{ {
return y.CompareTo(x); return y.CompareTo(x);
} }
} }
private static int PartCompare(string left, string right) private static int PartCompare(string left, string right)
{ {
if (!long.TryParse(left, out long x)) if (!long.TryParse(left, out long x))
{ {
return NaturalComparerUtil.CompareNumeric(right, left); return NaturalComparerUtil.CompareNumeric(right, left);
} }
if (!long.TryParse(right, out long y)) if (!long.TryParse(right, out long y))
{ {
return NaturalComparerUtil.CompareNumeric(right, left); return NaturalComparerUtil.CompareNumeric(right, left);
} }
// If we have an equal part, then make sure that "longer" ones are taken into account // If we have an equal part, then make sure that "longer" ones are taken into account
if (y.CompareTo(x) == 0) if (y.CompareTo(x) == 0)
{ {
return right.Length - left.Length; return right.Length - left.Length;
} }
return y.CompareTo(x); return y.CompareTo(x);
} }
} }
} }

View File

@@ -30,9 +30,6 @@ namespace SabreTools.Core
if (!Console.IsOutputRedirected) if (!Console.IsOutputRedirected)
{ {
// Set the console to ready state // Set the console to ready state
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
Console.SetBufferSize(Console.BufferWidth, 999);
ConsoleColor formertext = Console.ForegroundColor; ConsoleColor formertext = Console.ForegroundColor;
ConsoleColor formerback = Console.BackgroundColor; ConsoleColor formerback = Console.BackgroundColor;
Console.ForegroundColor = ConsoleColor.Yellow; Console.ForegroundColor = ConsoleColor.Yellow;
@@ -48,7 +45,7 @@ namespace SabreTools.Core
// Return the console to the original text and background colors // Return the console to the original text and background colors
Console.ForegroundColor = formertext; Console.ForegroundColor = formertext;
Console.BackgroundColor = formerback; Console.BackgroundColor = formerback;
} }
} }
} }

View File

@@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks> <TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -454,7 +454,7 @@ namespace Aaru.Checksums
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">null</param> /// <param name="hash">null</param>
/// <returns>Base64 representation of SpamSum $blocksize:$hash:$hash</returns> /// <returns>Base64 representation of SpamSum $blocksize:$hash:$hash</returns>
public static string Data(byte[] data, uint len, out byte[] hash) public static string Data(byte[] data, uint len, out byte[]? hash)
{ {
var fuzzyContext = new SpamSumContext(); var fuzzyContext = new SpamSumContext();
@@ -469,7 +469,7 @@ namespace Aaru.Checksums
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="hash">null</param> /// <param name="hash">null</param>
/// <returns>Base64 representation of SpamSum $blocksize:$hash:$hash</returns> /// <returns>Base64 representation of SpamSum $blocksize:$hash:$hash</returns>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); public static string Data(byte[] data, out byte[]? hash) => Data(data, (uint)data.Length, out hash);
// Converts an ASCII null-terminated string to .NET string // Converts an ASCII null-terminated string to .NET string
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -10,7 +10,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="value">Value to use</param> /// <param name="value">Value to use</param>
/// <returns>MappingAttribute attached to the value</returns> /// <returns>MappingAttribute attached to the value</returns>
public static MappingAttribute GetAttribute(T value) public static MappingAttribute? GetAttribute(T? value)
{ {
// Null value in, null value out // Null value in, null value out
if (value == null) if (value == null)
@@ -22,7 +22,7 @@ namespace SabreTools.Core.Tools
enumType = Nullable.GetUnderlyingType(enumType); enumType = Nullable.GetUnderlyingType(enumType);
// If the value returns a null on ToString, just return null // If the value returns a null on ToString, just return null
string valueStr = value.ToString(); string? valueStr = value.ToString();
if (string.IsNullOrWhiteSpace(valueStr)) if (string.IsNullOrWhiteSpace(valueStr))
return null; return null;
@@ -42,7 +42,7 @@ namespace SabreTools.Core.Tools
return null; return null;
// Return the first attribute, if possible // Return the first attribute, if possible
return (MappingAttribute)attributes.FirstOrDefault(); return (MappingAttribute?)attributes.FirstOrDefault();
} }
} }
} }

View File

@@ -43,7 +43,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="chipType">String to get value from</param> /// <param name="chipType">String to get value from</param>
/// <returns>ChipType value corresponding to the string</returns> /// <returns>ChipType value corresponding to the string</returns>
public static ChipType AsChipType(this string chipType) public static ChipType AsChipType(this string? chipType)
=> AsEnumValue<ChipType>(chipType); => AsEnumValue<ChipType>(chipType);
/// <summary> /// <summary>
@@ -51,7 +51,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="controlType">String to get value from</param> /// <param name="controlType">String to get value from</param>
/// <returns>ControlType value corresponding to the string</returns> /// <returns>ControlType value corresponding to the string</returns>
public static ControlType AsControlType(this string controlType) public static ControlType AsControlType(this string? controlType)
=> AsEnumValue<ControlType>(controlType); => AsEnumValue<ControlType>(controlType);
/// <summary> /// <summary>
@@ -59,7 +59,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="DatHeaderField">String to get value from</param> /// <param name="DatHeaderField">String to get value from</param>
/// <returns>DatHeaderField value corresponding to the string</returns> /// <returns>DatHeaderField value corresponding to the string</returns>
public static DatHeaderField AsDatHeaderField(this string input) public static DatHeaderField AsDatHeaderField(this string? input)
{ {
// If the input is empty, we return null // If the input is empty, we return null
if (string.IsNullOrEmpty(input)) if (string.IsNullOrEmpty(input))
@@ -89,7 +89,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="input">String to get value from</param> /// <param name="input">String to get value from</param>
/// <returns>DatItemField value corresponding to the string</returns> /// <returns>DatItemField value corresponding to the string</returns>
public static DatItemField AsDatItemField(this string input) public static DatItemField AsDatItemField(this string? input)
{ {
// If the input is empty, we return null // If the input is empty, we return null
if (string.IsNullOrEmpty(input)) if (string.IsNullOrEmpty(input))
@@ -119,7 +119,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="deviceType">String to get value from</param> /// <param name="deviceType">String to get value from</param>
/// <returns>DeviceType value corresponding to the string</returns> /// <returns>DeviceType value corresponding to the string</returns>
public static DeviceType AsDeviceType(this string deviceType) public static DeviceType AsDeviceType(this string? deviceType)
=> AsEnumValue<DeviceType>(deviceType); => AsEnumValue<DeviceType>(deviceType);
/// <summary> /// <summary>
@@ -127,7 +127,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="displayType">String to get value from</param> /// <param name="displayType">String to get value from</param>
/// <returns>DisplayType value corresponding to the string</returns> /// <returns>DisplayType value corresponding to the string</returns>
public static DisplayType AsDisplayType(this string displayType) public static DisplayType AsDisplayType(this string? displayType)
=> AsEnumValue<DisplayType>(displayType); => AsEnumValue<DisplayType>(displayType);
/// <summary> /// <summary>
@@ -135,7 +135,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="endianness">String to get value from</param> /// <param name="endianness">String to get value from</param>
/// <returns>Endianness value corresponding to the string</returns> /// <returns>Endianness value corresponding to the string</returns>
public static Endianness AsEndianness(this string endianness) public static Endianness AsEndianness(this string? endianness)
=> AsEnumValue<Endianness>(endianness); => AsEnumValue<Endianness>(endianness);
/// <summary> /// <summary>
@@ -143,7 +143,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="featureStatus">String to get value from</param> /// <param name="featureStatus">String to get value from</param>
/// <returns>FeatureStatus value corresponding to the string</returns> /// <returns>FeatureStatus value corresponding to the string</returns>
public static FeatureStatus AsFeatureStatus(this string featureStatus) public static FeatureStatus AsFeatureStatus(this string? featureStatus)
=> AsEnumValue<FeatureStatus>(featureStatus); => AsEnumValue<FeatureStatus>(featureStatus);
/// <summary> /// <summary>
@@ -151,7 +151,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="emulationStatus">String to get value from</param> /// <param name="emulationStatus">String to get value from</param>
/// <returns>FeatureType value corresponding to the string</returns> /// <returns>FeatureType value corresponding to the string</returns>
public static FeatureType AsFeatureType(this string featureType) public static FeatureType AsFeatureType(this string? featureType)
=> AsEnumValue<FeatureType>(featureType); => AsEnumValue<FeatureType>(featureType);
/// <summary> /// <summary>
@@ -159,7 +159,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="status">String to get value from</param> /// <param name="status">String to get value from</param>
/// <returns>ItemStatus value corresponding to the string</returns> /// <returns>ItemStatus value corresponding to the string</returns>
public static ItemStatus AsItemStatus(this string status) public static ItemStatus AsItemStatus(this string? status)
=> AsEnumValue<ItemStatus>(status); => AsEnumValue<ItemStatus>(status);
/// <summary> /// <summary>
@@ -167,7 +167,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="itemType">String to get value from</param> /// <param name="itemType">String to get value from</param>
/// <returns>ItemType? value corresponding to the string</returns> /// <returns>ItemType? value corresponding to the string</returns>
public static ItemType AsItemType(this string itemType) public static ItemType AsItemType(this string? itemType)
=> AsEnumValue<ItemType>(itemType); => AsEnumValue<ItemType>(itemType);
/// <summary> /// <summary>
@@ -175,7 +175,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="loadFlag">String to get value from</param> /// <param name="loadFlag">String to get value from</param>
/// <returns>LoadFlag value corresponding to the string</returns> /// <returns>LoadFlag value corresponding to the string</returns>
public static LoadFlag AsLoadFlag(this string loadFlag) public static LoadFlag AsLoadFlag(this string? loadFlag)
=> AsEnumValue<LoadFlag>(loadFlag); => AsEnumValue<LoadFlag>(loadFlag);
/// <summary> /// <summary>
@@ -183,7 +183,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="logLevel">String to get value from</param> /// <param name="logLevel">String to get value from</param>
/// <returns>LogLevel value corresponding to the string</returns> /// <returns>LogLevel value corresponding to the string</returns>
public static LogLevel AsLogLevel(this string logLevel) public static LogLevel AsLogLevel(this string? logLevel)
=> AsEnumValue<LogLevel>(logLevel); => AsEnumValue<LogLevel>(logLevel);
/// <summary> /// <summary>
@@ -191,7 +191,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="input">String to get value from</param> /// <param name="input">String to get value from</param>
/// <returns>MachineField value corresponding to the string</returns> /// <returns>MachineField value corresponding to the string</returns>
public static MachineField AsMachineField(this string input) public static MachineField AsMachineField(this string? input)
{ {
// If the input is empty, we return null // If the input is empty, we return null
if (string.IsNullOrEmpty(input)) if (string.IsNullOrEmpty(input))
@@ -221,7 +221,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="gametype">String to get value from</param> /// <param name="gametype">String to get value from</param>
/// <returns>MachineType value corresponding to the string</returns> /// <returns>MachineType value corresponding to the string</returns>
public static MachineType AsMachineType(this string gametype) public static MachineType AsMachineType(this string? gametype)
=> AsEnumValue<MachineType>(gametype); => AsEnumValue<MachineType>(gametype);
/// <summary> /// <summary>
@@ -229,7 +229,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="merging">String to get value from</param> /// <param name="merging">String to get value from</param>
/// <returns>MergingFlag value corresponding to the string</returns> /// <returns>MergingFlag value corresponding to the string</returns>
public static MergingFlag AsMergingFlag(this string merging) public static MergingFlag AsMergingFlag(this string? merging)
=> AsEnumValue<MergingFlag>(merging); => AsEnumValue<MergingFlag>(merging);
/// <summary> /// <summary>
@@ -237,7 +237,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="nodump">String to get value from</param> /// <param name="nodump">String to get value from</param>
/// <returns>NodumpFlag value corresponding to the string</returns> /// <returns>NodumpFlag value corresponding to the string</returns>
public static NodumpFlag AsNodumpFlag(this string nodump) public static NodumpFlag AsNodumpFlag(this string? nodump)
=> AsEnumValue<NodumpFlag>(nodump); => AsEnumValue<NodumpFlag>(nodump);
/// <summary> /// <summary>
@@ -245,7 +245,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="subType">String to get value from</param> /// <param name="subType">String to get value from</param>
/// <returns>OpenMSXSubType value corresponding to the string</returns> /// <returns>OpenMSXSubType value corresponding to the string</returns>
public static OpenMSXSubType AsOpenMSXSubType(this string subType) public static OpenMSXSubType AsOpenMSXSubType(this string? subType)
=> AsEnumValue<OpenMSXSubType>(subType); => AsEnumValue<OpenMSXSubType>(subType);
/// <summary> /// <summary>
@@ -253,7 +253,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="packing">String to get value from</param> /// <param name="packing">String to get value from</param>
/// <returns>PackingFlag value corresponding to the string</returns> /// <returns>PackingFlag value corresponding to the string</returns>
public static PackingFlag AsPackingFlag(this string packing) public static PackingFlag AsPackingFlag(this string? packing)
=> AsEnumValue<PackingFlag>(packing); => AsEnumValue<PackingFlag>(packing);
/// <summary> /// <summary>
@@ -261,7 +261,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="relation">String to get value from</param> /// <param name="relation">String to get value from</param>
/// <returns>Relation value corresponding to the string</returns> /// <returns>Relation value corresponding to the string</returns>
public static Relation AsRelation(this string relation) public static Relation AsRelation(this string? relation)
=> AsEnumValue<Relation>(relation); => AsEnumValue<Relation>(relation);
/// <summary> /// <summary>
@@ -269,7 +269,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="runnable">String to get value from</param> /// <param name="runnable">String to get value from</param>
/// <returns>Runnable value corresponding to the string</returns> /// <returns>Runnable value corresponding to the string</returns>
public static Runnable AsRunnable(this string runnable) public static Runnable AsRunnable(this string? runnable)
=> AsEnumValue<Runnable>(runnable); => AsEnumValue<Runnable>(runnable);
/// <summary> /// <summary>
@@ -277,7 +277,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="status">String to get value from</param> /// <param name="status">String to get value from</param>
/// <returns>SoftwareListStatus value corresponding to the string</returns> /// <returns>SoftwareListStatus value corresponding to the string</returns>
public static SoftwareListStatus AsSoftwareListStatus(this string status) public static SoftwareListStatus AsSoftwareListStatus(this string? status)
=> AsEnumValue<SoftwareListStatus>(status); => AsEnumValue<SoftwareListStatus>(status);
/// <summary> /// <summary>
@@ -285,7 +285,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="supported">String to get value from</param> /// <param name="supported">String to get value from</param>
/// <returns>Supported value corresponding to the string</returns> /// <returns>Supported value corresponding to the string</returns>
public static Supported AsSupported(this string supported) public static Supported AsSupported(this string? supported)
=> AsEnumValue<Supported>(supported); => AsEnumValue<Supported>(supported);
/// <summary> /// <summary>
@@ -293,7 +293,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="supported">String to get value from</param> /// <param name="supported">String to get value from</param>
/// <returns>SupportStatus value corresponding to the string</returns> /// <returns>SupportStatus value corresponding to the string</returns>
public static SupportStatus AsSupportStatus(this string supportStatus) public static SupportStatus AsSupportStatus(this string? supportStatus)
=> AsEnumValue<SupportStatus>(supportStatus); => AsEnumValue<SupportStatus>(supportStatus);
/// <summary> /// <summary>
@@ -301,7 +301,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="yesno">String to get value from</param> /// <param name="yesno">String to get value from</param>
/// <returns>bool? corresponding to the string</returns> /// <returns>bool? corresponding to the string</returns>
public static bool? AsYesNo(this string yesno) public static bool? AsYesNo(this string? yesno)
{ {
return yesno?.ToLowerInvariant() switch return yesno?.ToLowerInvariant() switch
{ {
@@ -317,7 +317,7 @@ namespace SabreTools.Core.Tools
/// <param name="value">String value to parse/param> /// <param name="value">String value to parse/param>
/// <typeparam name="T">Enum type that is expected</typeparam> /// <typeparam name="T">Enum type that is expected</typeparam>
/// <returns>Enum value representing the input, default on error</returns> /// <returns>Enum value representing the input, default on error</returns>
internal static T AsEnumValue<T>(string value) internal static T? AsEnumValue<T>(string? value)
{ {
// Get the mapping dictionary // Get the mapping dictionary
var mappings = GenerateToEnum<T>(); var mappings = GenerateToEnum<T>();
@@ -352,7 +352,7 @@ namespace SabreTools.Core.Tools
foreach (T value in values) foreach (T value in values)
{ {
// Try to get the mapping attribute // Try to get the mapping attribute
MappingAttribute attr = AttributeHelper<T>.GetAttribute(value); MappingAttribute? attr = AttributeHelper<T>.GetAttribute(value);
if (attr?.Mappings == null || !attr.Mappings.Any()) if (attr?.Mappings == null || !attr.Mappings.Any())
continue; continue;
@@ -383,7 +383,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="chipType">ChipType to get value from</param> /// <param name="chipType">ChipType to get value from</param>
/// <returns>String value corresponding to the ChipType</returns> /// <returns>String value corresponding to the ChipType</returns>
public static string FromChipType(this ChipType chipType) public static string? FromChipType(this ChipType chipType)
=> AsStringValue(chipType); => AsStringValue(chipType);
/// <summary> /// <summary>
@@ -391,7 +391,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="controlType">ControlType to get value from</param> /// <param name="controlType">ControlType to get value from</param>
/// <returns>String value corresponding to the ControlType</returns> /// <returns>String value corresponding to the ControlType</returns>
public static string FromControlType(this ControlType controlType) public static string? FromControlType(this ControlType controlType)
=> AsStringValue(controlType); => AsStringValue(controlType);
/// <summary> /// <summary>
@@ -399,7 +399,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="deviceType">vDeviceType to get value from</param> /// <param name="deviceType">vDeviceType to get value from</param>
/// <returns>String value corresponding to the DeviceType</returns> /// <returns>String value corresponding to the DeviceType</returns>
public static string FromDeviceType(this DeviceType deviceType) public static string? FromDeviceType(this DeviceType deviceType)
=> AsStringValue(deviceType); => AsStringValue(deviceType);
/// <summary> /// <summary>
@@ -407,7 +407,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="displayType">DisplayType to get value from</param> /// <param name="displayType">DisplayType to get value from</param>
/// <returns>String value corresponding to the DisplayType</returns> /// <returns>String value corresponding to the DisplayType</returns>
public static string FromDisplayType(this DisplayType displayType) public static string? FromDisplayType(this DisplayType displayType)
=> AsStringValue(displayType); => AsStringValue(displayType);
/// <summary> /// <summary>
@@ -415,7 +415,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="endianness">Endianness to get value from</param> /// <param name="endianness">Endianness to get value from</param>
/// <returns>String value corresponding to the Endianness</returns> /// <returns>String value corresponding to the Endianness</returns>
public static string FromEndianness(this Endianness endianness) public static string? FromEndianness(this Endianness endianness)
=> AsStringValue(endianness); => AsStringValue(endianness);
/// <summary> /// <summary>
@@ -423,7 +423,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="featureStatus">FeatureStatus to get value from</param> /// <param name="featureStatus">FeatureStatus to get value from</param>
/// <returns>String value corresponding to the FeatureStatus</returns> /// <returns>String value corresponding to the FeatureStatus</returns>
public static string FromFeatureStatus(this FeatureStatus featureStatus) public static string? FromFeatureStatus(this FeatureStatus featureStatus)
=> AsStringValue(featureStatus); => AsStringValue(featureStatus);
/// <summary> /// <summary>
@@ -431,7 +431,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="featureType">FeatureType to get value from</param> /// <param name="featureType">FeatureType to get value from</param>
/// <returns>String value corresponding to the FeatureType</returns> /// <returns>String value corresponding to the FeatureType</returns>
public static string FromFeatureType(this FeatureType featureType) public static string? FromFeatureType(this FeatureType featureType)
=> AsStringValue(featureType); => AsStringValue(featureType);
/// <summary> /// <summary>
@@ -440,7 +440,7 @@ namespace SabreTools.Core.Tools
/// <param name="status">ItemStatus to get value from</param> /// <param name="status">ItemStatus to get value from</param>
/// <param name="yesno">True to use Yes/No format instead</param> /// <param name="yesno">True to use Yes/No format instead</param>
/// <returns>String value corresponding to the ItemStatus</returns> /// <returns>String value corresponding to the ItemStatus</returns>
public static string FromItemStatus(this ItemStatus status, bool yesno) public static string? FromItemStatus(this ItemStatus status, bool yesno)
=> AsStringValue(status, yesno); => AsStringValue(status, yesno);
/// <summary> /// <summary>
@@ -448,7 +448,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="itemType">ItemType? to get value from</param> /// <param name="itemType">ItemType? to get value from</param>
/// <returns>String value corresponding to the ItemType?</returns> /// <returns>String value corresponding to the ItemType?</returns>
public static string FromItemType(this ItemType itemType) public static string? FromItemType(this ItemType itemType)
=> AsStringValue(itemType); => AsStringValue(itemType);
/// <summary> /// <summary>
@@ -456,7 +456,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="loadFlag">LoadFlag to get value from</param> /// <param name="loadFlag">LoadFlag to get value from</param>
/// <returns>String value corresponding to the LoadFlag</returns> /// <returns>String value corresponding to the LoadFlag</returns>
public static string FromLoadFlag(this LoadFlag loadFlag) public static string? FromLoadFlag(this LoadFlag loadFlag)
=> AsStringValue(loadFlag); => AsStringValue(loadFlag);
/// <summary> /// <summary>
@@ -465,7 +465,7 @@ namespace SabreTools.Core.Tools
/// <param name="gametype">MachineType to get value from</param> /// <param name="gametype">MachineType to get value from</param>
/// <param name="romCenter">True to use old naming instead</param> /// <param name="romCenter">True to use old naming instead</param>
/// <returns>String value corresponding to the MachineType</returns> /// <returns>String value corresponding to the MachineType</returns>
public static string FromMachineType(this MachineType gametype, bool old) public static string? FromMachineType(this MachineType gametype, bool old)
=> AsStringValue(gametype, old); => AsStringValue(gametype, old);
/// <summary> /// <summary>
@@ -474,7 +474,7 @@ namespace SabreTools.Core.Tools
/// <param name="merging">MergingFlag to get value from</param> /// <param name="merging">MergingFlag to get value from</param>
/// <param name="romCenter">True to use RomCenter naming instead</param> /// <param name="romCenter">True to use RomCenter naming instead</param>
/// <returns>String value corresponding to the MergingFlag</returns> /// <returns>String value corresponding to the MergingFlag</returns>
public static string FromMergingFlag(this MergingFlag merging, bool romCenter) public static string? FromMergingFlag(this MergingFlag merging, bool romCenter)
=> AsStringValue(merging, romCenter); => AsStringValue(merging, romCenter);
/// <summary> /// <summary>
@@ -482,7 +482,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="nodump">NodumpFlag to get value from</param> /// <param name="nodump">NodumpFlag to get value from</param>
/// <returns>String value corresponding to the NodumpFlag</returns> /// <returns>String value corresponding to the NodumpFlag</returns>
public static string FromNodumpFlag(this NodumpFlag nodump) public static string? FromNodumpFlag(this NodumpFlag nodump)
=> AsStringValue(nodump); => AsStringValue(nodump);
/// <summary> /// <summary>
@@ -490,7 +490,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="subType">OpenMSXSubType to get value from</param> /// <param name="subType">OpenMSXSubType to get value from</param>
/// <returns>String value corresponding to the OpenMSXSubType</returns> /// <returns>String value corresponding to the OpenMSXSubType</returns>
public static string FromOpenMSXSubType(this OpenMSXSubType subType) public static string? FromOpenMSXSubType(this OpenMSXSubType subType)
=> AsStringValue(subType); => AsStringValue(subType);
/// <summary> /// <summary>
@@ -499,7 +499,7 @@ namespace SabreTools.Core.Tools
/// <param name="packing">PackingFlag to get value from</param> /// <param name="packing">PackingFlag to get value from</param>
/// <param name="yesno">True to use Yes/No format instead</param> /// <param name="yesno">True to use Yes/No format instead</param>
/// <returns>String value corresponding to the PackingFlag</returns> /// <returns>String value corresponding to the PackingFlag</returns>
public static string FromPackingFlag(this PackingFlag packing, bool yesno) public static string? FromPackingFlag(this PackingFlag packing, bool yesno)
=> AsStringValue(packing, yesno); => AsStringValue(packing, yesno);
/// <summary> /// <summary>
@@ -507,7 +507,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="relation">Relation to get value from</param> /// <param name="relation">Relation to get value from</param>
/// <returns>String value corresponding to the Relation</returns> /// <returns>String value corresponding to the Relation</returns>
public static string FromRelation(this Relation relation) public static string? FromRelation(this Relation relation)
=> AsStringValue(relation); => AsStringValue(relation);
/// <summary> /// <summary>
@@ -515,7 +515,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="runnable">Runnable to get value from</param> /// <param name="runnable">Runnable to get value from</param>
/// <returns>String value corresponding to the Runnable</returns> /// <returns>String value corresponding to the Runnable</returns>
public static string FromRunnable(this Runnable runnable) public static string? FromRunnable(this Runnable runnable)
=> AsStringValue(runnable); => AsStringValue(runnable);
/// <summary> /// <summary>
@@ -523,7 +523,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="status">SoftwareListStatus to get value from</param> /// <param name="status">SoftwareListStatus to get value from</param>
/// <returns>String value corresponding to the SoftwareListStatus</returns> /// <returns>String value corresponding to the SoftwareListStatus</returns>
public static string FromSoftwareListStatus(this SoftwareListStatus status) public static string? FromSoftwareListStatus(this SoftwareListStatus status)
=> AsStringValue(status); => AsStringValue(status);
/// <summary> /// <summary>
@@ -532,7 +532,7 @@ namespace SabreTools.Core.Tools
/// <param name="supported">Supported to get value from</param> /// <param name="supported">Supported to get value from</param>
/// <param name="verbose">True to use verbose output, false otherwise</param> /// <param name="verbose">True to use verbose output, false otherwise</param>
/// <returns>String value corresponding to the Supported</returns> /// <returns>String value corresponding to the Supported</returns>
public static string FromSupported(this Supported supported, bool verbose) public static string? FromSupported(this Supported supported, bool verbose)
=> AsStringValue(supported, verbose); => AsStringValue(supported, verbose);
/// <summary> /// <summary>
@@ -540,7 +540,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="supportStatus">SupportStatus to get value from</param> /// <param name="supportStatus">SupportStatus to get value from</param>
/// <returns>String value corresponding to the SupportStatus</returns> /// <returns>String value corresponding to the SupportStatus</returns>
public static string FromSupportStatus(this SupportStatus supportStatus) public static string? FromSupportStatus(this SupportStatus supportStatus)
=> AsStringValue(supportStatus); => AsStringValue(supportStatus);
/// <summary> /// <summary>
@@ -548,7 +548,7 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
/// <param name="yesno">bool? to get value from</param> /// <param name="yesno">bool? to get value from</param>
/// <returns>String corresponding to the bool?</returns> /// <returns>String corresponding to the bool?</returns>
public static string FromYesNo(this bool? yesno) public static string? FromYesNo(this bool? yesno)
{ {
return yesno switch return yesno switch
{ {
@@ -565,7 +565,7 @@ namespace SabreTools.Core.Tools
/// <param name="useSecond">True to use the second mapping option, if it exists</param> /// <param name="useSecond">True to use the second mapping option, if it exists</param>
/// <typeparam name="T">Enum type that is expected</typeparam> /// <typeparam name="T">Enum type that is expected</typeparam>
/// <returns>String value representing the input, default on error</returns> /// <returns>String value representing the input, default on error</returns>
internal static string? AsStringValue<T>(T value, bool useSecond = false) internal static string? AsStringValue<T>(T value, bool useSecond = false) where T : notnull
{ {
// Get the mapping dictionary // Get the mapping dictionary
var mappings = GenerateToString<T>(useSecond); var mappings = GenerateToString<T>(useSecond);
@@ -584,7 +584,7 @@ namespace SabreTools.Core.Tools
/// <param name="useSecond">True to use the second mapping option, if it exists</param> /// <param name="useSecond">True to use the second mapping option, if it exists</param>
/// <typeparam name="T">Enum type that is expected</typeparam> /// <typeparam name="T">Enum type that is expected</typeparam>
/// <returns>Dictionary of enum to string values</returns> /// <returns>Dictionary of enum to string values</returns>
internal static Dictionary<T, string> GenerateToString<T>(bool useSecond) internal static Dictionary<T, string> GenerateToString<T>(bool useSecond) where T : notnull
{ {
try try
{ {
@@ -596,7 +596,7 @@ namespace SabreTools.Core.Tools
foreach (T value in values) foreach (T value in values)
{ {
// Try to get the mapping attribute // Try to get the mapping attribute
MappingAttribute attr = AttributeHelper<T>.GetAttribute(value); MappingAttribute? attr = AttributeHelper<T>.GetAttribute(value);
if (attr?.Mappings == null || !attr.Mappings.Any()) if (attr?.Mappings == null || !attr.Mappings.Any())
continue; continue;

View File

@@ -12,7 +12,7 @@ namespace SabreTools.Core.Tools
public class Hasher public class Hasher
{ {
public Hash HashType { get; private set; } public Hash HashType { get; private set; }
private IDisposable _hasher; private IDisposable? _hasher;
public Hasher(Hash hashType) public Hasher(Hash hashType)
{ {
@@ -59,7 +59,7 @@ namespace SabreTools.Core.Tools
public void Dispose() public void Dispose()
{ {
_hasher.Dispose(); _hasher?.Dispose();
} }
/// <summary> /// <summary>
@@ -67,22 +67,37 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
public void Process(byte[] buffer, int size) public void Process(byte[] buffer, int size)
{ {
switch (HashType) if (_hasher == null)
return;
switch (_hasher)
{ {
case Hash.CRC: case OptimizedCRC.OptimizedCRC crc:
(_hasher as OptimizedCRC.OptimizedCRC).Update(buffer, 0, size); crc.Update(buffer, 0, size);
break; break;
case Hash.MD5: case MD5 md5:
case Hash.SHA1: md5.TransformBlock(buffer, 0, size, null, 0);
case Hash.SHA256:
case Hash.SHA384:
case Hash.SHA512:
(_hasher as HashAlgorithm).TransformBlock(buffer, 0, size, null, 0);
break; break;
case Hash.SpamSum: case SHA1 sha1:
(_hasher as SpamSumContext).Update(buffer); sha1.TransformBlock(buffer, 0, size, null, 0);
break;
case SHA256 sha256:
sha256.TransformBlock(buffer, 0, size, null, 0);
break;
case SHA384 sha384:
sha384.TransformBlock(buffer, 0, size, null, 0);
break;
case SHA512 sha512:
sha512.TransformBlock(buffer, 0, size, null, 0);
break;
case SpamSumContext spamSum:
spamSum.Update(buffer);
break; break;
} }
} }
@@ -92,22 +107,37 @@ namespace SabreTools.Core.Tools
/// </summary> /// </summary>
public void Terminate() public void Terminate()
{ {
if (_hasher == null)
return;
byte[] emptyBuffer = Array.Empty<byte>(); byte[] emptyBuffer = Array.Empty<byte>();
switch (HashType) switch (_hasher)
{ {
case Hash.CRC: case OptimizedCRC.OptimizedCRC crc:
(_hasher as OptimizedCRC.OptimizedCRC).Update(emptyBuffer, 0, 0); crc.Update(emptyBuffer, 0, 0);
break; break;
case Hash.MD5: case MD5 md5:
case Hash.SHA1: md5.TransformFinalBlock(emptyBuffer, 0, 0);
case Hash.SHA256:
case Hash.SHA384:
case Hash.SHA512:
(_hasher as HashAlgorithm).TransformFinalBlock(emptyBuffer, 0, 0);
break; break;
case Hash.SpamSum: case SHA1 sha1:
sha1.TransformFinalBlock(emptyBuffer, 0, 0);
break;
case SHA256 sha256:
sha256.TransformFinalBlock(emptyBuffer, 0, 0);
break;
case SHA384 sha384:
sha384.TransformFinalBlock(emptyBuffer, 0, 0);
break;
case SHA512 sha512:
sha512.TransformFinalBlock(emptyBuffer, 0, 0);
break;
case SpamSumContext:
// No finalization step needed // No finalization step needed
break; break;
} }
@@ -116,17 +146,17 @@ namespace SabreTools.Core.Tools
/// <summary> /// <summary>
/// Get internal hash as a byte array /// Get internal hash as a byte array
/// </summary> /// </summary>
public byte[] GetHash() public byte[]? GetHash()
{ {
return HashType switch return _hasher switch
{ {
Hash.CRC => BitConverter.GetBytes((_hasher as OptimizedCRC.OptimizedCRC).Value).Reverse().ToArray(), OptimizedCRC.OptimizedCRC crc => BitConverter.GetBytes(crc.Value).Reverse().ToArray(),
Hash.MD5 => (_hasher as HashAlgorithm).Hash, MD5 md5 => md5.Hash,
Hash.SHA1 => (_hasher as HashAlgorithm).Hash, SHA1 sha1 => sha1.Hash,
Hash.SHA256 => (_hasher as HashAlgorithm).Hash, SHA256 sha256 => sha256.Hash,
Hash.SHA384 => (_hasher as HashAlgorithm).Hash, SHA384 sha384 => sha384.Hash,
Hash.SHA512 => (_hasher as HashAlgorithm).Hash, SHA512 sha512 => sha512.Hash,
Hash.SpamSum => (_hasher as SpamSumContext).Final(), SpamSumContext spamSum => spamSum.Final(),
_ => null, _ => null,
}; };
} }

View File

@@ -142,7 +142,7 @@ namespace OptimizedCRC
static public int Compute(ArraySegment<byte> block) static public int Compute(ArraySegment<byte> block)
{ {
return Compute(block.Array, block.Offset, block.Count); return Compute(block.Array!, block.Offset, block.Count);
} }
public void Dispose() public void Dispose()

View File

@@ -16,7 +16,7 @@ namespace SabreTools.Core.Tools
/// <param name="bytes">Byte array to convert</param> /// <param name="bytes">Byte array to convert</param>
/// <returns>Hex string representing the byte array</returns> /// <returns>Hex string representing the byte array</returns>
/// <link>http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa</link> /// <link>http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa</link>
public static string ByteArrayToString(byte[] bytes) public static string? ByteArrayToString(byte[]? bytes)
{ {
// If we get null in, we send null out // If we get null in, we send null out
if (bytes == null) if (bytes == null)
@@ -39,10 +39,10 @@ namespace SabreTools.Core.Tools
/// <param name="hex">Hex string to convert</param> /// <param name="hex">Hex string to convert</param>
/// <returns>Byte array represenging the hex string</returns> /// <returns>Byte array represenging the hex string</returns>
/// <link>http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa</link> /// <link>http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa</link>
public static byte[] StringToByteArray(string hex) public static byte[]? StringToByteArray(string? hex)
{ {
// If we get null in, we send null out // If we get null in, we send null out
if (hex == null) if (string.IsNullOrWhiteSpace(hex))
return null; return null;
try try
@@ -102,7 +102,7 @@ namespace SabreTools.Core.Tools
/// <param name="hash">SHA-1 hash to get the path for</param> /// <param name="hash">SHA-1 hash to get the path for</param>
/// <param name="depth">Positive value representing the depth of the depot</param> /// <param name="depth">Positive value representing the depth of the depot</param>
/// <returns>Subfolder path for the given hash</returns> /// <returns>Subfolder path for the given hash</returns>
public static string GetDepotPath(string hash, int depth) public static string? GetDepotPath(string? hash, int depth)
{ {
// If the hash is null or empty, then we return null // If the hash is null or empty, then we return null
if (string.IsNullOrEmpty(hash)) if (string.IsNullOrEmpty(hash))

View File

@@ -397,7 +397,7 @@ namespace SabreTools.DatFiles
Header.UseRomName = true; Header.UseRomName = true;
// Get the name to update // Get the name to update
string name = (Header.UseRomName ? item.GetName() : item.Machine.Name) ?? string.Empty; string? name = (Header.UseRomName ? item.GetName() : item.Machine.Name) ?? string.Empty;
// Create the proper Prefix and Postfix // Create the proper Prefix and Postfix
string pre = CreatePrefixPostfix(item, true); string pre = CreatePrefixPostfix(item, true);
@@ -411,7 +411,7 @@ namespace SabreTools.DatFiles
// We can only write out if there's a SHA-1 // We can only write out if there's a SHA-1
if (!string.IsNullOrWhiteSpace(disk.SHA1)) if (!string.IsNullOrWhiteSpace(disk.SHA1))
{ {
name = Utilities.GetDepotPath(disk.SHA1, Header.OutputDepot.Depth).Replace('\\', '/'); name = Utilities.GetDepotPath(disk.SHA1, Header.OutputDepot.Depth)?.Replace('\\', '/');
item.SetName($"{pre}{name}{post}"); item.SetName($"{pre}{name}{post}");
} }
} }
@@ -420,7 +420,7 @@ namespace SabreTools.DatFiles
// We can only write out if there's a SHA-1 // We can only write out if there's a SHA-1
if (!string.IsNullOrWhiteSpace(media.SHA1)) if (!string.IsNullOrWhiteSpace(media.SHA1))
{ {
name = Utilities.GetDepotPath(media.SHA1, Header.OutputDepot.Depth).Replace('\\', '/'); name = Utilities.GetDepotPath(media.SHA1, Header.OutputDepot.Depth)?.Replace('\\', '/');
item.SetName($"{pre}{name}{post}"); item.SetName($"{pre}{name}{post}");
} }
} }
@@ -429,7 +429,7 @@ namespace SabreTools.DatFiles
// We can only write out if there's a SHA-1 // We can only write out if there's a SHA-1
if (!string.IsNullOrWhiteSpace(rom.SHA1)) if (!string.IsNullOrWhiteSpace(rom.SHA1))
{ {
name = Utilities.GetDepotPath(rom.SHA1, Header.OutputDepot.Depth).Replace('\\', '/'); name = Utilities.GetDepotPath(rom.SHA1, Header.OutputDepot.Depth)?.Replace('\\', '/');
item.SetName($"{pre}{name}{post}"); item.SetName($"{pre}{name}{post}");
} }
} }

View File

@@ -60,11 +60,11 @@ namespace SabreTools.DatFiles.Formats
Header.HeaderSkipper ??= cmp.Header; Header.HeaderSkipper ??= cmp.Header;
Header.Type ??= cmp.Type; Header.Type ??= cmp.Type;
if (Header.ForceMerging == MergingFlag.None) if (Header.ForceMerging == MergingFlag.None)
Header.ForceMerging = cmp.ForceMerging.AsMergingFlag(); Header.ForceMerging = cmp.ForceMerging?.AsMergingFlag() ?? MergingFlag.None;
if (Header.ForcePacking == PackingFlag.None) if (Header.ForcePacking == PackingFlag.None)
Header.ForcePacking = cmp.ForceZipping.AsPackingFlag(); Header.ForcePacking = cmp.ForceZipping?.AsPackingFlag() ?? PackingFlag.None;
if (Header.ForcePacking == PackingFlag.None) if (Header.ForcePacking == PackingFlag.None)
Header.ForcePacking = cmp.ForcePacking.AsPackingFlag(); Header.ForcePacking = cmp.ForcePacking?.AsPackingFlag() ?? PackingFlag.None;
// Handle implied SuperDAT // Handle implied SuperDAT
if (cmp.Name?.Contains(" - SuperDAT") == true && keep) if (cmp.Name?.Contains(" - SuperDAT") == true && keep)

View File

@@ -1040,7 +1040,9 @@ namespace SabreTools.DatFiles
Parallel.ForEach(keys, Globals.ParallelOptions, key => Parallel.ForEach(keys, Globals.ParallelOptions, key =>
{ {
// Get the possibly unsorted list // Get the possibly unsorted list
ConcurrentList<DatItem> sortedlist = this[key].ToConcurrentList(); ConcurrentList<DatItem>? sortedlist = this[key]?.ToConcurrentList();
if (sortedlist == null)
return;
// Sort the list of items to be consistent // Sort the list of items to be consistent
DatItem.Sort(ref sortedlist, false); DatItem.Sort(ref sortedlist, false);

View File

@@ -1240,7 +1240,9 @@ CREATE TABLE IF NOT EXISTS groups (
Parallel.ForEach(keys, Globals.ParallelOptions, key => Parallel.ForEach(keys, Globals.ParallelOptions, key =>
{ {
// Get the possibly unsorted list // Get the possibly unsorted list
ConcurrentList<DatItem> sortedlist = this[key].ToConcurrentList(); ConcurrentList<DatItem>? sortedlist = this[key]?.ToConcurrentList();
if (sortedlist == null)
return;
// Sort the list of items to be consistent // Sort the list of items to be consistent
DatItem.Sort(ref sortedlist, false); DatItem.Sort(ref sortedlist, false);

View File

@@ -353,10 +353,8 @@ namespace SabreTools.Filter
return value.ToLowerInvariant() switch return value.ToLowerInvariant() switch
{ {
"true" => true, "true" or "yes" => true,
"yes" => true, "false" or "no" => false,
"false" => false,
"no" => false,
_ => null, _ => null,
}; };
} }

View File

@@ -32,10 +32,8 @@ namespace SabreTools.Models.Internal
string? asString = Read<string>(key); string? asString = Read<string>(key);
return asString?.ToLowerInvariant() switch return asString?.ToLowerInvariant() switch
{ {
"true" => true, "true" or "yes" => true,
"yes" => true, "false" or "no" => false,
"false" => false,
"no" => false,
_ => null, _ => null,
}; };
} }