diff --git a/CrossModel/Hashfile.Deserializer.cs b/CrossModel/Hashfile.Deserializer.cs new file mode 100644 index 00000000..61364335 --- /dev/null +++ b/CrossModel/Hashfile.Deserializer.cs @@ -0,0 +1,251 @@ +using System.Collections.Generic; +using System.Linq; +using SabreTools.Models.Hashfile; + +namespace SabreTools.Serialization.CrossModel +{ + public partial class Hashfile : IModelSerializer + { + /// +#if NET48 + public Models.Hashfile.Hashfile Deserialize(Models.Metadata.MetadataFile obj) => Deserialize(obj, Hash.CRC); +#else + public Models.Hashfile.Hashfile? Deserialize(Models.Metadata.MetadataFile? obj) => Deserialize(obj, Hash.CRC); +#endif + + /// +#if NET48 + public Models.Hashfile.Hashfile Deserialize(Models.Metadata.MetadataFile obj, Hash hash) +#else + public Models.Hashfile.Hashfile? Deserialize(Models.Metadata.MetadataFile? obj, Hash hash) +#endif + { + if (obj == null) + return null; + + var machines = obj.Read(Models.Metadata.MetadataFile.MachineKey); + if (machines == null || !machines.Any()) + return null; + + var hashfiles = machines + .Where(m => m != null) + .Select(machine => ConvertMachineFromInternalModel(machine, hash)); + + var sfvs = new List(); + var md5s = new List(); + var sha1s = new List(); + var sha256s = new List(); + var sha384s = new List(); + var sha512s = new List(); + var spamsums = new List(); + + foreach (var hashfile in hashfiles) + { + if (hashfile.SFV != null && hashfile.SFV.Any()) + sfvs.AddRange(hashfile.SFV); + if (hashfile.MD5 != null && hashfile.MD5.Any()) + md5s.AddRange(hashfile.MD5); + if (hashfile.SHA1 != null && hashfile.SHA1.Any()) + sha1s.AddRange(hashfile.SHA1); + if (hashfile.SHA256 != null && hashfile.SHA256.Any()) + sha256s.AddRange(hashfile.SHA256); + if (hashfile.SHA384 != null && hashfile.SHA384.Any()) + sha384s.AddRange(hashfile.SHA384); + if (hashfile.SHA512 != null && hashfile.SHA512.Any()) + sha512s.AddRange(hashfile.SHA512); + if (hashfile.SpamSum != null && hashfile.SpamSum.Any()) + spamsums.AddRange(hashfile.SpamSum); + } + + var hashfileItem = new Models.Hashfile.Hashfile(); + + if (sfvs.Any()) + hashfileItem.SFV = sfvs.ToArray(); + if (md5s.Any()) + hashfileItem.MD5 = md5s.ToArray(); + if (sha1s.Any()) + hashfileItem.SHA1 = sha1s.ToArray(); + if (sha256s.Any()) + hashfileItem.SHA256 = sha256s.ToArray(); + if (sha384s.Any()) + hashfileItem.SHA384 = sha384s.ToArray(); + if (sha512s.Any()) + hashfileItem.SHA512 = sha512s.ToArray(); + if (spamsums.Any()) + hashfileItem.SpamSum = spamsums.ToArray(); + + return hashfileItem; + } + + /// + /// Convert from to an array of + /// +#if NET48 + public static Models.Hashfile.Hashfile[] ConvertArrayFromInternalModel(Models.Metadata.MetadataFile item, Hash hash) +#else + public static Models.Hashfile.Hashfile[]? ConvertArrayFromInternalModel(Models.Metadata.MetadataFile? item, Hash hash) +#endif + { + if (item == null) + return null; + + var machines = item.Read(Models.Metadata.MetadataFile.MachineKey); + if (machines != null && machines.Any()) + { + return machines + .Where(m => m != null) + .Select(machine => ConvertMachineFromInternalModel(machine, hash)) + .ToArray(); + } + + return null; + } + + /// + /// Convert from to + /// + private static Models.Hashfile.Hashfile ConvertMachineFromInternalModel(Models.Metadata.Machine item, Hash hash) + { + var roms = item.Read(Models.Metadata.Machine.RomKey); + if (roms == null) + return new Models.Hashfile.Hashfile(); + + return new Models.Hashfile.Hashfile + { + SFV = hash == Hash.CRC + ? roms + .Where(r => r != null) + .Select(ConvertToSFV) + .ToArray() + : null, + MD5 = hash == Hash.MD5 + ? roms + .Where(r => r != null) + .Select(ConvertToMD5) + .ToArray() + : null, + SHA1 = hash == Hash.SHA1 + ? roms + .Where(r => r != null) + .Select(ConvertToSHA1) + .ToArray() + : null, + SHA256 = hash == Hash.SHA256 + ? roms + .Where(r => r != null) + .Select(ConvertToSHA256) + .ToArray() + : null, + SHA384 = hash == Hash.SHA384 + ? roms + .Where(r => r != null) + .Select(ConvertToSHA384) + .ToArray() + : null, + SHA512 = hash == Hash.SHA512 + ? roms + .Where(r => r != null) + .Select(ConvertToSHA512) + .ToArray() + : null, + SpamSum = hash == Hash.SpamSum + ? roms + .Where(r => r != null) + .Select(ConvertToSpamSum) + .ToArray() + : null, + }; + } + + /// + /// Convert from to + /// + private static MD5 ConvertToMD5(Models.Metadata.Rom item) + { + var md5 = new MD5 + { + Hash = item.ReadString(Models.Metadata.Rom.MD5Key), + File = item.ReadString(Models.Metadata.Rom.NameKey), + }; + return md5; + } + + /// + /// Convert from to + /// + private static SFV ConvertToSFV(Models.Metadata.Rom item) + { + var sfv = new SFV + { + File = item.ReadString(Models.Metadata.Rom.NameKey), + Hash = item.ReadString(Models.Metadata.Rom.CRCKey), + }; + return sfv; + } + + /// + /// Convert from to + /// + private static SHA1 ConvertToSHA1(Models.Metadata.Rom item) + { + var sha1 = new SHA1 + { + Hash = item.ReadString(Models.Metadata.Rom.SHA1Key), + File = item.ReadString(Models.Metadata.Rom.NameKey), + }; + return sha1; + } + + /// + /// Convert from to + /// + private static SHA256 ConvertToSHA256(Models.Metadata.Rom item) + { + var sha256 = new SHA256 + { + Hash = item.ReadString(Models.Metadata.Rom.SHA256Key), + File = item.ReadString(Models.Metadata.Rom.NameKey), + }; + return sha256; + } + + /// + /// Convert from to + /// + private static SHA384 ConvertToSHA384(Models.Metadata.Rom item) + { + var sha384 = new SHA384 + { + Hash = item.ReadString(Models.Metadata.Rom.SHA384Key), + File = item.ReadString(Models.Metadata.Rom.NameKey), + }; + return sha384; + } + + /// + /// Convert from to + /// + private static SHA512 ConvertToSHA512(Models.Metadata.Rom item) + { + var sha512 = new SHA512 + { + Hash = item.ReadString(Models.Metadata.Rom.SHA512Key), + File = item.ReadString(Models.Metadata.Rom.NameKey), + }; + return sha512; + } + + /// + /// Convert from to + /// + private static SpamSum ConvertToSpamSum(Models.Metadata.Rom item) + { + var spamsum = new SpamSum + { + Hash = item.ReadString(Models.Metadata.Rom.SpamSumKey), + File = item.ReadString(Models.Metadata.Rom.NameKey), + }; + return spamsum; + } + } +} \ No newline at end of file diff --git a/CrossModel/Hashfile.Serializer.cs b/CrossModel/Hashfile.Serializer.cs new file mode 100644 index 00000000..dad79c80 --- /dev/null +++ b/CrossModel/Hashfile.Serializer.cs @@ -0,0 +1,157 @@ +using System.Linq; +using SabreTools.Models.Hashfile; + +namespace SabreTools.Serialization.CrossModel +{ + public partial class Hashfile : IModelSerializer + { + /// +#if NET48 + public Models.Metadata.MetadataFile Serialize(Models.Hashfile.Hashfile obj) +#else + public Models.Metadata.MetadataFile? Serialize(Models.Hashfile.Hashfile? obj) +#endif + { + if (obj == null) + return null; + + var metadataFile = new Models.Metadata.MetadataFile + { + [Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(), + }; + + var machine = ConvertMachineToInternalModel(obj); + metadataFile[Models.Metadata.MetadataFile.MachineKey] = new Models.Metadata.Machine[] { machine }; + + return metadataFile; + } + + /// + /// Convert from to + /// + private static Models.Metadata.Header ConvertHeaderToInternalModel() + { + var header = new Models.Metadata.Header + { + [Models.Metadata.Header.NameKey] = "Hashfile", + }; + return header; + } + + /// + /// Convert from to + /// + private static Models.Metadata.Machine ConvertMachineToInternalModel(Models.Hashfile.Hashfile item) + { + var machine = new Models.Metadata.Machine(); + + if (item.SFV != null && item.SFV.Any()) + machine[Models.Metadata.Machine.RomKey] = item.SFV.Select(ConvertToInternalModel).ToArray(); + else if (item.MD5 != null && item.MD5.Any()) + machine[Models.Metadata.Machine.RomKey] = item.MD5.Select(ConvertToInternalModel).ToArray(); + else if (item.SHA1 != null && item.SHA1.Any()) + machine[Models.Metadata.Machine.RomKey] = item.SHA1.Select(ConvertToInternalModel).ToArray(); + else if (item.SHA256 != null && item.SHA256.Any()) + machine[Models.Metadata.Machine.RomKey] = item.SHA256.Select(ConvertToInternalModel).ToArray(); + else if (item.SHA384 != null && item.SHA384.Any()) + machine[Models.Metadata.Machine.RomKey] = item.SHA384.Select(ConvertToInternalModel).ToArray(); + else if (item.SHA512 != null && item.SHA512.Any()) + machine[Models.Metadata.Machine.RomKey] = item.SHA512.Select(ConvertToInternalModel).ToArray(); + else if (item.SpamSum != null && item.SpamSum.Any()) + machine[Models.Metadata.Machine.RomKey] = item.SpamSum.Select(ConvertToInternalModel).ToArray(); + + return machine; + } + + /// + /// Convert from to + /// + private static Models.Metadata.Rom ConvertToInternalModel(MD5 item) + { + var rom = new Models.Metadata.Rom + { + [Models.Metadata.Rom.MD5Key] = item.Hash, + [Models.Metadata.Rom.NameKey] = item.File, + }; + return rom; + } + + /// + /// Convert from to + /// + private static Models.Metadata.Rom ConvertToInternalModel(SFV item) + { + var rom = new Models.Metadata.Rom + { + [Models.Metadata.Rom.NameKey] = item.File, + [Models.Metadata.Rom.CRCKey] = item.Hash, + }; + return rom; + } + + /// + /// Convert from to + /// + private static Models.Metadata.Rom ConvertToInternalModel(SHA1 item) + { + var rom = new Models.Metadata.Rom + { + [Models.Metadata.Rom.SHA1Key] = item.Hash, + [Models.Metadata.Rom.NameKey] = item.File, + }; + return rom; + } + + /// + /// Convert from to + /// + private static Models.Metadata.Rom ConvertToInternalModel(SHA256 item) + { + var rom = new Models.Metadata.Rom + { + [Models.Metadata.Rom.SHA256Key] = item.Hash, + [Models.Metadata.Rom.NameKey] = item.File, + }; + return rom; + } + + /// + /// Convert from to + /// + private static Models.Metadata.Rom ConvertToInternalModel(SHA384 item) + { + var rom = new Models.Metadata.Rom + { + [Models.Metadata.Rom.SHA384Key] = item.Hash, + [Models.Metadata.Rom.NameKey] = item.File, + }; + return rom; + } + + /// + /// Convert from to + /// + private static Models.Metadata.Rom ConvertToInternalModel(SHA512 item) + { + var rom = new Models.Metadata.Rom + { + [Models.Metadata.Rom.SHA512Key] = item.Hash, + [Models.Metadata.Rom.NameKey] = item.File, + }; + return rom; + } + + /// + /// Convert from to + /// + private static Models.Metadata.Rom ConvertToInternalModel(SpamSum item) + { + var rom = new Models.Metadata.Rom + { + [Models.Metadata.Rom.SpamSumKey] = item.Hash, + [Models.Metadata.Rom.NameKey] = item.File, + }; + return rom; + } + } +} \ No newline at end of file diff --git a/Files/Hashfile.Deserializer.cs b/Files/Hashfile.Deserializer.cs new file mode 100644 index 00000000..f4538eda --- /dev/null +++ b/Files/Hashfile.Deserializer.cs @@ -0,0 +1,18 @@ +namespace SabreTools.Serialization.Files +{ + public partial class Hashfile : IFileSerializer + { + /// +#if NET48 + public Models.Hashfile.Hashfile Deserialize(string path) +#else + public Models.Hashfile.Hashfile? Deserialize(string? path) +#endif + { + using (var stream = PathProcessor.OpenStream(path)) + { + return new Streams.Hashfile().Deserialize(stream); + } + } + } +} \ No newline at end of file diff --git a/Files/Hashfile.Serializer.cs b/Files/Hashfile.Serializer.cs new file mode 100644 index 00000000..3122c0cd --- /dev/null +++ b/Files/Hashfile.Serializer.cs @@ -0,0 +1,25 @@ +namespace SabreTools.Serialization.Files +{ + public partial class Hashfile : IFileSerializer + { + /// +#if NET48 + public bool Serialize(Models.Hashfile.Hashfile obj, string path) +#else + public bool Serialize(Models.Hashfile.Hashfile? obj, string? path) +#endif + { + using (var stream = new Streams.Hashfile().Serialize(obj)) + { + if (stream == null) + return false; + + using (var fs = System.IO.File.OpenWrite(path)) + { + stream.CopyTo(fs); + return true; + } + } + } + } +} \ No newline at end of file diff --git a/Streams/HashFile.Deserializer.cs b/Streams/HashFile.Deserializer.cs new file mode 100644 index 00000000..3dac02b7 --- /dev/null +++ b/Streams/HashFile.Deserializer.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using SabreTools.Models.Hashfile; + +namespace SabreTools.Serialization.Streams +{ + public partial class Hashfile : IStreamSerializer + { + /// +#if NET48 + public Models.Hashfile.Hashfile Deserialize(Stream data) => Deserialize(data, Hash.CRC); +#else + public Models.Hashfile.Hashfile? Deserialize(Stream? data) => Deserialize(data, Hash.CRC); +#endif + + /// +#if NET48 + public Models.Hashfile.Hashfile Deserialize(Stream data, Hash hash) +#else + public Models.Hashfile.Hashfile? Deserialize(Stream? data, Hash hash) +#endif + { + // If the stream is null + if (data == null) + return default; + + // Setup the reader and output + var reader = new StreamReader(data); + var dat = new Models.Hashfile.Hashfile(); + var additional = new List(); + + // Loop through the rows and parse out values + var hashes = new List(); + while (!reader.EndOfStream) + { + // Read and split the line +#if NET48 + string line = reader.ReadLine(); + string[] lineParts = line?.Split(new char[] { ' ' } , StringSplitOptions.RemoveEmptyEntries); +#else + string? line = reader.ReadLine(); + string[]? lineParts = line?.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); +#endif + if (lineParts == null) + continue; + + // Parse the line into a hash + switch (hash) + { + case Hash.CRC: + var sfv = new SFV + { +#if NET48 + File = string.Join(" ", lineParts.Take(lineParts.Length - 1)), + Hash = lineParts[lineParts.Length - 1], +#else + File = string.Join(" ", lineParts[..^1]), + Hash = lineParts[^1], +#endif + }; + hashes.Add(sfv); + break; + case Hash.MD5: + var md5 = new MD5 + { + Hash = lineParts[0], +#if NET48 + File = string.Join(" ", lineParts.Skip(1)), +#else + File = string.Join(" ", lineParts[1..]), +#endif + }; + hashes.Add(md5); + break; + case Hash.SHA1: + var sha1 = new SHA1 + { + Hash = lineParts[0], +#if NET48 + File = string.Join(" ", lineParts.Skip(1)), +#else + File = string.Join(" ", lineParts[1..]), +#endif + }; + hashes.Add(sha1); + break; + case Hash.SHA256: + var sha256 = new SHA256 + { + Hash = lineParts[0], +#if NET48 + File = string.Join(" ", lineParts.Skip(1)), +#else + File = string.Join(" ", lineParts[1..]), +#endif + }; + hashes.Add(sha256); + break; + case Hash.SHA384: + var sha384 = new SHA384 + { + Hash = lineParts[0], +#if NET48 + File = string.Join(" ", lineParts.Skip(1)), +#else + File = string.Join(" ", lineParts[1..]), +#endif + }; + hashes.Add(sha384); + break; + case Hash.SHA512: + var sha512 = new SHA512 + { + Hash = lineParts[0], +#if NET48 + File = string.Join(" ", lineParts.Skip(1)), +#else + File = string.Join(" ", lineParts[1..]), +#endif + }; + hashes.Add(sha512); + break; + case Hash.SpamSum: + var spamSum = new SpamSum + { + Hash = lineParts[0], +#if NET48 + File = string.Join(" ", lineParts.Skip(1)), +#else + File = string.Join(" ", lineParts[1..]), +#endif + }; + hashes.Add(spamSum); + break; + } + } + + // Assign the hashes to the hashfile and return + switch (hash) + { + case Hash.CRC: + dat.SFV = hashes.Cast().ToArray(); + break; + case Hash.MD5: + dat.MD5 = hashes.Cast().ToArray(); + break; + case Hash.SHA1: + dat.SHA1 = hashes.Cast().ToArray(); + break; + case Hash.SHA256: + dat.SHA256 = hashes.Cast().ToArray(); + break; + case Hash.SHA384: + dat.SHA384 = hashes.Cast().ToArray(); + break; + case Hash.SHA512: + dat.SHA512 = hashes.Cast().ToArray(); + break; + case Hash.SpamSum: + dat.SpamSum = hashes.Cast().ToArray(); + break; + } + dat.ADDITIONAL_ELEMENTS = additional.ToArray(); + return dat; + } + } +} \ No newline at end of file diff --git a/Streams/Hashfile.Serializer.cs b/Streams/Hashfile.Serializer.cs new file mode 100644 index 00000000..c6e3d95d --- /dev/null +++ b/Streams/Hashfile.Serializer.cs @@ -0,0 +1,268 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using SabreTools.IO.Writers; +using SabreTools.Models.Hashfile; + +namespace SabreTools.Serialization.Streams +{ + public partial class Hashfile : IStreamSerializer + { + /// +#if NET48 + public Stream Serialize(Models.Hashfile.Hashfile obj) => Serialize(obj, Hash.CRC); +#else + public Stream? Serialize(Models.Hashfile.Hashfile? obj) => Serialize(obj, Hash.CRC); +#endif + + /// +#if NET48 + public Stream Serialize(Models.Hashfile.Hashfile obj, Hash hash) +#else + public Stream? Serialize(Models.Hashfile.Hashfile? obj, Hash hash) +#endif + { + // If the metadata file is null + if (obj == null) + return null; + + // Setup the writer and output + var stream = new MemoryStream(); + var writer = new SeparatedValueWriter(stream, Encoding.UTF8) + { + Separator = ' ', + Quotes = false, + VerifyFieldCount = false, + }; + + // Write out the items, if they exist + switch (hash) + { + case Hash.CRC: + WriteSFV(obj.SFV, writer); + break; + case Hash.MD5: + WriteMD5(obj.MD5, writer); + break; + case Hash.SHA1: + WriteSHA1(obj.SHA1, writer); + break; + case Hash.SHA256: + WriteSHA256(obj.SHA256, writer); + break; + case Hash.SHA384: + WriteSHA384(obj.SHA384, writer); + break; + case Hash.SHA512: + WriteSHA512(obj.SHA512, writer); + break; + case Hash.SpamSum: + WriteSpamSum(obj.SpamSum, writer); + break; + default: + throw new ArgumentOutOfRangeException(nameof(hash)); + } + + // Return the stream + stream.Seek(0, SeekOrigin.Begin); + return stream; + } + + /// + /// Write SFV information to the current writer + /// + /// Array of SFV objects representing the files + /// SeparatedValueWriter representing the output +#if NET48 + private static void WriteSFV(SFV[] sfvs, SeparatedValueWriter writer) +#else + private static void WriteSFV(SFV[]? sfvs, SeparatedValueWriter writer) +#endif + { + // If the item information is missing, we can't do anything + if (sfvs == null || !sfvs.Any()) + return; + + // Loop through and write out the items + foreach (var sfv in sfvs) + { + if (sfv == null) + continue; + if (string.IsNullOrWhiteSpace(sfv.File) || string.IsNullOrWhiteSpace(sfv.Hash)) + continue; + + writer.WriteValues(new string[] { sfv.File, sfv.Hash }); + writer.Flush(); + } + } + + /// + /// Write MD5 information to the current writer + /// + /// Array of MD5 objects representing the files + /// SeparatedValueWriter representing the output +#if NET48 + private static void WriteMD5(MD5[] md5s, SeparatedValueWriter writer) +#else + private static void WriteMD5(MD5[]? md5s, SeparatedValueWriter writer) +#endif + { + // If the item information is missing, we can't do anything + if (md5s == null || !md5s.Any()) + return; + + // Loop through and write out the items + foreach (var md5 in md5s) + { + if (md5 == null) + continue; + if (string.IsNullOrWhiteSpace(md5.Hash) || string.IsNullOrWhiteSpace(md5.File)) + continue; + + writer.WriteValues(new string[] { md5.Hash, md5.File }); + writer.Flush(); + } + } + + /// + /// Write SHA1 information to the current writer + /// + /// Array of SHA1 objects representing the files + /// SeparatedValueWriter representing the output +#if NET48 + private static void WriteSHA1(SHA1[] sha1s, SeparatedValueWriter writer) +#else + private static void WriteSHA1(SHA1[]? sha1s, SeparatedValueWriter writer) +#endif + { + // If the item information is missing, we can't do anything + if (sha1s == null || !sha1s.Any()) + return; + + // Loop through and write out the items + foreach (var sha1 in sha1s) + { + if (sha1 == null) + continue; + if (string.IsNullOrWhiteSpace(sha1.Hash) || string.IsNullOrWhiteSpace(sha1.File)) + continue; + + writer.WriteValues(new string[] { sha1.Hash, sha1.File }); + writer.Flush(); + } + } + + /// + /// Write SHA256 information to the current writer + /// + /// Array of SHA256 objects representing the files + /// SeparatedValueWriter representing the output +#if NET48 + private static void WriteSHA256(SHA256[] sha256s, SeparatedValueWriter writer) +#else + private static void WriteSHA256(SHA256[]? sha256s, SeparatedValueWriter writer) +#endif + { + // If the item information is missing, we can't do anything + if (sha256s == null || !sha256s.Any()) + return; + + // Loop through and write out the items + foreach (var sha256 in sha256s) + { + if (sha256 == null) + continue; + if (string.IsNullOrWhiteSpace(sha256.Hash) || string.IsNullOrWhiteSpace(sha256.File)) + continue; + + writer.WriteValues(new string[] { sha256.Hash, sha256.File }); + writer.Flush(); + } + } + + /// + /// Write SHA384 information to the current writer + /// + /// Array of SHA384 objects representing the files + /// SeparatedValueWriter representing the output +#if NET48 + private static void WriteSHA384(SHA384[] sha384s, SeparatedValueWriter writer) +#else + private static void WriteSHA384(SHA384[]? sha384s, SeparatedValueWriter writer) +#endif + { + // If the item information is missing, we can't do anything + if (sha384s == null || !sha384s.Any()) + return; + + // Loop through and write out the items + foreach (var sha384 in sha384s) + { + if (sha384 == null) + continue; + if (string.IsNullOrWhiteSpace(sha384.Hash) || string.IsNullOrWhiteSpace(sha384.File)) + continue; + + writer.WriteValues(new string[] { sha384.Hash, sha384.File }); + writer.Flush(); + } + } + + /// + /// Write SHA512 information to the current writer + /// + /// Array of SHA512 objects representing the files + /// SeparatedValueWriter representing the output +#if NET48 + private static void WriteSHA512(SHA512[] sha512s, SeparatedValueWriter writer) +#else + private static void WriteSHA512(SHA512[]? sha512s, SeparatedValueWriter writer) +#endif + { + // If the item information is missing, we can't do anything + if (sha512s == null || !sha512s.Any()) + return; + + // Loop through and write out the items + foreach (var sha512 in sha512s) + { + if (sha512 == null) + continue; + if (string.IsNullOrWhiteSpace(sha512.Hash) || string.IsNullOrWhiteSpace(sha512.File)) + continue; + + writer.WriteValues(new string[] { sha512.Hash, sha512.File }); + writer.Flush(); + } + } + + /// + /// Write SpamSum information to the current writer + /// + /// Array of SpamSum objects representing the files + /// SeparatedValueWriter representing the output +#if NET48 + private static void WriteSpamSum(SpamSum[] spamsums, SeparatedValueWriter writer) +#else + private static void WriteSpamSum(SpamSum[]? spamsums, SeparatedValueWriter writer) +#endif + { + // If the item information is missing, we can't do anything + if (spamsums == null || !spamsums.Any()) + return; + + // Loop through and write out the items + foreach (var spamsum in spamsums) + { + if (spamsum == null) + continue; + if (string.IsNullOrWhiteSpace(spamsum.Hash) || string.IsNullOrWhiteSpace(spamsum.File)) + continue; + + writer.WriteValues(new string[] { spamsum.Hash, spamsum.File }); + writer.Flush(); + } + } + } +} \ No newline at end of file