Let exceptions boil up

This commit is contained in:
Matt Nadareski
2023-07-30 09:00:15 -04:00
parent 9ae8036b0a
commit 378f9cbfd1
15 changed files with 1107 additions and 1321 deletions

View File

@@ -6,55 +6,55 @@ namespace SabreTools.Models.SeparatedValue
public class Row
{
/// <remarks>File Name</remarks>
public string FileName { get; set; }
public string? FileName { get; set; }
/// <remarks>Internal Name</remarks>
public string InternalName { get; set; }
public string? InternalName { get; set; }
/// <remarks>Description</remarks>
public string Description { get; set; }
public string? Description { get; set; }
/// <remarks>Game Name</remarks>
public string GameName { get; set; }
/// <remarks>Game Description</remarks>
public string GameDescription { get; set; }
public string? GameDescription { get; set; }
/// <remarks>Type</remarks>
public string Type { get; set; }
/// <remarks>Rom Name</remarks>
public string RomName { get; set; }
public string? RomName { get; set; }
/// <remarks>Disk Name</remarks>
public string DiskName { get; set; }
public string? DiskName { get; set; }
/// <remarks>Size, Numeric</remarks>
public string Size { get; set; }
public string? Size { get; set; }
/// <remarks>CRC</remarks>
public string CRC { get; set; }
public string? CRC { get; set; }
/// <remarks>MD5</remarks>
public string MD5 { get; set; }
public string? MD5 { get; set; }
/// <remarks>SHA1</remarks>
public string SHA1 { get; set; }
public string? SHA1 { get; set; }
/// <remarks>SHA256</remarks>
public string SHA256 { get; set; }
public string? SHA256 { get; set; }
/// <remarks>SHA384, Optional</remarks>
public string SHA384 { get; set; }
public string? SHA384 { get; set; }
/// <remarks>SHA512, Optional</remarks>
public string SHA512 { get; set; }
public string? SHA512 { get; set; }
/// <remarks>SpamSum, Optional</remarks>
public string SpamSum { get; set; }
public string? SpamSum { get; set; }
/// <remarks>Status, Nodump</remarks>
public string Status { get; set; }
public string? Status { get; set; }
#region DO NOT USE IN PRODUCTION

View File

@@ -19,16 +19,8 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(string path)
{
try
{
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream);
}
catch
{
// TODO: Handle logging the exception
return default;
}
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream);
}
/// <summary>
@@ -38,103 +30,95 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(Stream? stream)
{
try
// If the stream is null
if (stream == null)
return default;
// Setup the reader and output
var reader = new SeparatedValueReader(stream, Encoding.UTF8)
{
// If the stream is null
if (stream == null)
return default;
Separator = ';',
VerifyFieldCount = false,
};
var dat = new MetadataFile();
// Setup the reader and output
var reader = new SeparatedValueReader(stream, Encoding.UTF8)
// Read the header values first
if (!reader.ReadHeader())
return null;
dat.Header = reader.HeaderValues.ToArray();
// Loop through the rows and parse out values
var rows = new List<Row>();
while (!reader.EndOfStream)
{
// If we have no next line
if (!reader.ReadNextLine())
break;
// Parse the line into a row
Row? row = null;
if (reader.Line.Count < HeaderWithRomnameCount)
{
Separator = ';',
VerifyFieldCount = false,
};
var dat = new MetadataFile();
row = new Row
{
Name = reader.Line[0],
Title = reader.Line[1],
Emulator = reader.Line[2],
CloneOf = reader.Line[3],
Year = reader.Line[4],
Manufacturer = reader.Line[5],
Category = reader.Line[6],
Players = reader.Line[7],
Rotation = reader.Line[8],
Control = reader.Line[9],
Status = reader.Line[10],
DisplayCount = reader.Line[11],
DisplayType = reader.Line[12],
AltRomname = reader.Line[13],
AltTitle = reader.Line[14],
Extra = reader.Line[15],
Buttons = reader.Line[16],
};
// Read the header values first
if (!reader.ReadHeader())
return null;
dat.Header = reader.HeaderValues.ToArray();
// Loop through the rows and parse out values
var rows = new List<Row>();
while (!reader.EndOfStream)
// If we have additional fields
if (reader.Line.Count > HeaderWithoutRomnameCount)
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithoutRomnameCount).ToArray();
}
else
{
// If we have no next line
if (!reader.ReadNextLine())
break;
// Parse the line into a row
Row? row = null;
if (reader.Line.Count < HeaderWithRomnameCount)
row = new Row
{
row = new Row
{
Name = reader.Line[0],
Title = reader.Line[1],
Emulator = reader.Line[2],
CloneOf = reader.Line[3],
Year = reader.Line[4],
Manufacturer = reader.Line[5],
Category = reader.Line[6],
Players = reader.Line[7],
Rotation = reader.Line[8],
Control = reader.Line[9],
Status = reader.Line[10],
DisplayCount = reader.Line[11],
DisplayType = reader.Line[12],
AltRomname = reader.Line[13],
AltTitle = reader.Line[14],
Extra = reader.Line[15],
Buttons = reader.Line[16],
};
Name = reader.Line[0],
Title = reader.Line[1],
Emulator = reader.Line[2],
CloneOf = reader.Line[3],
Year = reader.Line[4],
Manufacturer = reader.Line[5],
Category = reader.Line[6],
Players = reader.Line[7],
Rotation = reader.Line[8],
Control = reader.Line[9],
Status = reader.Line[10],
DisplayCount = reader.Line[11],
DisplayType = reader.Line[12],
AltRomname = reader.Line[13],
AltTitle = reader.Line[14],
Extra = reader.Line[15],
Buttons = reader.Line[16],
};
// If we have additional fields
if (reader.Line.Count > HeaderWithoutRomnameCount)
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithoutRomnameCount).ToArray();
}
else
{
row = new Row
{
Name = reader.Line[0],
Title = reader.Line[1],
Emulator = reader.Line[2],
CloneOf = reader.Line[3],
Year = reader.Line[4],
Manufacturer = reader.Line[5],
Category = reader.Line[6],
Players = reader.Line[7],
Rotation = reader.Line[8],
Control = reader.Line[9],
Status = reader.Line[10],
DisplayCount = reader.Line[11],
DisplayType = reader.Line[12],
AltRomname = reader.Line[13],
AltTitle = reader.Line[14],
Extra = reader.Line[15],
Buttons = reader.Line[16],
};
// If we have additional fields
if (reader.Line.Count > HeaderWithRomnameCount)
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithRomnameCount).ToArray();
}
rows.Add(row);
// If we have additional fields
if (reader.Line.Count > HeaderWithRomnameCount)
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithRomnameCount).ToArray();
}
// Assign the rows to the Dat and return
dat.Row = rows.ToArray();
return dat;
}
catch
{
// TODO: Handle logging the exception
return default;
rows.Add(row);
}
// Assign the rows to the Dat and return
dat.Row = rows.ToArray();
return dat;
}
}
}

View File

