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
|
public class Row
|
||||||
{
|
{
|
||||||
/// <remarks>File Name</remarks>
|
/// <remarks>File Name</remarks>
|
||||||
public string FileName { get; set; }
|
public string? FileName { get; set; }
|
||||||
|
|
||||||
/// <remarks>Internal Name</remarks>
|
/// <remarks>Internal Name</remarks>
|
||||||
public string InternalName { get; set; }
|
public string? InternalName { get; set; }
|
||||||
|
|
||||||
/// <remarks>Description</remarks>
|
/// <remarks>Description</remarks>
|
||||||
public string Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
/// <remarks>Game Name</remarks>
|
/// <remarks>Game Name</remarks>
|
||||||
public string GameName { get; set; }
|
public string GameName { get; set; }
|
||||||
|
|
||||||
/// <remarks>Game Description</remarks>
|
/// <remarks>Game Description</remarks>
|
||||||
public string GameDescription { get; set; }
|
public string? GameDescription { get; set; }
|
||||||
|
|
||||||
/// <remarks>Type</remarks>
|
/// <remarks>Type</remarks>
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
|
|
||||||
/// <remarks>Rom Name</remarks>
|
/// <remarks>Rom Name</remarks>
|
||||||
public string RomName { get; set; }
|
public string? RomName { get; set; }
|
||||||
|
|
||||||
/// <remarks>Disk Name</remarks>
|
/// <remarks>Disk Name</remarks>
|
||||||
public string DiskName { get; set; }
|
public string? DiskName { get; set; }
|
||||||
|
|
||||||
/// <remarks>Size, Numeric</remarks>
|
/// <remarks>Size, Numeric</remarks>
|
||||||
public string Size { get; set; }
|
public string? Size { get; set; }
|
||||||
|
|
||||||
/// <remarks>CRC</remarks>
|
/// <remarks>CRC</remarks>
|
||||||
public string CRC { get; set; }
|
public string? CRC { get; set; }
|
||||||
|
|
||||||
/// <remarks>MD5</remarks>
|
/// <remarks>MD5</remarks>
|
||||||
public string MD5 { get; set; }
|
public string? MD5 { get; set; }
|
||||||
|
|
||||||
/// <remarks>SHA1</remarks>
|
/// <remarks>SHA1</remarks>
|
||||||
public string SHA1 { get; set; }
|
public string? SHA1 { get; set; }
|
||||||
|
|
||||||
/// <remarks>SHA256</remarks>
|
/// <remarks>SHA256</remarks>
|
||||||
public string SHA256 { get; set; }
|
public string? SHA256 { get; set; }
|
||||||
|
|
||||||
/// <remarks>SHA384, Optional</remarks>
|
/// <remarks>SHA384, Optional</remarks>
|
||||||
public string SHA384 { get; set; }
|
public string? SHA384 { get; set; }
|
||||||
|
|
||||||
/// <remarks>SHA512, Optional</remarks>
|
/// <remarks>SHA512, Optional</remarks>
|
||||||
public string SHA512 { get; set; }
|
public string? SHA512 { get; set; }
|
||||||
|
|
||||||
/// <remarks>SpamSum, Optional</remarks>
|
/// <remarks>SpamSum, Optional</remarks>
|
||||||
public string SpamSum { get; set; }
|
public string? SpamSum { get; set; }
|
||||||
|
|
||||||
/// <remarks>Status, Nodump</remarks>
|
/// <remarks>Status, Nodump</remarks>
|
||||||
public string Status { get; set; }
|
public string? Status { get; set; }
|
||||||
|
|
||||||
#region DO NOT USE IN PRODUCTION
|
#region DO NOT USE IN PRODUCTION
|
||||||
|
|
||||||
|
|||||||
@@ -19,16 +19,8 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static MetadataFile? Deserialize(string path)
|
public static MetadataFile? Deserialize(string path)
|
||||||
{
|
{
|
||||||
try
|
using var stream = PathProcessor.OpenStream(path);
|
||||||
{
|
return Deserialize(stream);
|
||||||
using var stream = PathProcessor.OpenStream(path);
|
|
||||||
return Deserialize(stream);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// TODO: Handle logging the exception
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -38,103 +30,95 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static MetadataFile? Deserialize(Stream? stream)
|
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
|
Separator = ';',
|
||||||
if (stream == null)
|
VerifyFieldCount = false,
|
||||||
return default;
|
};
|
||||||
|
var dat = new MetadataFile();
|
||||||
|
|
||||||
// Setup the reader and output
|
// Read the header values first
|
||||||
var reader = new SeparatedValueReader(stream, Encoding.UTF8)
|
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 = ';',
|
row = new Row
|
||||||
VerifyFieldCount = false,
|
{
|
||||||
};
|
Name = reader.Line[0],
|
||||||
var dat = new MetadataFile();
|
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 we have additional fields
|
||||||
if (!reader.ReadHeader())
|
if (reader.Line.Count > HeaderWithoutRomnameCount)
|
||||||
return null;
|
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithoutRomnameCount).ToArray();
|
||||||
|
}
|
||||||
dat.Header = reader.HeaderValues.ToArray();
|
else
|
||||||
|
|
||||||
// Loop through the rows and parse out values
|
|
||||||
var rows = new List<Row>();
|
|
||||||
while (!reader.EndOfStream)
|
|
||||||
{
|
{
|
||||||
// If we have no next line
|
row = new Row
|
||||||
if (!reader.ReadNextLine())
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Parse the line into a row
|
|
||||||
Row? row = null;
|
|
||||||
if (reader.Line.Count < HeaderWithRomnameCount)
|
|
||||||
{
|
{
|
||||||
row = new Row
|
Name = reader.Line[0],
|
||||||
{
|
Title = reader.Line[1],
|
||||||
Name = reader.Line[0],
|
Emulator = reader.Line[2],
|
||||||
Title = reader.Line[1],
|
CloneOf = reader.Line[3],
|
||||||
Emulator = reader.Line[2],
|
Year = reader.Line[4],
|
||||||
CloneOf = reader.Line[3],
|
Manufacturer = reader.Line[5],
|
||||||
Year = reader.Line[4],
|
Category = reader.Line[6],
|
||||||
Manufacturer = reader.Line[5],
|
Players = reader.Line[7],
|
||||||
Category = reader.Line[6],
|
Rotation = reader.Line[8],
|
||||||
Players = reader.Line[7],
|
Control = reader.Line[9],
|
||||||
Rotation = reader.Line[8],
|
Status = reader.Line[10],
|
||||||
Control = reader.Line[9],
|
DisplayCount = reader.Line[11],
|
||||||
Status = reader.Line[10],
|
DisplayType = reader.Line[12],
|
||||||
DisplayCount = reader.Line[11],
|
AltRomname = reader.Line[13],
|
||||||
DisplayType = reader.Line[12],
|
AltTitle = reader.Line[14],
|
||||||
AltRomname = reader.Line[13],
|
Extra = reader.Line[15],
|
||||||
AltTitle = reader.Line[14],
|
Buttons = reader.Line[16],
|
||||||
Extra = reader.Line[15],
|
};
|
||||||
Buttons = reader.Line[16],
|
|
||||||
};
|
|
||||||
|
|
||||||
// If we have additional fields
|
// If we have additional fields
|
||||||
if (reader.Line.Count > HeaderWithoutRomnameCount)
|
if (reader.Line.Count > HeaderWithRomnameCount)
|
||||||
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithoutRomnameCount).ToArray();
|
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithRomnameCount).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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign the rows to the Dat and return
|
rows.Add(row);
|
||||||
dat.Row = rows.ToArray();
|
|
||||||
return dat;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// TODO: Handle logging the exception
|
|
||||||
return default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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>
|
/// <returns>True on successful serialization, false otherwise</returns>
|
||||||
public static bool SerializeToFile(MetadataFile? metadataFile, string path)
|
public static bool SerializeToFile(MetadataFile? metadataFile, string path)
|
||||||
{
|
{
|
||||||
try
|
using var stream = SerializeToStream(metadataFile);
|
||||||
{
|
if (stream == null)
|
||||||
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
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
using var fs = File.OpenWrite(path);
|
||||||
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
stream.CopyTo(fs);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -44,31 +36,28 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Stream containing serialized data on success, null otherwise</returns>
|
/// <returns>Stream containing serialized data on success, null otherwise</returns>
|
||||||
public static Stream? SerializeToStream(MetadataFile? metadataFile)
|
public static Stream? SerializeToStream(MetadataFile? metadataFile)
|
||||||
{
|
{
|
||||||
try
|
// If the metadata file is null
|
||||||
{
|
if (metadataFile == null)
|
||||||
// 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
|
|
||||||
return 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>
|
/// <summary>
|
||||||
@@ -85,7 +74,7 @@ namespace SabreTools.Serialization
|
|||||||
// Loop through and write out the rows
|
// Loop through and write out the rows
|
||||||
foreach (var row in rows)
|
foreach (var row in rows)
|
||||||
{
|
{
|
||||||
var rowArray = new string[]
|
var rowArray = new string?[]
|
||||||
{
|
{
|
||||||
row.Name,
|
row.Name,
|
||||||
row.Title,
|
row.Title,
|
||||||
|
|||||||
@@ -19,16 +19,8 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static MetadataFile? Deserialize(string path, bool quotes)
|
public static MetadataFile? Deserialize(string path, bool quotes)
|
||||||
{
|
{
|
||||||
try
|
using var stream = PathProcessor.OpenStream(path);
|
||||||
{
|
return Deserialize(stream, quotes);
|
||||||
using var stream = PathProcessor.OpenStream(path);
|
|
||||||
return Deserialize(stream, quotes);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// TODO: Handle logging the exception
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -39,305 +31,297 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static MetadataFile? Deserialize(Stream? stream, bool quotes)
|
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 we have no next line
|
||||||
if (stream == null)
|
if (!reader.ReadNextLine())
|
||||||
return default;
|
break;
|
||||||
|
|
||||||
// Setup the reader and output
|
// Ignore certain row types
|
||||||
var reader = new ClrMameProReader(stream, Encoding.UTF8) { Quotes = quotes };
|
switch (reader.RowType)
|
||||||
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 we have no next line
|
case CmpRowType.None:
|
||||||
if (!reader.ReadNextLine())
|
case CmpRowType.Comment:
|
||||||
break;
|
continue;
|
||||||
|
case CmpRowType.EndTopLevel:
|
||||||
// Ignore certain row types
|
switch (lastTopLevel)
|
||||||
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 "clrmamepro":
|
case "doscenter":
|
||||||
dat.ClrMamePro = new Models.ClrMamePro.ClrMamePro();
|
dat.ClrMamePro!.ADDITIONAL_ELEMENTS = headerAdditional.ToArray();
|
||||||
|
headerAdditional.Clear();
|
||||||
break;
|
break;
|
||||||
case "game":
|
case "game":
|
||||||
game = new Game();
|
|
||||||
break;
|
|
||||||
case "machine":
|
case "machine":
|
||||||
game = new Machine();
|
|
||||||
break;
|
|
||||||
case "resource":
|
case "resource":
|
||||||
game = new Resource();
|
|
||||||
break;
|
|
||||||
case "set":
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
additional.Add(reader.CurrentLine);
|
// No-op
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// If we're in the doscenter block
|
// If we're at the root
|
||||||
else if (reader.TopLevel == "clrmamepro"
|
if (reader.RowType == CmpRowType.TopLevel)
|
||||||
&& reader.RowType == CmpRowType.Standalone)
|
{
|
||||||
|
lastTopLevel = reader.TopLevel;
|
||||||
|
switch (reader.TopLevel)
|
||||||
{
|
{
|
||||||
// Create the block if we haven't already
|
case "clrmamepro":
|
||||||
dat.ClrMamePro ??= new Models.ClrMamePro.ClrMamePro();
|
dat.ClrMamePro = new Models.ClrMamePro.ClrMamePro();
|
||||||
|
break;
|
||||||
switch (reader.Standalone?.Key?.ToLowerInvariant())
|
case "game":
|
||||||
{
|
game = new Game();
|
||||||
case "name":
|
break;
|
||||||
dat.ClrMamePro.Name = reader.Standalone?.Value;
|
case "machine":
|
||||||
break;
|
game = new Machine();
|
||||||
case "description":
|
break;
|
||||||
dat.ClrMamePro.Description = reader.Standalone?.Value;
|
case "resource":
|
||||||
break;
|
game = new Resource();
|
||||||
case "rootdir":
|
break;
|
||||||
dat.ClrMamePro.RootDir = reader.Standalone?.Value;
|
case "set":
|
||||||
break;
|
game = new Set();
|
||||||
case "category":
|
break;
|
||||||
dat.ClrMamePro.Category = reader.Standalone?.Value;
|
default:
|
||||||
break;
|
additional.Add(reader.CurrentLine);
|
||||||
case "version":
|
break;
|
||||||
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
|
// If we're in the doscenter block
|
||||||
dat.Game = games.ToArray();
|
else if (reader.TopLevel == "clrmamepro"
|
||||||
dat.ADDITIONAL_ELEMENTS = additional.ToArray();
|
&& reader.RowType == CmpRowType.Standalone)
|
||||||
return dat;
|
{
|
||||||
}
|
// Create the block if we haven't already
|
||||||
catch
|
dat.ClrMamePro ??= new Models.ClrMamePro.ClrMamePro();
|
||||||
{
|
|
||||||
// TODO: Handle logging the exception
|
switch (reader.Standalone?.Key?.ToLowerInvariant())
|
||||||
return default;
|
{
|
||||||
|
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>
|
/// <summary>
|
||||||
|
|||||||
@@ -20,22 +20,14 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>True on successful serialization, false otherwise</returns>
|
/// <returns>True on successful serialization, false otherwise</returns>
|
||||||
public static bool SerializeToFile(MetadataFile? metadataFile, string path, bool quotes)
|
public static bool SerializeToFile(MetadataFile? metadataFile, string path, bool quotes)
|
||||||
{
|
{
|
||||||
try
|
using var stream = SerializeToStream(metadataFile, quotes);
|
||||||
{
|
if (stream == null)
|
||||||
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
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
using var fs = File.OpenWrite(path);
|
||||||
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
stream.CopyTo(fs);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -46,30 +38,22 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Stream containing serialized data on success, null otherwise</returns>
|
/// <returns>Stream containing serialized data on success, null otherwise</returns>
|
||||||
public static Stream? SerializeToStream(MetadataFile? metadataFile, bool quotes)
|
public static Stream? SerializeToStream(MetadataFile? metadataFile, bool quotes)
|
||||||
{
|
{
|
||||||
try
|
// If the metadata file is null
|
||||||
{
|
if (metadataFile == null)
|
||||||
// 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
|
|
||||||
return 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>
|
/// <summary>
|
||||||
|
|||||||
@@ -19,16 +19,8 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static MetadataFile? Deserialize(string path)
|
public static MetadataFile? Deserialize(string path)
|
||||||
{
|
{
|
||||||
try
|
using var stream = PathProcessor.OpenStream(path);
|
||||||
{
|
return Deserialize(stream);
|
||||||
using var stream = PathProcessor.OpenStream(path);
|
|
||||||
return Deserialize(stream);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// TODO: Handle logging the exception
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -38,59 +30,51 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static MetadataFile? Deserialize(Stream? stream)
|
public static MetadataFile? Deserialize(Stream? stream)
|
||||||
{
|
{
|
||||||
try
|
// If the stream is null
|
||||||
{
|
if (stream == null)
|
||||||
// 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
|
|
||||||
return default;
|
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>
|
/// <returns>True on successful serialization, false otherwise</returns>
|
||||||
public static bool SerializeToFile(MetadataFile? metadataFile, string path)
|
public static bool SerializeToFile(MetadataFile? metadataFile, string path)
|
||||||
{
|
{
|
||||||
try
|
using var stream = SerializeToStream(metadataFile);
|
||||||
{
|
if (stream == null)
|
||||||
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
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
using var fs = File.OpenWrite(path);
|
||||||
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
stream.CopyTo(fs);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -45,27 +37,19 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Stream containing serialized data on success, null otherwise</returns>
|
/// <returns>Stream containing serialized data on success, null otherwise</returns>
|
||||||
public static Stream? SerializeToStream(MetadataFile? metadataFile)
|
public static Stream? SerializeToStream(MetadataFile? metadataFile)
|
||||||
{
|
{
|
||||||
try
|
// If the metadata file is null
|
||||||
{
|
if (metadataFile == null)
|
||||||
// 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
|
|
||||||
return 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>
|
/// <summary>
|
||||||
|
|||||||
@@ -19,16 +19,8 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static Models.Hashfile.Hashfile? Deserialize(string path, Hash hash)
|
public static Models.Hashfile.Hashfile? Deserialize(string path, Hash hash)
|
||||||
{
|
{
|
||||||
try
|
using var stream = PathProcessor.OpenStream(path);
|
||||||
{
|
return Deserialize(stream, hash);
|
||||||
using var stream = PathProcessor.OpenStream(path);
|
|
||||||
return Deserialize(stream, hash);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// TODO: Handle logging the exception
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -39,122 +31,114 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static Models.Hashfile.Hashfile? Deserialize(Stream? stream, Hash hash)
|
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
|
// Read and split the line
|
||||||
if (stream == null)
|
string? line = reader.ReadLine();
|
||||||
return default;
|
string[]? lineParts = line?.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||||
|
if (lineParts == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
// Setup the reader and output
|
// Parse the line into a hash
|
||||||
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
|
|
||||||
switch (hash)
|
switch (hash)
|
||||||
{
|
{
|
||||||
case Hash.CRC:
|
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;
|
break;
|
||||||
case Hash.MD5:
|
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;
|
break;
|
||||||
case Hash.SHA1:
|
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;
|
break;
|
||||||
case Hash.SHA256:
|
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;
|
break;
|
||||||
case Hash.SHA384:
|
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;
|
break;
|
||||||
case Hash.SHA512:
|
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;
|
break;
|
||||||
case Hash.SpamSum:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
dat.ADDITIONAL_ELEMENTS = additional.ToArray();
|
|
||||||
return dat;
|
|
||||||
}
|
}
|
||||||
catch
|
|
||||||
|
// Assign the hashes to the hashfile and return
|
||||||
|
switch (hash)
|
||||||
{
|
{
|
||||||
// TODO: Handle logging the exception
|
case Hash.CRC:
|
||||||
return default;
|
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>
|
/// <returns>True on successful serialization, false otherwise</returns>
|
||||||
public static bool SerializeToFile(Models.Hashfile.Hashfile? hashfile, string path, Hash hash)
|
public static bool SerializeToFile(Models.Hashfile.Hashfile? hashfile, string path, Hash hash)
|
||||||
{
|
{
|
||||||
try
|
using var stream = SerializeToStream(hashfile, hash);
|
||||||
{
|
if (stream == null)
|
||||||
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
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
using var fs = File.OpenWrite(path);
|
||||||
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
stream.CopyTo(fs);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -48,52 +40,49 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Stream containing serialized data on success, null otherwise</returns>
|
/// <returns>Stream containing serialized data on success, null otherwise</returns>
|
||||||
public static Stream? SerializeToStream(Models.Hashfile.Hashfile? hashfile, Hash hash)
|
public static Stream? SerializeToStream(Models.Hashfile.Hashfile? hashfile, Hash hash)
|
||||||
{
|
{
|
||||||
try
|
// If the metadata file is null
|
||||||
{
|
if (hashfile == null)
|
||||||
// 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
|
|
||||||
return 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>
|
/// <summary>
|
||||||
|
|||||||
@@ -18,16 +18,8 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static MetadataFile? Deserialize(string path)
|
public static MetadataFile? Deserialize(string path)
|
||||||
{
|
{
|
||||||
try
|
using var stream = PathProcessor.OpenStream(path);
|
||||||
{
|
return Deserialize(stream);
|
||||||
using var stream = PathProcessor.OpenStream(path);
|
|
||||||
return Deserialize(stream);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// TODO: Handle logging the exception
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -37,161 +29,153 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static MetadataFile? Deserialize(Stream? stream)
|
public static MetadataFile? Deserialize(Stream? stream)
|
||||||
{
|
{
|
||||||
try
|
// If the stream is null
|
||||||
{
|
if (stream == null)
|
||||||
// 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
|
|
||||||
return default;
|
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>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static MetadataFile? Deserialize(string path)
|
public static MetadataFile? Deserialize(string path)
|
||||||
{
|
{
|
||||||
try
|
using var stream = PathProcessor.OpenStream(path);
|
||||||
{
|
return Deserialize(stream);
|
||||||
using var stream = PathProcessor.OpenStream(path);
|
|
||||||
return Deserialize(stream);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// TODO: Handle logging the exception
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -38,203 +30,195 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static MetadataFile? Deserialize(Stream? stream)
|
public static MetadataFile? Deserialize(Stream? stream)
|
||||||
{
|
{
|
||||||
try
|
// If the stream is null
|
||||||
{
|
if (stream == null)
|
||||||
// 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
|
|
||||||
return default;
|
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>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static MetadataFile? Deserialize(string path, char delim)
|
public static MetadataFile? Deserialize(string path, char delim)
|
||||||
{
|
{
|
||||||
try
|
using var stream = PathProcessor.OpenStream(path);
|
||||||
{
|
return Deserialize(stream, delim);
|
||||||
using var stream = PathProcessor.OpenStream(path);
|
|
||||||
return Deserialize(stream, delim);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// TODO: Handle logging the exception
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -40,100 +32,92 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static MetadataFile? Deserialize(Stream? stream, char delim)
|
public static MetadataFile? Deserialize(Stream? stream, char delim)
|
||||||
{
|
{
|
||||||
try
|
// If the stream is null
|
||||||
{
|
if (stream == null)
|
||||||
// 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
|
|
||||||
return default;
|
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>
|
/// <returns>True on successful serialization, false otherwise</returns>
|
||||||
public static bool SerializeToFile(MetadataFile? metadataFile, string path, char delim)
|
public static bool SerializeToFile(MetadataFile? metadataFile, string path, char delim)
|
||||||
{
|
{
|
||||||
try
|
using var stream = SerializeToStream(metadataFile, delim);
|
||||||
{
|
if (stream == null)
|
||||||
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
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
using var fs = File.OpenWrite(path);
|
||||||
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
stream.CopyTo(fs);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -46,31 +38,23 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Stream containing serialized data on success, null otherwise</returns>
|
/// <returns>Stream containing serialized data on success, null otherwise</returns>
|
||||||
public static Stream? SerializeToStream(MetadataFile? metadataFile, char delim)
|
public static Stream? SerializeToStream(MetadataFile? metadataFile, char delim)
|
||||||
{
|
{
|
||||||
try
|
// If the metadata file is null
|
||||||
{
|
if (metadataFile == null)
|
||||||
// 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
|
|
||||||
return 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>
|
/// <summary>
|
||||||
@@ -79,7 +63,7 @@ namespace SabreTools.Serialization
|
|||||||
/// <param name="writer">SeparatedValueWriter representing the output</param>
|
/// <param name="writer">SeparatedValueWriter representing the output</param>
|
||||||
private static void WriteHeader(SeparatedValueWriter writer)
|
private static void WriteHeader(SeparatedValueWriter writer)
|
||||||
{
|
{
|
||||||
var headerArray = new string[]
|
var headerArray = new string?[]
|
||||||
{
|
{
|
||||||
"File Name",
|
"File Name",
|
||||||
"Internal Name",
|
"Internal Name",
|
||||||
@@ -118,7 +102,7 @@ namespace SabreTools.Serialization
|
|||||||
// Loop through and write out the rows
|
// Loop through and write out the rows
|
||||||
foreach (var row in rows)
|
foreach (var row in rows)
|
||||||
{
|
{
|
||||||
var rowArray = new string[]
|
var rowArray = new string?[]
|
||||||
{
|
{
|
||||||
row.FileName,
|
row.FileName,
|
||||||
row.InternalName,
|
row.InternalName,
|
||||||
|
|||||||
@@ -16,16 +16,8 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static T? Deserialize(string path)
|
public static T? Deserialize(string path)
|
||||||
{
|
{
|
||||||
try
|
using var stream = PathProcessor.OpenStream(path);
|
||||||
{
|
return Deserialize(stream);
|
||||||
using var stream = PathProcessor.OpenStream(path);
|
|
||||||
return Deserialize(stream);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// TODO: Handle logging the exception
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -35,30 +27,22 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Deserialized data on success, null on failure</returns>
|
/// <returns>Deserialized data on success, null on failure</returns>
|
||||||
public static T? Deserialize(Stream? stream)
|
public static T? Deserialize(Stream? stream)
|
||||||
{
|
{
|
||||||
try
|
// If the stream is null
|
||||||
{
|
if (stream == null)
|
||||||
// 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
|
|
||||||
return default;
|
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>
|
/// <returns>True on successful serialization, false otherwise</returns>
|
||||||
public static bool SerializeToFile(T? obj, string path)
|
public static bool SerializeToFile(T? obj, string path)
|
||||||
{
|
{
|
||||||
try
|
using var stream = SerializeToStream(obj);
|
||||||
{
|
if (stream == null)
|
||||||
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
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
using var fs = File.OpenWrite(path);
|
||||||
|
stream.CopyTo(fs);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -41,31 +33,23 @@ namespace SabreTools.Serialization
|
|||||||
/// <returns>Stream containing serialized data on success, null otherwise</returns>
|
/// <returns>Stream containing serialized data on success, null otherwise</returns>
|
||||||
public static Stream? SerializeToStream(T? obj)
|
public static Stream? SerializeToStream(T? obj)
|
||||||
{
|
{
|
||||||
try
|
// If the object is null
|
||||||
{
|
if (obj == null)
|
||||||
// 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
|
|
||||||
return 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