Create and use DosCenter serializer

This commit is contained in:
Matt Nadareski
2023-07-30 15:13:16 -04:00
parent 6c8bdd99ca
commit 1ba4b18cab
7 changed files with 546 additions and 463 deletions

View File

@@ -7,16 +7,16 @@ using SabreTools.Models.DosCenter;
namespace SabreTools.Serialization
{
/// <summary>
/// Serializer for DosCenter metadata files
/// Deserializer for DosCenter metadata files
/// </summary>
public class DosCenter
public partial class DosCenter
{
/// <summary>
/// Deserializes a DosCenter metadata file to the defined type
/// </summary>
/// <param name="path">Path to the file to deserialize</param>
/// <returns>Deserialized data on success, null on failure</returns>
public static DatFile? Deserialize(string path)
public static MetadataFile? Deserialize(string path)
{
try
{
@@ -35,7 +35,7 @@ namespace SabreTools.Serialization
/// </summary>
/// <param name="stream">Stream to deserialize</param>
/// <returns>Deserialized data on success, null on failure</returns>
public static DatFile? Deserialize(Stream? stream)
public static MetadataFile? Deserialize(Stream? stream)
{
try
{
@@ -45,7 +45,7 @@ namespace SabreTools.Serialization
// Setup the reader and output
var reader = new ClrMameProReader(stream, Encoding.UTF8) { DosCenter = true };
var dat = new DatFile();
var dat = new MetadataFile();
// Loop through and parse out the values
string lastTopLevel = reader.TopLevel;
@@ -166,9 +166,6 @@ namespace SabreTools.Serialization
// If we're in a file block
else if (reader.TopLevel == "game" && reader.RowType == CmpRowType.Internal)
{
// Create the block
var file = new Models.DosCenter.File();
// If we have an unknown type, log it
if (reader.InternalName != "file")
{
@@ -176,32 +173,9 @@ namespace SabreTools.Serialization
continue;
}
foreach (var kvp in reader.Internal)
{
switch (kvp.Key?.ToLowerInvariant())
{
case "name":
file.Name = kvp.Value;
break;
case "size":
file.Size = kvp.Value;
break;
case "crc":
file.CRC = kvp.Value;
break;
case "date":
file.Date = kvp.Value;
break;
default:
fileAdditional.Add(item: reader.CurrentLine);
break;
}
}
// Add the file to the list
file.ADDITIONAL_ELEMENTS = fileAdditional.ToArray();
// Create the file and add to the list
var file = CreateFile(reader);
files.Add(file);
fileAdditional.Clear();
}
else
@@ -221,5 +195,40 @@ namespace SabreTools.Serialization
return default;
}
}
/// <summary>
/// Create a File object from the current reader context
/// </summary>
/// <param name="reader">ClrMameProReader representing the metadata file</param>
/// <returns>File object created from the reader context</returns>
private static Models.DosCenter.File CreateFile(ClrMameProReader reader)
{
var itemAdditional = new List<string>();
var file = new Models.DosCenter.File();
foreach (var kvp in reader.Internal)
{
switch (kvp.Key?.ToLowerInvariant())
{
case "name":
file.Name = kvp.Value;
break;
case "size":
file.Size = kvp.Value;
break;
case "crc":
file.CRC = kvp.Value;
break;
case "date":
file.Date = kvp.Value;
break;
default:
itemAdditional.Add(item: reader.CurrentLine);
break;
}
}
file.ADDITIONAL_ELEMENTS = itemAdditional.ToArray();
return file;
}
}
}

View File

@@ -0,0 +1,149 @@
using System.IO;
using System.Linq;
using System.Text;
using SabreTools.IO.Writers;
using SabreTools.Models.DosCenter;
namespace SabreTools.Serialization
{
/// <summary>
/// Deserializer for DosCenter metadata files
/// </summary>
public partial class DosCenter
{
/// <summary>
/// Serializes the defined type to a DosCenter metadata file
/// </summary>
/// <param name="metadataFile">Data to serialize</param>
/// <param name="path">Path to the file to serialize to</param>
/// <returns>True on successful serialization, false otherwise</returns>
public static bool SerializeToFile(MetadataFile? metadataFile, string path)
{
using var stream = SerializeToStream(metadataFile);
if (stream == null)
return false;
using var fs = System.IO.File.OpenWrite(path);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fs);
return true;
}
/// <summary>
/// Serializes the defined type to a stream
/// </summary>
/// <param name="metadataFile">Data to serialize</param>
/// <returns>Stream containing serialized data on success, null otherwise</returns>
public static Stream? SerializeToStream(MetadataFile? metadataFile)
{
// 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 = false,
};
// Write the header, if it exists
WriteHeader(metadataFile.DosCenter, writer);
// Write out the games, if they exist
WriteGames(metadataFile.Game, writer);
// Return the stream
return stream;
}
/// <summary>
/// Write header information to the current writer
/// </summary>
/// <param name="header">DosCenter representing the header information</param>
/// <param name="writer">ClrMameProWriter representing the output</param>
private static void WriteHeader(Models.DosCenter.DosCenter? header, ClrMameProWriter writer)
{
// If the header information is missing, we can't do anything
if (header == null)
return;
writer.WriteStartElement("DOSCenter");
writer.WriteOptionalStandalone("Name:", header.Name);
writer.WriteOptionalStandalone("Description:", header.Description);
writer.WriteOptionalStandalone("Version:", header.Version);
writer.WriteOptionalStandalone("Date:", header.Date);
writer.WriteOptionalStandalone("Author:", header.Author);
writer.WriteOptionalStandalone("Homepage:", header.Homepage);
writer.WriteOptionalStandalone("Comment:", header.Comment);
writer.WriteEndElement(); // doscenter
writer.Flush();
}
/// <summary>
/// Write games information to the current writer
/// </summary>
/// <param name="games">Array of Game objects representing the games information</param>
/// <param name="writer">ClrMameProWriter representing the output</param>
private static void WriteGames(Game[]? games, ClrMameProWriter writer)
{
// If the games information is missing, we can't do anything
if (games == null || !games.Any())
return;
// Loop through and write out the games
foreach (var game in games)
{
WriteGame(game, writer);
writer.Flush();
}
}
/// <summary>
/// Write game information to the current writer
/// </summary>
/// <param name="game">Game object representing the game information</param>
/// <param name="writer">ClrMameProWriter representing the output</param>
private static void WriteGame(Game game, ClrMameProWriter writer)
{
// If the game information is missing, we can't do anything
if (game == null)
return;
writer.WriteStartElement("game");
// Write the standalone values
writer.WriteRequiredStandalone("name", game.Name, throwOnError: true);
// Write the item values
WriteFiles(game.File, writer);
writer.WriteEndElement(); // game
}
/// <summary>
/// Write files information to the current writer
/// </summary>
/// <param name="files">Array of File objects to write</param>
/// <param name="writer">ClrMameProWriter representing the output</param>
private static void WriteFiles(Models.DosCenter.File[]? files, ClrMameProWriter writer)
{
// If the array is missing, we can't do anything
if (files == null)
return;
foreach (var file in files)
{
writer.WriteStartElement("file");
writer.WriteRequiredAttributeString("name", file.Name, throwOnError: true);
writer.WriteRequiredAttributeString("size", file.Size, throwOnError: true);
writer.WriteOptionalAttributeString("date", file.Date);
writer.WriteRequiredAttributeString("crc", file.CRC.ToUpperInvariant(), throwOnError: true);
writer.WriteEndElement(); // file
}
}
}
}