@@ -19,22 +19,14 @@ namespace SabreTools.Serialization
/// <returns>True on successful serialization, false otherwise</returns>
public static bool SerializeToFile(MetadataFile? metadataFile, string path)
{
try
{
using var stream = SerializeToStream(metadataFile);
if (stream == null)
return false;
using var fs = File.OpenWrite(path);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fs);
return true;
}
catch
{
// TODO: Handle logging the exception
using var stream = SerializeToStream(metadataFile);
if (stream == null)
return false;
}
using var fs = File.OpenWrite(path);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fs);
return true;
}
/// <summary>
@@ -44,31 +36,28 @@ namespace SabreTools.Serialization
/// <returns>Stream containing serialized data on success, null otherwise</returns>
public static Stream? SerializeToStream(MetadataFile? metadataFile)
{
try
{
// If the metadata file is null
if (metadataFile == null)
return null;
// Setup the writer and output
var stream = new MemoryStream();
var writer = new SeparatedValueWriter(stream, Encoding.UTF8) { Separator = ';', Quotes = false };
// TODO: Include flag to write out long or short header
// Write the short header
writer.WriteString(HeaderWithoutRomname); // TODO: Convert to array of values
// Write out the rows, if they exist
WriteRows(metadataFile.Row, writer);
// Return the stream
return stream;
}
catch
{
// TODO: Handle logging the exception
// If the metadata file is null
if (metadataFile == null)
return null;
}
// Setup the writer and output
var stream = new MemoryStream();
var writer = new SeparatedValueWriter(stream, Encoding.UTF8)
{
Separator = ';',
Quotes = false,
VerifyFieldCount = false,
};
// TODO: Include flag to write out long or short header
// Write the short header
writer.WriteString(HeaderWithoutRomname); // TODO: Convert to array of values
// Write out the rows, if they exist
WriteRows(metadataFile.Row, writer);
// Return the stream
return stream;
}
/// <summary>
@@ -85,7 +74,7 @@ namespace SabreTools.Serialization
// Loop through and write out the rows
foreach (var row in rows)
{
var rowArray = new string[]
var rowArray = new string?[]
{
row.Name,
row.Title,

View File

@@ -19,16 +19,8 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(string path, bool quotes)
{
try
{
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream, quotes);
}
catch
{
// TODO: Handle logging the exception
return default;
}
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream, quotes);
}
/// <summary>
@@ -39,305 +31,297 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(Stream? stream, bool quotes)
{
try
// If the stream is null
if (stream == null)
return default;
// Setup the reader and output
var reader = new ClrMameProReader(stream, Encoding.UTF8) { Quotes = quotes };
var dat = new MetadataFile();
// Loop through and parse out the values
string lastTopLevel = reader.TopLevel;
GameBase? game = null;
var games = new List<GameBase>();
var releases = new List<Release>();
var biosSets = new List<BiosSet>();
var roms = new List<Rom>();
var disks = new List<Disk>();
var medias = new List<Media>();
var samples = new List<Sample>();
var archives = new List<Archive>();
var chips = new List<Chip>();
var dipSwitches = new List<DipSwitch>();
var additional = new List<string>();
var headerAdditional = new List<string>();
var gameAdditional = new List<string>();
while (!reader.EndOfStream)
{
// If the stream is null
if (stream == null)
return default;
// If we have no next line
if (!reader.ReadNextLine())
break;
// Setup the reader and output
var reader = new ClrMameProReader(stream, Encoding.UTF8) { Quotes = quotes };
var dat = new MetadataFile();
// Loop through and parse out the values
string lastTopLevel = reader.TopLevel;
GameBase? game = null;
var games = new List<GameBase>();
var releases = new List<Release>();
var biosSets = new List<BiosSet>();
var roms = new List<Rom>();
var disks = new List<Disk>();
var medias = new List<Media>();
var samples = new List<Sample>();
var archives = new List<Archive>();
var chips = new List<Chip>();
var dipSwitches = new List<DipSwitch>();
var additional = new List<string>();
var headerAdditional = new List<string>();
var gameAdditional = new List<string>();
while (!reader.EndOfStream)
// Ignore certain row types
switch (reader.RowType)
{
// If we have no next line
if (!reader.ReadNextLine())
break;
// Ignore certain row types
switch (reader.RowType)
{
case CmpRowType.None:
case CmpRowType.Comment:
continue;
case CmpRowType.EndTopLevel:
switch (lastTopLevel)
{
case "doscenter":
dat.ClrMamePro!.ADDITIONAL_ELEMENTS = headerAdditional.ToArray();
headerAdditional.Clear();
break;
case "game":
case "machine":
case "resource":
case "set":
game!.Release = releases.ToArray();
game.BiosSet = biosSets.ToArray();
game.Rom = roms.ToArray();
game.Disk = disks.ToArray();
game.Media = medias.ToArray();
game.Sample = samples.ToArray();
game.Archive = archives.ToArray();
game.Chip = chips.ToArray();
game.DipSwitch = dipSwitches.ToArray();
game.ADDITIONAL_ELEMENTS = gameAdditional.ToArray();
games.Add(game);
game = null;
releases.Clear();
biosSets.Clear();
roms.Clear();
disks.Clear();
medias.Clear();
samples.Clear();
archives.Clear();
chips.Clear();
dipSwitches.Clear();
gameAdditional.Clear();
break;
default:
// No-op
break;
}
continue;
}
// If we're at the root
if (reader.RowType == CmpRowType.TopLevel)
{
lastTopLevel = reader.TopLevel;
switch (reader.TopLevel)
case CmpRowType.None:
case CmpRowType.Comment:
continue;
case CmpRowType.EndTopLevel:
switch (lastTopLevel)
{
case "clrmamepro":
dat.ClrMamePro = new Models.ClrMamePro.ClrMamePro();
case "doscenter":
dat.ClrMamePro!.ADDITIONAL_ELEMENTS = headerAdditional.ToArray();
headerAdditional.Clear();
break;
case "game":
game = new Game();
break;
case "machine":
game = new Machine();
break;
case "resource":
game = new Resource();
break;
case "set":
game = new Set();
game!.Release = releases.ToArray();
game.BiosSet = biosSets.ToArray();
game.Rom = roms.ToArray();
game.Disk = disks.ToArray();
game.Media = medias.ToArray();
game.Sample = samples.ToArray();
game.Archive = archives.ToArray();
game.Chip = chips.ToArray();
game.DipSwitch = dipSwitches.ToArray();
game.ADDITIONAL_ELEMENTS = gameAdditional.ToArray();
games.Add(game);
game = null;
releases.Clear();
biosSets.Clear();
roms.Clear();
disks.Clear();
medias.Clear();
samples.Clear();
archives.Clear();
chips.Clear();
dipSwitches.Clear();
gameAdditional.Clear();
break;
default:
additional.Add(reader.CurrentLine);
// No-op
break;
}
}
continue;
}
// If we're in the doscenter block
else if (reader.TopLevel == "clrmamepro"
&& reader.RowType == CmpRowType.Standalone)
// If we're at the root
if (reader.RowType == CmpRowType.TopLevel)
{
lastTopLevel = reader.TopLevel;
switch (reader.TopLevel)
{
// Create the block if we haven't already
dat.ClrMamePro ??= new Models.ClrMamePro.ClrMamePro();
switch (reader.Standalone?.Key?.ToLowerInvariant())
{
case "name":
dat.ClrMamePro.Name = reader.Standalone?.Value;
break;
case "description":
dat.ClrMamePro.Description = reader.Standalone?.Value;
break;
case "rootdir":
dat.ClrMamePro.RootDir = reader.Standalone?.Value;
break;
case "category":
dat.ClrMamePro.Category = reader.Standalone?.Value;
break;
case "version":
dat.ClrMamePro.Version = reader.Standalone?.Value;
break;
case "date":
dat.ClrMamePro.Date = reader.Standalone?.Value;
break;
case "author":
dat.ClrMamePro.Author = reader.Standalone?.Value;
break;
case "homepage":
dat.ClrMamePro.Homepage = reader.Standalone?.Value;
break;
case "url":
dat.ClrMamePro.Url = reader.Standalone?.Value;
break;
case "comment":
dat.ClrMamePro.Comment = reader.Standalone?.Value;
break;
case "header":
dat.ClrMamePro.Header = reader.Standalone?.Value;
break;
case "type":
dat.ClrMamePro.Type = reader.Standalone?.Value;
break;
case "forcemerging":
dat.ClrMamePro.ForceMerging = reader.Standalone?.Value;
break;
case "forcezipping":
dat.ClrMamePro.ForceZipping = reader.Standalone?.Value;
break;
case "forcepacking":
dat.ClrMamePro.ForcePacking = reader.Standalone?.Value;
break;
default:
headerAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in a game, machine, resource, or set block
else if ((reader.TopLevel == "game"
|| reader.TopLevel == "machine"
|| reader.TopLevel == "resource"
|| reader.TopLevel == "set")
&& reader.RowType == CmpRowType.Standalone)
{
// Create the block if we haven't already
game ??= reader.TopLevel switch
{
"game" => new Game(),
"machine" => new Machine(),
"resource" => new Resource(),
"set" => new Set(),
_ => throw new FormatException($"Unknown top-level block: {reader.TopLevel}"),
};
switch (reader.Standalone?.Key?.ToLowerInvariant())
{
case "name":
game.Name = reader.Standalone?.Value;
break;
case "description":
game.Description = reader.Standalone?.Value;
break;
case "year":
game.Year = reader.Standalone?.Value;
break;
case "manufacturer":
game.Manufacturer = reader.Standalone?.Value;
break;
case "category":
game.Category = reader.Standalone?.Value;
break;
case "cloneof":
game.CloneOf = reader.Standalone?.Value;
break;
case "romof":
game.RomOf = reader.Standalone?.Value;
break;
case "sampleof":
game.SampleOf = reader.Standalone?.Value;
break;
case "sample":
var sample = new Sample
{
Name = reader.Standalone?.Value ?? string.Empty,
ADDITIONAL_ELEMENTS = Array.Empty<string>()
};
samples.Add(sample);
break;
default:
gameAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in an item block
else if ((reader.TopLevel == "game"
|| reader.TopLevel == "machine"
|| reader.TopLevel == "resource"
|| reader.TopLevel == "set")
&& game != null
&& reader.RowType == CmpRowType.Internal)
{
// Create the block
switch (reader.InternalName)
{
case "release":
releases.Add(CreateRelease(reader));
break;
case "biosset":
biosSets.Add(CreateBiosSet(reader));
break;
case "rom":
roms.Add(CreateRom(reader));
break;
case "disk":
disks.Add(CreateDisk(reader));
break;
case "media":
medias.Add(CreateMedia(reader));
break;
case "sample":
samples.Add(CreateSample(reader));
break;
case "archive":
archives.Add(CreateArchive(reader));
break;
case "chip":
chips.Add(CreateChip(reader));
break;
case "video":
game.Video = CreateVideo(reader);
break;
case "sound":
game.Sound = CreateSound(reader);
break;
case "input":
game.Input = CreateInput(reader);
break;
case "dipswitch":
dipSwitches.Add(CreateDipSwitch(reader));
break;
case "driver":
game.Driver = CreateDriver(reader);
break;
default:
gameAdditional.Add(reader.CurrentLine);
continue;
}
}
else
{
additional.Add(reader.CurrentLine);
case "clrmamepro":
dat.ClrMamePro = new Models.ClrMamePro.ClrMamePro();
break;
case "game":
game = new Game();
break;
case "machine":
game = new Machine();
break;
case "resource":
game = new Resource();
break;
case "set":
game = new Set();
break;
default:
additional.Add(reader.CurrentLine);
break;
}
}
// Add extra pieces and return
dat.Game = games.ToArray();
dat.ADDITIONAL_ELEMENTS = additional.ToArray();
return dat;
}
catch
{
// TODO: Handle logging the exception
return default;
// If we're in the doscenter block
else if (reader.TopLevel == "clrmamepro"
&& reader.RowType == CmpRowType.Standalone)
{
// Create the block if we haven't already
dat.ClrMamePro ??= new Models.ClrMamePro.ClrMamePro();
switch (reader.Standalone?.Key?.ToLowerInvariant())
{
case "name":
dat.ClrMamePro.Name = reader.Standalone?.Value;
break;
case "description":
dat.ClrMamePro.Description = reader.Standalone?.Value;
break;
case "rootdir":
dat.ClrMamePro.RootDir = reader.Standalone?.Value;
break;
case "category":
dat.ClrMamePro.Category = reader.Standalone?.Value;
break;
case "version":
dat.ClrMamePro.Version = reader.Standalone?.Value;
break;
case "date":
dat.ClrMamePro.Date = reader.Standalone?.Value;
break;
case "author":
dat.ClrMamePro.Author = reader.Standalone?.Value;
break;
case "homepage":
dat.ClrMamePro.Homepage = reader.Standalone?.Value;
break;
case "url":
dat.ClrMamePro.Url = reader.Standalone?.Value;
break;
case "comment":
dat.ClrMamePro.Comment = reader.Standalone?.Value;
break;
case "header":
dat.ClrMamePro.Header = reader.Standalone?.Value;
break;
case "type":
dat.ClrMamePro.Type = reader.Standalone?.Value;
break;
case "forcemerging":
dat.ClrMamePro.ForceMerging = reader.Standalone?.Value;
break;
case "forcezipping":
dat.ClrMamePro.ForceZipping = reader.Standalone?.Value;
break;
case "forcepacking":
dat.ClrMamePro.ForcePacking = reader.Standalone?.Value;
break;
default:
headerAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in a game, machine, resource, or set block
else if ((reader.TopLevel == "game"
|| reader.TopLevel == "machine"
|| reader.TopLevel == "resource"
|| reader.TopLevel == "set")
&& reader.RowType == CmpRowType.Standalone)
{
// Create the block if we haven't already
game ??= reader.TopLevel switch
{
"game" => new Game(),
"machine" => new Machine(),
"resource" => new Resource(),
"set" => new Set(),
_ => throw new FormatException($"Unknown top-level block: {reader.TopLevel}"),
};
switch (reader.Standalone?.Key?.ToLowerInvariant())
{
case "name":
game.Name = reader.Standalone?.Value;
break;
case "description":
game.Description = reader.Standalone?.Value;
break;
case "year":
game.Year = reader.Standalone?.Value;
break;
case "manufacturer":
game.Manufacturer = reader.Standalone?.Value;
break;
case "category":
game.Category = reader.Standalone?.Value;
break;
case "cloneof":
game.CloneOf = reader.Standalone?.Value;
break;
case "romof":
game.RomOf = reader.Standalone?.Value;
break;
case "sampleof":
game.SampleOf = reader.Standalone?.Value;
break;
case "sample":
var sample = new Sample
{
Name = reader.Standalone?.Value ?? string.Empty,
ADDITIONAL_ELEMENTS = Array.Empty<string>()
};
samples.Add(sample);
break;
default:
gameAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in an item block
else if ((reader.TopLevel == "game"
|| reader.TopLevel == "machine"
|| reader.TopLevel == "resource"
|| reader.TopLevel == "set")
&& game != null
&& reader.RowType == CmpRowType.Internal)
{
// Create the block
switch (reader.InternalName)
{
case "release":
releases.Add(CreateRelease(reader));
break;
case "biosset":
biosSets.Add(CreateBiosSet(reader));
break;
case "rom":
roms.Add(CreateRom(reader));
break;
case "disk":
disks.Add(CreateDisk(reader));
break;
case "media":
medias.Add(CreateMedia(reader));
break;
case "sample":
samples.Add(CreateSample(reader));
break;
case "archive":
archives.Add(CreateArchive(reader));
break;
case "chip":
chips.Add(CreateChip(reader));
break;
case "video":
game.Video = CreateVideo(reader);
break;
case "sound":
game.Sound = CreateSound(reader);
break;
case "input":
game.Input = CreateInput(reader);
break;
case "dipswitch":
dipSwitches.Add(CreateDipSwitch(reader));
break;
case "driver":
game.Driver = CreateDriver(reader);
break;
default:
gameAdditional.Add(reader.CurrentLine);
continue;
}
}
else
{
additional.Add(reader.CurrentLine);
}
}
// Add extra pieces and return
dat.Game = games.ToArray();
dat.ADDITIONAL_ELEMENTS = additional.ToArray();
return dat;
}
/// <summary>

View File

@@ -20,22 +20,14 @@ namespace SabreTools.Serialization
/// <returns>True on successful serialization, false otherwise</returns>
public static bool SerializeToFile(MetadataFile? metadataFile, string path, bool quotes)
{
try
{
using var stream = SerializeToStream(metadataFile, quotes);
if (stream == null)
return false;
using var fs = File.OpenWrite(path);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fs);
return true;
}
catch
{
// TODO: Handle logging the exception
using var stream = SerializeToStream(metadataFile, quotes);
if (stream == null)
return false;
}
using var fs = File.OpenWrite(path);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fs);
return true;
}
/// <summary>
@@ -46,30 +38,22 @@ namespace SabreTools.Serialization
/// <returns>Stream containing serialized data on success, null otherwise</returns>
public static Stream? SerializeToStream(MetadataFile? metadataFile, bool quotes)
{
try
{
// If the metadata file is null
if (metadataFile == null)
return null;
// Setup the writer and output
var stream = new MemoryStream();
var writer = new ClrMameProWriter(stream, Encoding.UTF8) { Quotes = quotes };
// Write the header, if it exists
WriteHeader(metadataFile.ClrMamePro, writer);
// Write out the games, if they exist
WriteGames(metadataFile.Game, writer);
// Return the stream
return stream;
}
catch
{
// TODO: Handle logging the exception
// If the metadata file is null
if (metadataFile == null)
return null;
}
// Setup the writer and output
var stream = new MemoryStream();
var writer = new ClrMameProWriter(stream, Encoding.UTF8) { Quotes = quotes };
// Write the header, if it exists
WriteHeader(metadataFile.ClrMamePro, writer);
// Write out the games, if they exist
WriteGames(metadataFile.Game, writer);
// Return the stream
return stream;
}
/// <summary>

View File

@@ -19,16 +19,8 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(string path)
{
try
{
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream);
}
catch
{
// TODO: Handle logging the exception
return default;
}
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream);
}
/// <summary>
@@ -38,59 +30,51 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(Stream? stream)
{
try
{
// If the stream is null
if (stream == null)
return default;
// Setup the reader and output
var reader = new SeparatedValueReader(stream, Encoding.UTF8)
{
Header = false,
Separator = '\t',
VerifyFieldCount = false,
};
var dat = new MetadataFile();
// Loop through the rows and parse out values
var rows = new List<Row>();
while (!reader.EndOfStream)
{
// If we have no next line
if (!reader.ReadNextLine())
break;
// Parse the line into a row
var row = new Row
{
SHA256 = reader.Line[0],
Name = reader.Line[1],
SHA1 = reader.Line[2],
MD5 = reader.Line[3],
CRC32 = reader.Line[4],
};
// If we have the size field
if (reader.Line.Count > 5)
row.Size = reader.Line[5];
// If we have additional fields
if (reader.Line.Count > 6)
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(5).ToArray();
rows.Add(row);
}
// Assign the rows to the Dat and return
dat.Row = rows.ToArray();
return dat;
}
catch
{
// TODO: Handle logging the exception
// If the stream is null
if (stream == null)
return default;
// Setup the reader and output
var reader = new SeparatedValueReader(stream, Encoding.UTF8)
{
Header = false,
Separator = '\t',
VerifyFieldCount = false,
};
var dat = new MetadataFile();
// Loop through the rows and parse out values
var rows = new List<Row>();
while (!reader.EndOfStream)
{
// If we have no next line
if (!reader.ReadNextLine())
break;
// Parse the line into a row
var row = new Row
{
SHA256 = reader.Line[0],
Name = reader.Line[1],
SHA1 = reader.Line[2],
MD5 = reader.Line[3],
CRC32 = reader.Line[4],
};
// If we have the size field
if (reader.Line.Count > 5)
row.Size = reader.Line[5];
// If we have additional fields
if (reader.Line.Count > 6)
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(5).ToArray();
rows.Add(row);
}
// Assign the rows to the Dat and return
dat.Row = rows.ToArray();
return dat;
}
}
}

View File

@@ -20,22 +20,14 @@ namespace SabreTools.Serialization
/// <returns>True on successful serialization, false otherwise</returns>
public static bool SerializeToFile(MetadataFile? metadataFile, string path)
{
try
{
using var stream = SerializeToStream(metadataFile);
if (stream == null)
return false;
using var fs = File.OpenWrite(path);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fs);
return true;
}
catch
{
// TODO: Handle logging the exception
using var stream = SerializeToStream(metadataFile);
if (stream == null)
return false;
}
using var fs = File.OpenWrite(path);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fs);
return true;
}
/// <summary>
@@ -45,27 +37,19 @@ namespace SabreTools.Serialization
/// <returns>Stream containing serialized data on success, null otherwise</returns>
public static Stream? SerializeToStream(MetadataFile? metadataFile)
{
try
{
// If the metadata file is null
if (metadataFile == null)
return null;
// Setup the writer and output
var stream = new MemoryStream();
var writer = new SeparatedValueWriter(stream, Encoding.UTF8) { Separator = '\t', Quotes = false };
// Write out the rows, if they exist
WriteRows(metadataFile.Row, writer);
// Return the stream
return stream;
}
catch
{
// TODO: Handle logging the exception
// If the metadata file is null
if (metadataFile == null)
return null;
}
// Setup the writer and output
var stream = new MemoryStream();
var writer = new SeparatedValueWriter(stream, Encoding.UTF8) { Separator = '\t', Quotes = false };
// Write out the rows, if they exist
WriteRows(metadataFile.Row, writer);
// Return the stream
return stream;
}
/// <summary>

View File

@@ -19,16 +19,8 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static Models.Hashfile.Hashfile? Deserialize(string path, Hash hash)
{
try
{
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream, hash);
}
catch
{
// TODO: Handle logging the exception
return default;
}
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream, hash);
}
/// <summary>
@@ -39,122 +31,114 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static Models.Hashfile.Hashfile? Deserialize(Stream? stream, Hash hash)
{
try
// If the stream is null
if (stream == null)
return default;
// Setup the reader and output
var reader = new StreamReader(stream);
var dat = new Models.Hashfile.Hashfile();
var additional = new List<string>();
// Loop through the rows and parse out values
var hashes = new List<object>();
while (!reader.EndOfStream)
{
// If the stream is null
if (stream == null)
return default;
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (lineParts == null)
continue;
// Setup the reader and output
var reader = new StreamReader(stream);
var dat = new Models.Hashfile.Hashfile();
var additional = new List<string>();
// Loop through the rows and parse out values
var hashes = new List<object>();
while (!reader.EndOfStream)
{
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (lineParts == null)
continue;
// Parse the line into a hash
switch (hash)
{
case Hash.CRC:
var sfv = new Models.Hashfile.SFV
{
File = string.Join(" ", lineParts[..^1]),
Hash = string.Join(" ", lineParts[^1]),
};
hashes.Add(sfv);
break;
case Hash.MD5:
var md5 = new Models.Hashfile.MD5
{
Hash = lineParts[0],
File = string.Join(" ", lineParts[1..]),
};
hashes.Add(md5);
break;
case Hash.SHA1:
var sha1 = new Models.Hashfile.SHA1
{
Hash = lineParts[0],
File = string.Join(" ", lineParts[1..]),
};
hashes.Add(sha1);
break;
case Hash.SHA256:
var sha256 = new Models.Hashfile.SHA256
{
Hash = lineParts[0],
File = string.Join(" ", lineParts[1..]),
};
hashes.Add(sha256);
break;
case Hash.SHA384:
var sha384 = new Models.Hashfile.SHA384
{
Hash = lineParts[0],
File = string.Join(" ", lineParts[1..]),
};
hashes.Add(sha384);
break;
case Hash.SHA512:
var sha512 = new Models.Hashfile.SHA512
{
Hash = lineParts[0],
File = string.Join(" ", lineParts[1..]),
};
hashes.Add(sha512);
break;
case Hash.SpamSum:
var spamSum = new Models.Hashfile.SpamSum
{
Hash = lineParts[0],
File = string.Join(" ", lineParts[1..]),
};
hashes.Add(spamSum);
break;
}
}
// Assign the hashes to the hashfile and return
// Parse the line into a hash
switch (hash)
{
case Hash.CRC:
dat.SFV = hashes.Cast<Models.Hashfile.SFV>().ToArray();
var sfv = new Models.Hashfile.SFV
{
File = string.Join(" ", lineParts[..^1]),
Hash = string.Join(" ", lineParts[^1]),
};
hashes.Add(sfv);
break;
case Hash.MD5:
dat.MD5 = hashes.Cast<Models.Hashfile.MD5>().ToArray();
var md5 = new Models.Hashfile.MD5
{
Hash = lineParts[0],
File = string.Join(" ", lineParts[1..]),
};
hashes.Add(md5);
break;
case Hash.SHA1:
dat.SHA1 = hashes.Cast<Models.Hashfile.SHA1>().ToArray();
var sha1 = new Models.Hashfile.SHA1
{
Hash = lineParts[0],
File = string.Join(" ", lineParts[1..]),
};
hashes.Add(sha1);
break;
case Hash.SHA256:
dat.SHA256 = hashes.Cast<Models.Hashfile.SHA256>().ToArray();
var sha256 = new Models.Hashfile.SHA256
{
Hash = lineParts[0],
File = string.Join(" ", lineParts[1..]),
};
hashes.Add(sha256);
break;
case Hash.SHA384:
dat.SHA384 = hashes.Cast<Models.Hashfile.SHA384>().ToArray();
var sha384 = new Models.Hashfile.SHA384
{
Hash = lineParts[0],
File = string.Join(" ", lineParts[1..]),
};
hashes.Add(sha384);
break;
case Hash.SHA512:
dat.SHA512 = hashes.Cast<Models.Hashfile.SHA512>().ToArray();
var sha512 = new Models.Hashfile.SHA512
{
Hash = lineParts[0],
File = string.Join(" ", lineParts[1..]),
};
hashes.Add(sha512);
break;
case Hash.SpamSum:
dat.SpamSum = hashes.Cast<Models.Hashfile.SpamSum>().ToArray();
var spamSum = new Models.Hashfile.SpamSum
{
Hash = lineParts[0],
File = string.Join(" ", lineParts[1..]),
};
hashes.Add(spamSum);
break;
}
dat.ADDITIONAL_ELEMENTS = additional.ToArray();
return dat;
}
catch
// Assign the hashes to the hashfile and return
switch (hash)
{
// TODO: Handle logging the exception
return default;
case Hash.CRC:
dat.SFV = hashes.Cast<Models.Hashfile.SFV>().ToArray();
break;
case Hash.MD5:
dat.MD5 = hashes.Cast<Models.Hashfile.MD5>().ToArray();
break;
case Hash.SHA1:
dat.SHA1 = hashes.Cast<Models.Hashfile.SHA1>().ToArray();
break;
case Hash.SHA256:
dat.SHA256 = hashes.Cast<Models.Hashfile.SHA256>().ToArray();
break;
case Hash.SHA384:
dat.SHA384 = hashes.Cast<Models.Hashfile.SHA384>().ToArray();
break;
case Hash.SHA512:
dat.SHA512 = hashes.Cast<Models.Hashfile.SHA512>().ToArray();
break;
case Hash.SpamSum:
dat.SpamSum = hashes.Cast<Models.Hashfile.SpamSum>().ToArray();
break;
}
dat.ADDITIONAL_ELEMENTS = additional.ToArray();
return dat;
}
}
}

