mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Let exceptions boil up
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user