View File

@@ -22,22 +22,14 @@ namespace SabreTools.Serialization
/// <returns>True on successful serialization, false otherwise</returns>
public static bool SerializeToFile(Models.Hashfile.Hashfile? hashfile, string path, Hash hash)
{
try
{
using var stream = SerializeToStream(hashfile, hash);
if (stream == null)
return false;
using var fs = File.OpenWrite(path);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fs);
return true;
}
catch
{
// TODO: Handle logging the exception
using var stream = SerializeToStream(hashfile, hash);
if (stream == null)
return false;
}
using var fs = File.OpenWrite(path);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fs);
return true;
}
/// <summary>
@@ -48,52 +40,49 @@ namespace SabreTools.Serialization
/// <returns>Stream containing serialized data on success, null otherwise</returns>
public static Stream? SerializeToStream(Models.Hashfile.Hashfile? hashfile, Hash hash)
{
try
{
// If the metadata file is null
if (hashfile == null)
return null;
// Setup the writer and output
var stream = new MemoryStream();
var writer = new SeparatedValueWriter(stream, Encoding.UTF8) { Separator = ' ', Quotes = false };
// Write out the items, if they exist
switch (hash)
{
case Hash.CRC:
WriteSFV(hashfile.SFV, writer);
break;
case Hash.MD5:
WriteMD5(hashfile.MD5, writer);
break;
case Hash.SHA1:
WriteSHA1(hashfile.SHA1, writer);
break;
case Hash.SHA256:
WriteSHA256(hashfile.SHA256, writer);
break;
case Hash.SHA384:
WriteSHA384(hashfile.SHA384, writer);
break;
case Hash.SHA512:
WriteSHA512(hashfile.SHA512, writer);
break;
case Hash.SpamSum:
WriteSpamSum(hashfile.SpamSum, writer);
break;
default:
throw new ArgumentOutOfRangeException(nameof(hash));
}
// Return the stream
return stream;
}
catch
{
// TODO: Handle logging the exception
// If the metadata file is null
if (hashfile == 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(hashfile.SFV, writer);
break;
case Hash.MD5:
WriteMD5(hashfile.MD5, writer);
break;
case Hash.SHA1:
WriteSHA1(hashfile.SHA1, writer);
break;
case Hash.SHA256:
WriteSHA256(hashfile.SHA256, writer);
break;
case Hash.SHA384:
WriteSHA384(hashfile.SHA384, writer);
break;
case Hash.SHA512:
WriteSHA512(hashfile.SHA512, writer);
break;
case Hash.SpamSum:
WriteSpamSum(hashfile.SpamSum, writer);
break;
default:
throw new ArgumentOutOfRangeException(nameof(hash));
}
// Return the stream
return stream;
}
/// <summary>

View File

@@ -18,16 +18,8 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(string path)
{
try
{
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream);
}
catch
{
// TODO: Handle logging the exception
return default;
}
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream);
}
/// <summary>
@@ -37,161 +29,153 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(Stream? stream)
{
try
{
// If the stream is null
if (stream == null)
return default;
// Setup the reader and output
var reader = new StreamReader(stream, Encoding.UTF8);
var dat = new MetadataFile();
Set? set = null;
var sets = new List<Set?>();
var rows = new List<Row?>();
var additional = new List<string>();
while (!reader.EndOfStream)
{
// Read the line and don't split yet
string? line = reader.ReadLine();
if (string.IsNullOrWhiteSpace(line))
{
// If we have a set to process
if (set != null)
{
set.Row = rows.ToArray();
sets.Add(set);
set = null;
rows.Clear();
}
continue;
}
// Set lines are unique
if (line.StartsWith("ROMs required for driver"))
{
string driver = line["ROMs required for driver".Length..].Trim('"', ' ', '.');
set = new Set { Driver = driver };
continue;
}
else if (line.StartsWith("No ROMs required for driver"))
{
string driver = line["No ROMs required for driver".Length..].Trim('"', ' ', '.');
set = new Set { Driver = driver };
continue;
}
else if (line.StartsWith("ROMs required for device"))
{
string device = line["ROMs required for device".Length..].Trim('"', ' ', '.');
set = new Set { Device = device };
continue;
}
else if (line.StartsWith("No ROMs required for device"))
{
string device = line["No ROMs required for device".Length..].Trim('"', ' ', '.');
set = new Set { Device = device };
continue;
}
else if (line.Equals("Name Size Checksum", StringComparison.OrdinalIgnoreCase))
{
// No-op
continue;
}
// Split the line for the name iteratively
string[]? lineParts = line?.Split(" ", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (lineParts?.Length == 1)
lineParts = line?.Split(" ", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (lineParts?.Length == 1)
lineParts = line?.Split(" ", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (lineParts?.Length == 1)
lineParts = line?.Split(" ", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
// Read the name and set the rest of the line for processing
string name = lineParts[0];
string trimmedLine = line[name.Length..];
lineParts = trimmedLine?.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
// The number of items in the row explains what type of row it is
var row = new Row();
switch (lineParts.Length)
{
// Normal CHD (Name, SHA1)
case 1:
row.Name = name;
row.SHA1 = lineParts[0]["SHA1".Length..].Trim('(', ')');
break;
// Normal ROM (Name, Size, CRC, SHA1)
case 3 when line.Contains("CRC"):
row.Name = name;
row.Size = lineParts[0];
row.CRC = lineParts[1]["CRC".Length..].Trim('(', ')');
row.SHA1 = lineParts[2]["SHA1".Length..].Trim('(', ')');
break;
// Bad CHD (Name, BAD, SHA1, BAD_DUMP)
case 3 when line.Contains("BAD_DUMP"):
row.Name = name;
row.Bad = true;
row.SHA1 = lineParts[1]["SHA1".Length..].Trim('(', ')');
break;
// Nodump CHD (Name, NO GOOD DUMP KNOWN)
case 4 when line.Contains("NO GOOD DUMP KNOWN"):
row.Name = name;
row.NoGoodDumpKnown = true;
break;
// Bad ROM (Name, Size, BAD, CRC, SHA1, BAD_DUMP)
case 5 when line.Contains("BAD_DUMP"):
row.Name = name;
row.Size = lineParts[0];
row.Bad = true;
row.CRC = lineParts[2]["CRC".Length..].Trim('(', ')');
row.SHA1 = lineParts[3]["SHA1".Length..].Trim('(', ')');
break;
// Nodump ROM (Name, Size, NO GOOD DUMP KNOWN)
case 5 when line.Contains("NO GOOD DUMP KNOWN"):
row.Name = name;
row.Size = lineParts[0];
row.NoGoodDumpKnown = true;
break;
default:
row = null;
additional.Add(line);
break;
}
if (row != null)
rows.Add(row);
}
// If we have a set to process
if (set != null)
{
set.Row = rows.ToArray();
sets.Add(set);
set = null;
rows.Clear();
}
// Add extra pieces and return
dat.Set = sets.ToArray();
dat.ADDITIONAL_ELEMENTS = additional.ToArray();
return dat;
}
catch
{
// TODO: Handle logging the exception
// If the stream is null
if (stream == null)
return default;
// Setup the reader and output
var reader = new StreamReader(stream, Encoding.UTF8);
var dat = new MetadataFile();
Set? set = null;
var sets = new List<Set?>();
var rows = new List<Row?>();
var additional = new List<string>();
while (!reader.EndOfStream)
{
// Read the line and don't split yet
string? line = reader.ReadLine();
if (string.IsNullOrWhiteSpace(line))
{
// If we have a set to process
if (set != null)
{
set.Row = rows.ToArray();
sets.Add(set);
set = null;
rows.Clear();
}
continue;
}
// Set lines are unique
if (line.StartsWith("ROMs required for driver"))
{
string driver = line["ROMs required for driver".Length..].Trim('"', ' ', '.');
set = new Set { Driver = driver };
continue;
}
else if (line.StartsWith("No ROMs required for driver"))
{
string driver = line["No ROMs required for driver".Length..].Trim('"', ' ', '.');
set = new Set { Driver = driver };
continue;
}
else if (line.StartsWith("ROMs required for device"))
{
string device = line["ROMs required for device".Length..].Trim('"', ' ', '.');
set = new Set { Device = device };
continue;
}
else if (line.StartsWith("No ROMs required for device"))
{
string device = line["No ROMs required for device".Length..].Trim('"', ' ', '.');
set = new Set { Device = device };
continue;
}
else if (line.Equals("Name Size Checksum", StringComparison.OrdinalIgnoreCase))
{
// No-op
continue;
}
// Split the line for the name iteratively
string[]? lineParts = line?.Split(" ", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (lineParts?.Length == 1)
lineParts = line?.Split(" ", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (lineParts?.Length == 1)
lineParts = line?.Split(" ", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (lineParts?.Length == 1)
lineParts = line?.Split(" ", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
// Read the name and set the rest of the line for processing
string name = lineParts[0];
string trimmedLine = line[name.Length..];
lineParts = trimmedLine?.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
// The number of items in the row explains what type of row it is
var row = new Row();
switch (lineParts.Length)
{
// Normal CHD (Name, SHA1)
case 1:
row.Name = name;
row.SHA1 = lineParts[0]["SHA1".Length..].Trim('(', ')');
break;
// Normal ROM (Name, Size, CRC, SHA1)
case 3 when line.Contains("CRC"):
row.Name = name;
row.Size = lineParts[0];
row.CRC = lineParts[1]["CRC".Length..].Trim('(', ')');
row.SHA1 = lineParts[2]["SHA1".Length..].Trim('(', ')');
break;
// Bad CHD (Name, BAD, SHA1, BAD_DUMP)
case 3 when line.Contains("BAD_DUMP"):
row.Name = name;
row.Bad = true;
row.SHA1 = lineParts[1]["SHA1".Length..].Trim('(', ')');
break;
// Nodump CHD (Name, NO GOOD DUMP KNOWN)
case 4 when line.Contains("NO GOOD DUMP KNOWN"):
row.Name = name;
row.NoGoodDumpKnown = true;
break;
// Bad ROM (Name, Size, BAD, CRC, SHA1, BAD_DUMP)
case 5 when line.Contains("BAD_DUMP"):
row.Name = name;
row.Size = lineParts[0];
row.Bad = true;
row.CRC = lineParts[2]["CRC".Length..].Trim('(', ')');
row.SHA1 = lineParts[3]["SHA1".Length..].Trim('(', ')');
break;
// Nodump ROM (Name, Size, NO GOOD DUMP KNOWN)
case 5 when line.Contains("NO GOOD DUMP KNOWN"):
row.Name = name;
row.Size = lineParts[0];
row.NoGoodDumpKnown = true;
break;
default:
row = null;
additional.Add(line);
break;
}
if (row != null)
rows.Add(row);
}
// If we have a set to process
if (set != null)
{
set.Row = rows.ToArray();
sets.Add(set);
set = null;
rows.Clear();
}
// Add extra pieces and return
dat.Set = sets.ToArray();
dat.ADDITIONAL_ELEMENTS = additional.ToArray();
return dat;
}
}
}

View File

@@ -19,16 +19,8 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(string path)
{
try
{
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream);
}
catch
{
// TODO: Handle logging the exception
return default;
}
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream);
}
/// <summary>
@@ -38,203 +30,195 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(Stream? stream)
{
try
{
// If the stream is null
if (stream == null)
return default;
// Setup the reader and output
var reader = new IniReader(stream, Encoding.UTF8)
{
ValidateRows = false,
};
var dat = new MetadataFile();
// Loop through and parse out the values
var roms = new List<Rom>();
var additional = new List<string>();
var creditsAdditional = new List<string>();
var datAdditional = new List<string>();
var emulatorAdditional = new List<string>();
var gamesAdditional = new List<string>();
while (!reader.EndOfStream)
{
// If we have no next line
if (!reader.ReadNextLine())
break;
// Ignore certain row types
switch (reader.RowType)
{
case IniRowType.None:
case IniRowType.Comment:
continue;
case IniRowType.SectionHeader:
switch (reader.Section.ToLowerInvariant())
{
case "credits":
dat.Credits ??= new Credits();
break;
case "dat":
dat.Dat ??= new Dat();
break;
case "emulator":
dat.Emulator ??= new Emulator();
break;
case "games":
dat.Games ??= new Games();
break;
default:
additional.Add(reader.CurrentLine);
break;
}
continue;
}
// If we're in credits
if (reader.Section.ToLowerInvariant() == "credits")
{
// Create the section if we haven't already
dat.Credits ??= new Credits();
switch (reader.KeyValuePair?.Key?.ToLowerInvariant())
{
case "author":
dat.Credits.Author = reader.KeyValuePair?.Value;
break;
case "version":
dat.Credits.Version = reader.KeyValuePair?.Value;
break;
case "email":
dat.Credits.Email = reader.KeyValuePair?.Value;
break;
case "homepage":
dat.Credits.Homepage = reader.KeyValuePair?.Value;
break;
case "url":
dat.Credits.Url = reader.KeyValuePair?.Value;
break;
case "date":
dat.Credits.Date = reader.KeyValuePair?.Value;
break;
case "comment":
dat.Credits.Comment = reader.KeyValuePair?.Value;
break;
default:
creditsAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in dat
else if (reader.Section.ToLowerInvariant() == "dat")
{
// Create the section if we haven't already
dat.Dat ??= new Dat();
switch (reader.KeyValuePair?.Key?.ToLowerInvariant())
{
case "version":
dat.Dat.Version = reader.KeyValuePair?.Value;
break;
case "plugin":
dat.Dat.Plugin = reader.KeyValuePair?.Value;
break;
case "split":
dat.Dat.Split = reader.KeyValuePair?.Value;
break;
case "merge":
dat.Dat.Merge = reader.KeyValuePair?.Value;
break;
default:
datAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in emulator
else if (reader.Section.ToLowerInvariant() == "emulator")
{
// Create the section if we haven't already
dat.Emulator ??= new Emulator();
switch (reader.KeyValuePair?.Key?.ToLowerInvariant())
{
case "refname":
dat.Emulator.RefName = reader.KeyValuePair?.Value;
break;
case "version":
dat.Emulator.Version = reader.KeyValuePair?.Value;
break;
default:
emulatorAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in games
else if (reader.Section.ToLowerInvariant() == "games")
{
// Create the section if we haven't already
dat.Games ??= new Games();
// If the line doesn't contain the delimiter
if (!reader.CurrentLine.Contains('¬'))
{
gamesAdditional.Add(reader.CurrentLine);
continue;
}
// Otherwise, separate out the line
string[] splitLine = reader.CurrentLine.Split('¬');
var rom = new Rom
{
// EMPTY = splitLine[0]
ParentName = splitLine[1],
ParentDescription = splitLine[2],
GameName = splitLine[3],
GameDescription = splitLine[4],
RomName = splitLine[5],
RomCRC = splitLine[6],
RomSize = splitLine[7],
RomOf = splitLine[8],
MergeName = splitLine[9],
// EMPTY = splitLine[10]
};
if (splitLine.Length > 11)
rom.ADDITIONAL_ELEMENTS = splitLine.Skip(11).ToArray();
roms.Add(rom);
}
else
{
additional.Add(item: reader.CurrentLine);
}
}
// Add extra pieces and return
dat.ADDITIONAL_ELEMENTS = additional.ToArray();
if (dat.Credits != null)
dat.Credits.ADDITIONAL_ELEMENTS = creditsAdditional.ToArray();
if (dat.Dat != null)
dat.Dat.ADDITIONAL_ELEMENTS = datAdditional.ToArray();
if (dat.Emulator != null)
dat.Emulator.ADDITIONAL_ELEMENTS = emulatorAdditional.ToArray();
if (dat.Games != null)
{
dat.Games.Rom = roms.ToArray();
dat.Games.ADDITIONAL_ELEMENTS = gamesAdditional.ToArray();
}
return dat;
}
catch
{
// TODO: Handle logging the exception
// If the stream is null
if (stream == null)
return default;
// Setup the reader and output
var reader = new IniReader(stream, Encoding.UTF8)
{
ValidateRows = false,
};
var dat = new MetadataFile();
// Loop through and parse out the values
var roms = new List<Rom>();
var additional = new List<string>();
var creditsAdditional = new List<string>();
var datAdditional = new List<string>();
var emulatorAdditional = new List<string>();
var gamesAdditional = new List<string>();
while (!reader.EndOfStream)
{
// If we have no next line
if (!reader.ReadNextLine())
break;
// Ignore certain row types
switch (reader.RowType)
{
case IniRowType.None:
case IniRowType.Comment:
continue;
case IniRowType.SectionHeader:
switch (reader.Section.ToLowerInvariant())
{
case "credits":
dat.Credits ??= new Credits();
break;
case "dat":
dat.Dat ??= new Dat();
break;
case "emulator":
dat.Emulator ??= new Emulator();
break;
case "games":
dat.Games ??= new Games();
break;
default:
additional.Add(reader.CurrentLine);
break;
}
continue;
}
// If we're in credits
if (reader.Section.ToLowerInvariant() == "credits")
{
// Create the section if we haven't already
dat.Credits ??= new Credits();
switch (reader.KeyValuePair?.Key?.ToLowerInvariant())
{
case "author":
dat.Credits.Author = reader.KeyValuePair?.Value;
break;
case "version":
dat.Credits.Version = reader.KeyValuePair?.Value;
break;
case "email":
dat.Credits.Email = reader.KeyValuePair?.Value;
break;
case "homepage":
dat.Credits.Homepage = reader.KeyValuePair?.Value;
break;
case "url":
dat.Credits.Url = reader.KeyValuePair?.Value;
break;
case "date":
dat.Credits.Date = reader.KeyValuePair?.Value;
break;
case "comment":
dat.Credits.Comment = reader.KeyValuePair?.Value;
break;
default:
creditsAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in dat
else if (reader.Section.ToLowerInvariant() == "dat")
{
// Create the section if we haven't already
dat.Dat ??= new Dat();
switch (reader.KeyValuePair?.Key?.ToLowerInvariant())
{
case "version":
dat.Dat.Version = reader.KeyValuePair?.Value;
break;
case "plugin":
dat.Dat.Plugin = reader.KeyValuePair?.Value;
break;
case "split":
dat.Dat.Split = reader.KeyValuePair?.Value;
break;
case "merge":
dat.Dat.Merge = reader.KeyValuePair?.Value;
break;
default:
datAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in emulator
else if (reader.Section.ToLowerInvariant() == "emulator")
{
// Create the section if we haven't already
dat.Emulator ??= new Emulator();
switch (reader.KeyValuePair?.Key?.ToLowerInvariant())
{
case "refname":
dat.Emulator.RefName = reader.KeyValuePair?.Value;
break;
case "version":
dat.Emulator.Version = reader.KeyValuePair?.Value;
break;
default:
emulatorAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in games
else if (reader.Section.ToLowerInvariant() == "games")
{
// Create the section if we haven't already
dat.Games ??= new Games();
// If the line doesn't contain the delimiter
if (!reader.CurrentLine.Contains('¬'))
{
gamesAdditional.Add(reader.CurrentLine);
continue;
}
// Otherwise, separate out the line
string[] splitLine = reader.CurrentLine.Split('¬');
var rom = new Rom
{
// EMPTY = splitLine[0]
ParentName = splitLine[1],
ParentDescription = splitLine[2],
GameName = splitLine[3],
GameDescription = splitLine[4],
RomName = splitLine[5],
RomCRC = splitLine[6],
RomSize = splitLine[7],
RomOf = splitLine[8],
MergeName = splitLine[9],
// EMPTY = splitLine[10]
};
if (splitLine.Length > 11)
rom.ADDITIONAL_ELEMENTS = splitLine.Skip(11).ToArray();
roms.Add(rom);
}
else
{
additional.Add(item: reader.CurrentLine);
}
}
// Add extra pieces and return
dat.ADDITIONAL_ELEMENTS = additional.ToArray();
if (dat.Credits != null)
dat.Credits.ADDITIONAL_ELEMENTS = creditsAdditional.ToArray();
if (dat.Dat != null)
dat.Dat.ADDITIONAL_ELEMENTS = datAdditional.ToArray();
if (dat.Emulator != null)
dat.Emulator.ADDITIONAL_ELEMENTS = emulatorAdditional.ToArray();
if (dat.Games != null)
{
dat.Games.Rom = roms.ToArray();
dat.Games.ADDITIONAL_ELEMENTS = gamesAdditional.ToArray();
}
return dat;
}
}
}

View File

@@ -20,16 +20,8 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(string path, char delim)
{
try
{
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream, delim);
}
catch
{
// TODO: Handle logging the exception
return default;
}
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream, delim);
}
/// <summary>
@@ -40,100 +32,92 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static MetadataFile? Deserialize(Stream? stream, char delim)
{
try
{
// If the stream is null
if (stream == null)
return default;
// Setup the reader and output
var reader = new SeparatedValueReader(stream, Encoding.UTF8)
{
Header = true,
Separator = delim,
VerifyFieldCount = false,
};
var dat = new MetadataFile();
// Read the header values first
if (!reader.ReadHeader())
return null;
dat.Header = reader.HeaderValues.ToArray();
// Loop through the rows and parse out values
var rows = new List<Row>();
while (!reader.EndOfStream)
{
// If we have no next line
if (!reader.ReadNextLine())
break;
// Parse the line into a row
Row? row = null;
if (reader.Line.Count < HeaderWithExtendedHashesCount)
{
row = new Row
{
FileName = reader.Line[0],
InternalName = reader.Line[1],
Description = reader.Line[2],
GameName = reader.Line[3],
GameDescription = reader.Line[4],
Type = reader.Line[5],
RomName = reader.Line[6],
DiskName = reader.Line[7],
Size = reader.Line[8],
CRC = reader.Line[9],
MD5 = reader.Line[10],
SHA1 = reader.Line[11],
SHA256 = reader.Line[12],
Status = reader.Line[13],
};
// If we have additional fields
if (reader.Line.Count > HeaderWithoutExtendedHashesCount)
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithoutExtendedHashesCount).ToArray();
}
else
{
row = new Row
{
FileName = reader.Line[0],
InternalName = reader.Line[1],
Description = reader.Line[2],
GameName = reader.Line[3],
GameDescription = reader.Line[4],
Type = reader.Line[5],
RomName = reader.Line[6],
DiskName = reader.Line[7],
Size = reader.Line[8],
CRC = reader.Line[9],
MD5 = reader.Line[10],
SHA1 = reader.Line[11],
SHA256 = reader.Line[12],
SHA384 = reader.Line[13],
SHA512 = reader.Line[14],
SpamSum = reader.Line[15],
Status = reader.Line[16],
};
// If we have additional fields
if (reader.Line.Count > HeaderWithExtendedHashesCount)
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithExtendedHashesCount).ToArray();
}
rows.Add(row);
}
// Assign the rows to the Dat and return
dat.Row = rows.ToArray();
return dat;
}
catch
{
// TODO: Handle logging the exception
// If the stream is null
if (stream == null)
return default;
// Setup the reader and output
var reader = new SeparatedValueReader(stream, Encoding.UTF8)
{
Header = true,
Separator = delim,
VerifyFieldCount = false,
};
var dat = new MetadataFile();
// Read the header values first
if (!reader.ReadHeader())
return null;
dat.Header = reader.HeaderValues.ToArray();
// Loop through the rows and parse out values
var rows = new List<Row>();
while (!reader.EndOfStream)
{
// If we have no next line
if (!reader.ReadNextLine())
break;
// Parse the line into a row
Row? row = null;
if (reader.Line.Count < HeaderWithExtendedHashesCount)
{
row = new Row
{
FileName = reader.Line[0],
InternalName = reader.Line[1],
Description = reader.Line[2],
GameName = reader.Line[3],
GameDescription = reader.Line[4],
Type = reader.Line[5],
RomName = reader.Line[6],
DiskName = reader.Line[7],
Size = reader.Line[8],
CRC = reader.Line[9],
MD5 = reader.Line[10],
SHA1 = reader.Line[11],
SHA256 = reader.Line[12],
Status = reader.Line[13],
};
// If we have additional fields
if (reader.Line.Count > HeaderWithoutExtendedHashesCount)
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithoutExtendedHashesCount).ToArray();
}
else
{
row = new Row
{
FileName = reader.Line[0],
InternalName = reader.Line[1],
Description = reader.Line[2],
GameName = reader.Line[3],
GameDescription = reader.Line[4],
Type = reader.Line[5],
RomName = reader.Line[6],
DiskName = reader.Line[7],
Size = reader.Line[8],
CRC = reader.Line[9],
MD5 = reader.Line[10],
SHA1 = reader.Line[11],
SHA256 = reader.Line[12],
SHA384 = reader.Line[13],
SHA512 = reader.Line[14],
SpamSum = reader.Line[15],
Status = reader.Line[16],
};
// If we have additional fields
if (reader.Line.Count > HeaderWithExtendedHashesCount)
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithExtendedHashesCount).ToArray();
}
rows.Add(row);
}
// Assign the rows to the Dat and return
dat.Row = rows.ToArray();
return dat;
}
}
}

View File

@@ -20,22 +20,14 @@ namespace SabreTools.Serialization
/// <returns>True on successful serialization, false otherwise</returns>
public static bool SerializeToFile(MetadataFile? metadataFile, string path, char delim)
{
try
{
using var stream = SerializeToStream(metadataFile, delim);
if (stream == null)
return false;
using var fs = File.OpenWrite(path);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fs);
return true;
}
catch
{
// TODO: Handle logging the exception
using var stream = SerializeToStream(metadataFile, delim);
if (stream == null)
return false;
}
using var fs = File.OpenWrite(path);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fs);
return true;
}
/// <summary>
@@ -46,31 +38,23 @@ namespace SabreTools.Serialization
/// <returns>Stream containing serialized data on success, null otherwise</returns>
public static Stream? SerializeToStream(MetadataFile? metadataFile, char delim)
{
try
{
// If the metadata file is null
if (metadataFile == null)
return null;
// Setup the writer and output
var stream = new MemoryStream();
var writer = new SeparatedValueWriter(stream, Encoding.UTF8) { Separator = delim, Quotes = true };
// TODO: Include flag to write out long or short header
// Write the short header
WriteHeader(writer);
// Write out the rows, if they exist
WriteRows(metadataFile.Row, writer);
// Return the stream
return stream;
}
catch
{
// TODO: Handle logging the exception
// If the metadata file is null
if (metadataFile == null)
return null;
}
// Setup the writer and output
var stream = new MemoryStream();
var writer = new SeparatedValueWriter(stream, Encoding.UTF8) { Separator = delim, Quotes = true };
// TODO: Include flag to write out long or short header
// Write the short header
WriteHeader(writer);
// Write out the rows, if they exist
WriteRows(metadataFile.Row, writer);
// Return the stream
return stream;
}
/// <summary>
@@ -79,7 +63,7 @@ namespace SabreTools.Serialization
/// <param name="writer">SeparatedValueWriter representing the output</param>
private static void WriteHeader(SeparatedValueWriter writer)
{
var headerArray = new string[]
var headerArray = new string?[]
{
"File Name",
"Internal Name",
@@ -118,7 +102,7 @@ namespace SabreTools.Serialization
// Loop through and write out the rows
foreach (var row in rows)
{
var rowArray = new string[]
var rowArray = new string?[]
{
row.FileName,
row.InternalName,

View File

@@ -16,16 +16,8 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static T? Deserialize(string path)
{
try
{
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream);
}
catch
{
// TODO: Handle logging the exception
return default;
}
using var stream = PathProcessor.OpenStream(path);
return Deserialize(stream);
}
/// <summary>
@@ -35,30 +27,22 @@ namespace SabreTools.Serialization
/// <returns>Deserialized data on success, null on failure</returns>
public static T? Deserialize(Stream? stream)
{
try
{
// If the stream is null
if (stream == null)
return default;
// Setup the serializer and the reader
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings
{
CheckCharacters = false,
DtdProcessing = DtdProcessing.Ignore,
};
var streamReader = new StreamReader(stream);
var xmlReader = XmlReader.Create(streamReader, settings);
// Perform the deserialization and return
return (T?)serializer.Deserialize(xmlReader);
}
catch
{
// TODO: Handle logging the exception
// If the stream is null
if (stream == null)
return default;
}
// Setup the serializer and the reader
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings
{
CheckCharacters = false,
DtdProcessing = DtdProcessing.Ignore,
};
var streamReader = new StreamReader(stream);
var xmlReader = XmlReader.Create(streamReader, settings);
// Perform the deserialization and return
return (T?)serializer.Deserialize(xmlReader);
}
}
}

View File

@@ -17,21 +17,13 @@ namespace SabreTools.Serialization
/// <returns>True on successful serialization, false otherwise</returns>
public static bool SerializeToFile(T? obj, string path)
{
try
{
using var stream = SerializeToStream(obj);
if (stream == null)
return false;
using var fs = File.OpenWrite(path);
stream.CopyTo(fs);
return true;
}
catch
{
// TODO: Handle logging the exception
using var stream = SerializeToStream(obj);
if (stream == null)
return false;
}
using var fs = File.OpenWrite(path);
stream.CopyTo(fs);
return true;
}
/// <summary>
@@ -41,31 +33,23 @@ namespace SabreTools.Serialization
/// <returns>Stream containing serialized data on success, null otherwise</returns>
public static Stream? SerializeToStream(T? obj)
{
try
{
// If the object is null
if (obj == null)
return null;
// Setup the serializer and the reader
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings
{
CheckCharacters = false,
};
var stream = new MemoryStream();
var streamWriter = new StreamWriter(stream);
var xmlWriter = XmlWriter.Create(streamWriter, settings);
// Perform the deserialization and return
serializer.Serialize(xmlWriter, obj);
return stream;
}
catch
{
// TODO: Handle logging the exception
// If the object is null
if (obj == null)
return null;
}
// Setup the serializer and the reader
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings
{
CheckCharacters = false,
};
var stream = new MemoryStream();
var streamWriter = new StreamWriter(stream);
var xmlWriter = XmlWriter.Create(streamWriter, settings);
// Perform the deserialization and return
serializer.Serialize(xmlWriter, obj);
return stream;
}
}
}