Use XmlTextReader for XML DAT reading

This commit is contained in:
Matt Nadareski
2026-03-31 00:01:44 -04:00
parent ea2bfbcb1f
commit 0670231606
12 changed files with 6667 additions and 67 deletions

View File

@@ -78,7 +78,7 @@ namespace SabreTools.Data.Models.Logiqx
[XmlElement("trurip")]
public Trurip? Trurip { get; set; }
[XmlElement(elementName: "release")]
[XmlElement("release")]
public Release[]? Release { get; set; }
[XmlElement("biosset")]

View File

@@ -90,7 +90,7 @@ namespace SabreTools.Serialization.Readers.Test
Assert.NotNull(newDf);
Assert.Equal("XXXXXX", newDf.Build);
Assert.Equal("XXXXXX", newDf.Debug);
Assert.Equal("XXXXXX", newDf.SchemaLocation);
// Assert.Equal("XXXXXX", newDf.SchemaLocation); // TODO: Fix this based on No-Intro DATs
Validate(newDf.Header);
Assert.NotNull(newDf.Game);
@@ -122,7 +122,7 @@ namespace SabreTools.Serialization.Readers.Test
Assert.NotNull(newDf);
Assert.Equal("XXXXXX", newDf.Build);
Assert.Equal("XXXXXX", newDf.Debug);
Assert.Equal("XXXXXX", newDf.SchemaLocation);
// Assert.Equal("XXXXXX", newDf.SchemaLocation); // TODO: Fix this based on No-Intro DATs
Validate(newDf.Header);
Assert.NotNull(newDf.Game);

View File

@@ -88,7 +88,7 @@ namespace SabreTools.Serialization.Readers.Test
// Validate the data
Assert.NotNull(newDat);
Assert.Equal("XXXXXX", newDat.NoNamespaceSchemaLocation);
// Assert.Equal("XXXXXX", newDat.NoNamespaceSchemaLocation); // TODO: Fix this based on schema
Validate(newDat.Configuration);
Validate(newDat.Games);
Validate(newDat.GUI);

View File

@@ -1,9 +1,311 @@
using System;
using System.Collections.Generic;
using System.Xml;
using SabreTools.Data.Models.ArchiveDotOrg;
namespace SabreTools.Serialization.Readers
{
public class ArchiveDotOrg : XmlFile<Files>
public class ArchiveDotOrg : BaseBinaryReader<Files>
{
// All logic taken care of in the base class
/// <inheritdoc/>
public override Files? Deserialize(System.IO.Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
try
{
// Cache the current offset
long initialOffset = data.Position;
// Create the XmlTextReader
var reader = new XmlTextReader(data);
reader.WhitespaceHandling = WhitespaceHandling.None;
// Parse the XML, if possible
Files? files = null;
while (reader.Read())
{
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "files":
if (files is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
files = ParseFiles(reader);
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
break;
}
}
return files;
}
catch
{
// Ignore the actual error
return null;
}
}
/// <summary>
/// Parse from an XmlTextReader into a Files
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Files on success, null on error</returns>
public Files ParseFiles(XmlTextReader reader)
{
var obj = new Files();
List<File> files = [];
while (reader.Read())
{
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "file":
var file = ParseFile(reader);
if (file is not null)
files.Add(file);
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
obj.File = [.. files];
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a File
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled File on success, null on error</returns>
public File ParseFile(XmlTextReader reader)
{
var obj = new File();
obj.Name = reader.GetAttribute("name");
obj.Source = reader.GetAttribute("source");
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "btih":
obj.BitTorrentMagnetHash = reader.ReadElementContentAsString();
break;
case "mtime":
obj.LastModifiedTime = reader.ReadElementContentAsString();
break;
case "size":
obj.Size = reader.ReadElementContentAsString();
break;
case "md5":
obj.MD5 = reader.ReadElementContentAsString();
break;
case "crc32":
obj.CRC32 = reader.ReadElementContentAsString();
break;
case "sha1":
obj.SHA1 = reader.ReadElementContentAsString();
break;
case "filecount":
obj.FileCount = reader.ReadElementContentAsString();
break;
case "format":
obj.Format = reader.ReadElementContentAsString();
break;
case "original":
obj.Original = reader.ReadElementContentAsString();
break;
case "summation":
obj.Summation = reader.ReadElementContentAsString();
break;
case "matrix_number":
obj.MatrixNumber = reader.ReadElementContentAsString();
break;
case "collection-catalog-number":
obj.CollectionCatalogNumber = reader.ReadElementContentAsString();
break;
case "publisher":
obj.Publisher = reader.ReadElementContentAsString();
break;
case "comment":
obj.Comment = reader.ReadElementContentAsString();
break;
// ASR-Related
case "asr_detected_lang":
obj.ASRDetectedLang = reader.ReadElementContentAsString();
break;
case "asr_detected_lang_conf":
obj.ASRDetectedLangConf = reader.ReadElementContentAsString();
break;
case "asr_transcribed_lang":
obj.ASRTranscribedLang = reader.ReadElementContentAsString();
break;
case "whisper_asr_module_version":
obj.WhisperASRModuleVersion = reader.ReadElementContentAsString();
break;
case "whisper_model_hash":
obj.WhisperModelHash = reader.ReadElementContentAsString();
break;
case "whisper_model_name":
obj.WhisperModelName = reader.ReadElementContentAsString();
break;
case "whisper_version":
obj.WhisperVersion = reader.ReadElementContentAsString();
break;
// OCR-Related
case "cloth_cover_detection_module_version":
obj.ClothCoverDetectionModuleVersion = reader.ReadElementContentAsString();
break;
case "hocr_char_to_word_hocr_version":
obj.hOCRCharToWordhOCRVersion = reader.ReadElementContentAsString();
break;
case "hocr_char_to_word_module_version":
obj.hOCRCharToWordModuleVersion = reader.ReadElementContentAsString();
break;
case "hocr_fts_text_hocr_version":
obj.hOCRFtsTexthOCRVersion = reader.ReadElementContentAsString();
break;
case "hocr_fts_text_module_version":
obj.hOCRFtsTextModuleVersion = reader.ReadElementContentAsString();
break;
case "hocr_pageindex_hocr_version":
obj.hOCRPageIndexhOCRVersion = reader.ReadElementContentAsString();
break;
case "hocr_pageindex_module_version":
obj.hOCRPageIndexModuleVersion = reader.ReadElementContentAsString();
break;
case "ocr":
obj.TesseractOCR = reader.ReadElementContentAsString();
break;
case "ocr_converted":
obj.TesseractOCRConverted = reader.ReadElementContentAsString();
break;
case "ocr_detected_lang":
obj.TesseractOCRDetectedLang = reader.ReadElementContentAsString();
break;
case "ocr_detected_lang_conf":
obj.TesseractOCRDetectedLangConf = reader.ReadElementContentAsString();
break;
case "ocr_detected_script":
obj.TesseractOCRDetectedScript = reader.ReadElementContentAsString();
break;
case "ocr_detected_script_conf":
obj.TesseractOCRDetectedScriptConf = reader.ReadElementContentAsString();
break;
case "ocr_module_version":
obj.TesseractOCRModuleVersion = reader.ReadElementContentAsString();
break;
case "ocr_parameters":
obj.TesseractOCRParameters = reader.ReadElementContentAsString();
break;
case "pdf_module_version":
obj.PDFModuleVersion = reader.ReadElementContentAsString();
break;
case "word_conf_0_10":
obj.WordConfidenceInterval0To10 = reader.ReadElementContentAsString();
break;
case "word_conf_11_20":
obj.WordConfidenceInterval11To20 = reader.ReadElementContentAsString();
break;
case "word_conf_21_30":
obj.WordConfidenceInterval21To30 = reader.ReadElementContentAsString();
break;
case "word_conf_31_40":
obj.WordConfidenceInterval31To40 = reader.ReadElementContentAsString();
break;
case "word_conf_41_50":
obj.WordConfidenceInterval41To50 = reader.ReadElementContentAsString();
break;
case "word_conf_51_60":
obj.WordConfidenceInterval51To60 = reader.ReadElementContentAsString();
break;
case "word_conf_61_70":
obj.WordConfidenceInterval61To70 = reader.ReadElementContentAsString();
break;
case "word_conf_71_80":
obj.WordConfidenceInterval71To80 = reader.ReadElementContentAsString();
break;
case "word_conf_81_90":
obj.WordConfidenceInterval81To90 = reader.ReadElementContentAsString();
break;
case "word_conf_91_100":
obj.WordConfidenceInterval91To100 = reader.ReadElementContentAsString();
break;
// Media-Related
case "album":
obj.Album = reader.ReadElementContentAsString();
break;
case "artist":
obj.Artist = reader.ReadElementContentAsString();
break;
case "bitrate":
obj.Bitrate = reader.ReadElementContentAsString();
break;
case "creator":
obj.Creator = reader.ReadElementContentAsString();
break;
case "height":
obj.Height = reader.ReadElementContentAsString();
break;
case "length":
obj.Length = reader.ReadElementContentAsString();
break;
case "preview-image":
obj.PreviewImage = reader.ReadElementContentAsString();
break;
case "rotation":
obj.Rotation = reader.ReadElementContentAsString();
break;
case "title":
obj.Title = reader.ReadElementContentAsString();
break;
case "track":
obj.Track = reader.ReadElementContentAsString();
break;
case "width":
obj.Width = reader.ReadElementContentAsString();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
return obj;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,868 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using SabreTools.Data.Models.Logiqx;
namespace SabreTools.Serialization.Readers
{
public class Logiqx : XmlFile<Datafile>
public class Logiqx : BaseBinaryReader<Datafile>
{
// All logic taken care of in the base class
/// <inheritdoc/>
public override Datafile? Deserialize(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
try
{
// Cache the current offset
long initialOffset = data.Position;
// Create the XmlTextReader
var reader = new XmlTextReader(data);
reader.WhitespaceHandling = WhitespaceHandling.None;
// Parse the XML, if possible
Datafile? datafile = null;
while (reader.Read())
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "datafile":
if (datafile is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
datafile = ParseDatafile(reader);
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
break;
}
}
return datafile;
}
catch
{
// Ignore the actual error
return null;
}
}
/// <summary>
/// Parse from an XmlTextReader into a Datafile
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Datafile on success, null on error</returns>
public Datafile ParseDatafile(XmlTextReader reader)
{
var obj = new Datafile();
obj.Build = reader.GetAttribute("build");
obj.Debug = reader.GetAttribute("debug");
// TODO: Fix this based on No-Intro DATs
// obj.SchemaLocation = reader.GetAttribute("schemaLocation");
List<GameBase> games = [];
List<Dir> dirs = [];
while (reader.Read())
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "header":
if (obj.Header is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Header = ParseHeader(reader);
break;
case "game":
case "machine":
var game = ParseGameBase(reader);
if (game is not null)
games.Add(game);
break;
case "dir":
var dir = ParseDir(reader);
if (dir is not null)
dirs.Add(dir);
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
break;
}
}
if (games.Count > 0)
obj.Game = [.. games];
if (dirs.Count > 0)
obj.Dir = [.. dirs];
return obj;
}
#region Header
/// <summary>
/// Parse from an XmlTextReader into a ClrMamePro
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled ClrMamePro on success, null on error</returns>
public Data.Models.Logiqx.ClrMamePro ParseClrMamePro(XmlTextReader reader)
{
var obj = new Data.Models.Logiqx.ClrMamePro();
obj.Header = reader.GetAttribute("header");
obj.ForceMerging = reader.GetAttribute("forcemerging");
obj.ForceNodump = reader.GetAttribute("forcenodump");
obj.ForcePacking = reader.GetAttribute("forcepacking");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Header
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Header on success, null on error</returns>
public Header ParseHeader(XmlTextReader reader)
{
var obj = new Header();
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "id":
if (obj.Id is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Id = reader.ReadElementContentAsString();
break;
case "name":
if (obj.Name is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Name = reader.ReadElementContentAsString();
break;
case "description":
if (obj.Description is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Description = reader.ReadElementContentAsString();
break;
case "rootdir":
if (obj.RootDir is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.RootDir = reader.ReadElementContentAsString();
break;
case "category":
if (obj.Category is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Category = reader.ReadElementContentAsString();
break;
case "version":
if (obj.Version is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Version = reader.ReadElementContentAsString();
break;
case "date":
if (obj.Date is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Date = reader.ReadElementContentAsString();
break;
case "author":
if (obj.Author is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Author = reader.ReadElementContentAsString();
break;
case "email":
if (obj.Email is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Email = reader.ReadElementContentAsString();
break;
case "homepage":
if (obj.Homepage is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Homepage = reader.ReadElementContentAsString();
break;
case "url":
if (obj.Url is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Url = reader.ReadElementContentAsString();
break;
case "comment":
if (obj.Comment is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Comment = reader.ReadElementContentAsString();
break;
case "type":
if (obj.Type is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Type = reader.ReadElementContentAsString();
break;
case "clrmamepro":
if (obj.ClrMamePro is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.ClrMamePro = ParseClrMamePro(reader);
reader.Skip();
break;
case "romcenter":
if (obj.RomCenter is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.RomCenter = ParseRomCenter(reader);
reader.Skip();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a RomCenter
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled RomCenter on success, null on error</returns>
public Data.Models.Logiqx.RomCenter ParseRomCenter(XmlTextReader reader)
{
var obj = new Data.Models.Logiqx.RomCenter();
obj.Plugin = reader.GetAttribute("plugin");
obj.RomMode = reader.GetAttribute("rommode");
obj.BiosMode = reader.GetAttribute("biosmode");
obj.SampleMode = reader.GetAttribute("samplemode");
obj.LockRomMode = reader.GetAttribute("lockrommode");
obj.LockBiosMode = reader.GetAttribute("lockbiosmode");
obj.LockSampleMode = reader.GetAttribute("locksamplemode");
return obj;
}
#endregion
#region Items
/// <summary>
/// Parse from an XmlTextReader into a Archive
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Archive on success, null on error</returns>
public Archive ParseArchive(XmlTextReader reader)
{
var obj = new Archive();
obj.Name = reader.GetAttribute("name");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a BiosSet
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled BiosSet on success, null on error</returns>
public BiosSet ParseBiosSet(XmlTextReader reader)
{
var obj = new BiosSet();
obj.Name = reader.GetAttribute("name");
obj.Description = reader.GetAttribute("description");
obj.Default = reader.GetAttribute("default");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a DeviceRef
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled DeviceRef on success, null on error</returns>
public DeviceRef ParseDeviceRef(XmlTextReader reader)
{
var obj = new DeviceRef();
obj.Name = reader.GetAttribute("name");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Dir
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Dir on success, null on error</returns>
public Dir ParseDir(XmlTextReader reader)
{
var obj = new Dir();
obj.Name = reader.GetAttribute("name");
List<Dir> subdirs = [];
List<GameBase> games = [];
while (reader.Read())
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "dir":
var dir = ParseDir(reader);
if (dir is not null)
subdirs.Add(dir);
break;
case "game":
case "machine":
var game = ParseGameBase(reader);
if (game is not null)
games.Add(game);
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
break;
}
}
if (subdirs.Count > 0)
obj.Subdir = [.. subdirs];
if (games.Count > 0)
obj.Game = [.. games];
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Disk
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Disk on success, null on error</returns>
public Disk ParseDisk(XmlTextReader reader)
{
var obj = new Disk();
obj.Name = reader.GetAttribute("name");
obj.MD5 = reader.GetAttribute("md5");
obj.SHA1 = reader.GetAttribute("sha1");
obj.Merge = reader.GetAttribute("merge");
obj.Status = reader.GetAttribute("status");
obj.Region = reader.GetAttribute("region");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Driver
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Driver on success, null on error</returns>
public Driver ParseDriver(XmlTextReader reader)
{
var obj = new Driver();
obj.Status = reader.GetAttribute("status");
obj.Emulation = reader.GetAttribute("emulation");
obj.Cocktail = reader.GetAttribute("cocktail");
obj.SaveState = reader.GetAttribute("savestate");
obj.RequiresArtwork = reader.GetAttribute("requiresartwork");
obj.Unofficial = reader.GetAttribute("unofficial");
obj.NoSoundHardware = reader.GetAttribute("nosoundhardware");
obj.Incomplete = reader.GetAttribute("incomplete");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a GameBase
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled GameBase on success, null on error</returns>
public GameBase? ParseGameBase(XmlTextReader reader)
{
GameBase obj;
if (reader.Name == "game")
obj = new Game();
else if (reader.Name == "machine")
obj = new Machine();
else
return null;
obj.Name = reader.GetAttribute("name");
obj.SourceFile = reader.GetAttribute("sourcefile");
obj.IsBios = reader.GetAttribute("isbios");
obj.IsDevice = reader.GetAttribute("isdevice");
obj.IsMechanical = reader.GetAttribute("ismechanical");
obj.CloneOf = reader.GetAttribute("cloneof");
obj.RomOf = reader.GetAttribute("romof");
obj.SampleOf = reader.GetAttribute("sampleof");
obj.Board = reader.GetAttribute("board");
obj.RebuildTo = reader.GetAttribute("rebuildto");
obj.Id = reader.GetAttribute("id");
obj.CloneOfId = reader.GetAttribute("cloneofid");
obj.Runnable = reader.GetAttribute("runnable");
List<string> comments = [];
List<string> categories = [];
List<Release> releases = [];
List<BiosSet> biosSets = [];
List<Rom> roms = [];
List<Disk> disks = [];
List<Media> medias = [];
List<DeviceRef> deviceRefs = [];
List<Sample> samples = [];
List<Archive> archives = [];
List<Data.Models.Logiqx.SoftwareList> softwareLists = [];
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "comment":
var comment = reader.ReadElementContentAsString();
if (comment is not null)
comments.Add(comment);
break;
case "description":
if (obj.Description is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Description = reader.ReadElementContentAsString();
break;
case "year":
if (obj.Year is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Year = reader.ReadElementContentAsString();
break;
case "manufacturer":
if (obj.Manufacturer is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Manufacturer = reader.ReadElementContentAsString();
break;
case "publisher":
if (obj.Publisher is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Publisher = reader.ReadElementContentAsString();
break;
case "category":
var category = reader.ReadElementContentAsString();
if (category is not null)
categories.Add(category);
break;
case "trurip":
if (obj.Trurip is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Trurip = ParseTrurip(reader);
reader.Skip();
break;
case "release":
var release = ParseRelease(reader);
if (release is not null)
releases.Add(release);
reader.Skip();
break;
case "biosset":
var biosSet = ParseBiosSet(reader);
if (biosSet is not null)
biosSets.Add(biosSet);
reader.Skip();
break;
case "rom":
var rom = ParseRom(reader);
if (rom is not null)
roms.Add(rom);
reader.Skip();
break;
case "disk":
var disk = ParseDisk(reader);
if (disk is not null)
disks.Add(disk);
reader.Skip();
break;
case "media":
var media = ParseMedia(reader);
if (media is not null)
medias.Add(media);
reader.Skip();
break;
case "device_ref":
var deviceRef = ParseDeviceRef(reader);
if (deviceRef is not null)
deviceRefs.Add(deviceRef);
reader.Skip();
break;
case "sample":
var sample = ParseSample(reader);
if (sample is not null)
samples.Add(sample);
reader.Skip();
break;
case "archive":
var archive = ParseArchive(reader);
if (archive is not null)
archives.Add(archive);
reader.Skip();
break;
case "driver":
if (obj.Driver is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Driver = ParseDriver(reader);
reader.Skip();
break;
case "softwarelist":
var softwareList = ParseSoftwareList(reader);
if (softwareList is not null)
softwareLists.Add(softwareList);
reader.Skip();
break;
case "url":
if (obj.Url is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Url = reader.ReadElementContentAsString();
break;
case "hash":
if (obj.Hash is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Hash = reader.ReadElementContentAsString();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
if (comments.Count > 0)
obj.Comment = [.. comments];
if (categories.Count > 0)
obj.Category = [.. categories];
if (releases.Count > 0)
obj.Release = [.. releases];
if (biosSets.Count > 0)
obj.BiosSet = [.. biosSets];
if (roms.Count > 0)
obj.Rom = [.. roms];
if (disks.Count > 0)
obj.Disk = [.. disks];
if (medias.Count > 0)
obj.Media = [.. medias];
if (deviceRefs.Count > 0)
obj.DeviceRef = [.. deviceRefs];
if (samples.Count > 0)
obj.Sample = [.. samples];
if (archives.Count > 0)
obj.Archive = [.. archives];
if (softwareLists.Count > 0)
obj.SoftwareList = [.. softwareLists];
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Media
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Media on success, null on error</returns>
public Media ParseMedia(XmlTextReader reader)
{
var obj = new Media();
obj.Name = reader.GetAttribute("name");
obj.MD5 = reader.GetAttribute("md5");
obj.SHA1 = reader.GetAttribute("sha1");
obj.SHA256 = reader.GetAttribute("sha256");
obj.SpamSum = reader.GetAttribute("spamsum");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Release
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Release on success, null on error</returns>
public Release ParseRelease(XmlTextReader reader)
{
var obj = new Release();
obj.Name = reader.GetAttribute("name");
obj.Region = reader.GetAttribute("region");
obj.Language = reader.GetAttribute("language");
obj.Date = reader.GetAttribute("date");
obj.Default = reader.GetAttribute("default");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Rom
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Rom on success, null on error</returns>
public Rom ParseRom(XmlTextReader reader)
{
var obj = new Rom();
obj.Name = reader.GetAttribute("name");
obj.Size = reader.GetAttribute("size");
obj.CRC16 = reader.GetAttribute("crc16");
obj.CRC = reader.GetAttribute("crc");
obj.CRC64 = reader.GetAttribute("crc64");
obj.MD2 = reader.GetAttribute("md2");
obj.MD4 = reader.GetAttribute("md4");
obj.MD5 = reader.GetAttribute("md5");
obj.RIPEMD128 = reader.GetAttribute("ripemd128");
obj.RIPEMD160 = reader.GetAttribute("ripemd160");
obj.SHA1 = reader.GetAttribute("sha1");
obj.SHA256 = reader.GetAttribute("sha256");
obj.SHA384 = reader.GetAttribute("sha384");
obj.SHA512 = reader.GetAttribute("sha512");
obj.SpamSum = reader.GetAttribute("spamsum");
obj.xxHash364 = reader.GetAttribute("xxh3_64");
obj.xxHash3128 = reader.GetAttribute("xxh3_128");
obj.Merge = reader.GetAttribute("merge");
obj.Status = reader.GetAttribute("status");
obj.Serial = reader.GetAttribute("serial");
obj.Header = reader.GetAttribute("header");
obj.Date = reader.GetAttribute("date");
obj.Inverted = reader.GetAttribute("inverted");
obj.MIA = reader.GetAttribute("mia");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Sample
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Sample on success, null on error</returns>
public Sample ParseSample(XmlTextReader reader)
{
var obj = new Sample();
obj.Name = reader.GetAttribute("name");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a SoftwareList
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled SoftwareList on success, null on error</returns>
public Data.Models.Logiqx.SoftwareList ParseSoftwareList(XmlTextReader reader)
{
var obj = new Data.Models.Logiqx.SoftwareList();
obj.Tag = reader.GetAttribute("tag");
obj.Name = reader.GetAttribute("name");
obj.Status = reader.GetAttribute("status");
obj.Filter = reader.GetAttribute("filter");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Trurip
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Trurip on success, null on error</returns>
public Trurip ParseTrurip(XmlTextReader reader)
{
var obj = new Trurip();
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "titleid":
if (obj.TitleID is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.TitleID = reader.ReadElementContentAsString();
break;
case "publisher":
if (obj.Publisher is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Publisher = reader.ReadElementContentAsString();
break;
case "developer":
if (obj.Developer is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Developer = reader.ReadElementContentAsString();
break;
case "year":
if (obj.Year is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Year = reader.ReadElementContentAsString();
break;
case "genre":
if (obj.Genre is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Genre = reader.ReadElementContentAsString();
break;
case "subgenre":
if (obj.Subgenre is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Subgenre = reader.ReadElementContentAsString();
break;
case "ratings":
if (obj.Ratings is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Ratings = reader.ReadElementContentAsString();
break;
case "score":
if (obj.Score is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Score = reader.ReadElementContentAsString();
break;
case "players":
if (obj.Players is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Players = reader.ReadElementContentAsString();
break;
case "enabled":
if (obj.Enabled is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Enabled = reader.ReadElementContentAsString();
break;
case "crc":
if (obj.CRC is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.CRC = reader.ReadElementContentAsString();
break;
case "source":
if (obj.Source is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Source = reader.ReadElementContentAsString();
break;
case "cloneof":
if (obj.CloneOf is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.CloneOf = reader.ReadElementContentAsString();
break;
case "relatedto":
if (obj.RelatedTo is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.RelatedTo = reader.ReadElementContentAsString();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
return obj;
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,318 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using SabreTools.Data.Models.OpenMSX;
namespace SabreTools.Serialization.Readers
{
public class OpenMSX : XmlFile<SoftwareDb>
public class OpenMSX : BaseBinaryReader<SoftwareDb>
{
// All logic taken care of in the base class
/// <inheritdoc/>
public override SoftwareDb? Deserialize(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
try
{
// Cache the current offset
long initialOffset = data.Position;
// Create the XmlTextReader
var reader = new XmlTextReader(data);
reader.WhitespaceHandling = WhitespaceHandling.None;
// Parse the XML, if possible
SoftwareDb? softwareDb = null;
while (reader.Read())
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "softwaredb":
if (softwareDb is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
softwareDb = ParseSoftwareDb(reader);
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
break;
}
}
return softwareDb;
}
catch
{
// Ignore the actual error
return null;
}
}
/// <summary>
/// Parse from an XmlTextReader into a SoftwareDb
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled SoftwareDb on success, null on error</returns>
public SoftwareDb ParseSoftwareDb(XmlTextReader reader)
{
var obj = new SoftwareDb();
obj.Timestamp = reader.GetAttribute("timestamp");
List<Software> softwares = [];
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "software":
var software = ParseSoftware(reader);
if (software is not null)
softwares.Add(software);
reader.Skip();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
if (softwares.Count > 0)
obj.Software = [.. softwares];
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Dump
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Dump on success, null on error</returns>
public Dump ParseDump(XmlTextReader reader)
{
var obj = new Dump();
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "original":
if (obj.Original is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Original = ParseOriginal(reader);
break;
case "rom":
case "megarom":
case "sccpluscart":
if (obj.Rom is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Rom = ParseRomBase(reader);
reader.Skip();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
break;
}
}
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Original
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Original on success, null on error</returns>
public Original ParseOriginal(XmlTextReader reader)
{
var obj = new Original();
obj.Value = reader.GetAttribute("value");
obj.Content = reader.ReadElementContentAsString();
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a RomBase
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled RomBase on success, null on error</returns>
public RomBase? ParseRomBase(XmlTextReader reader)
{
RomBase obj;
if (reader.Name == "rom")
obj = new Rom();
else if (reader.Name == "megarom")
obj = new MegaRom();
else if (reader.Name == "sccpluscart")
obj = new SCCPlusCart();
else
return null;
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "start":
if (obj.Start is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Start = reader.ReadElementContentAsString();
break;
case "type":
if (obj.Type is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Type = reader.ReadElementContentAsString();
break;
case "hash":
if (obj.Hash is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Hash = reader.ReadElementContentAsString();
break;
case "remark":
if (obj.Remark is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Remark = reader.ReadElementContentAsString();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Software
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Software on success, null on error</returns>
public Software ParseSoftware(XmlTextReader reader)
{
var obj = new Software();
List<Dump> dumps = [];
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "title":
if (obj.Title is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Title = reader.ReadElementContentAsString();
break;
case "genmsxid":
if (obj.GenMSXID is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.GenMSXID = reader.ReadElementContentAsString();
break;
case "system":
if (obj.System is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.System = reader.ReadElementContentAsString();
break;
case "company":
if (obj.Company is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Company = reader.ReadElementContentAsString();
break;
case "year":
if (obj.Year is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Year = reader.ReadElementContentAsString();
break;
case "country":
if (obj.Country is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Country = reader.ReadElementContentAsString();
break;
case "dump":
var dump = ParseDump(reader);
if (dump is not null)
dumps.Add(dump);
reader.Skip();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
if (dumps.Count > 0)
obj.Dump = [.. dumps];
return obj;
}
}
}

View File

@@ -1,7 +1,535 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using SabreTools.Data.Models.SoftwareList;
namespace SabreTools.Serialization.Readers
{
public class SoftwareList : XmlFile<Data.Models.SoftwareList.SoftwareList>
public class SoftwareList : BaseBinaryReader<Data.Models.SoftwareList.SoftwareList>
{
// All logic taken care of in the base class
/// <inheritdoc/>
public override Data.Models.SoftwareList.SoftwareList? Deserialize(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
try
{
// Cache the current offset
long initialOffset = data.Position;
// Create the XmlTextReader
var reader = new XmlTextReader(data);
reader.WhitespaceHandling = WhitespaceHandling.None;
// Parse the XML, if possible
Data.Models.SoftwareList.SoftwareList? softwareList = null;
while (reader.Read())
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "softwarelist":
if (softwareList is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
softwareList = ParseSoftwareList(reader);
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
break;
}
}
return softwareList;
}
catch
{
// Ignore the actual error
return null;
}
}
/// <summary>
/// Parse from an XmlTextReader into a SoftwareList
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled SoftwareList on success, null on error</returns>
public Data.Models.SoftwareList.SoftwareList ParseSoftwareList(XmlTextReader reader)
{
var obj = new Data.Models.SoftwareList.SoftwareList();
obj.Name = reader.GetAttribute("name");
obj.Description = reader.GetAttribute("description");
List<Software> softwares = [];
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "notes":
if (obj.Notes is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Notes = reader.ReadElementContentAsString();
break;
case "software":
var software = ParseSoftware(reader);
if (software is not null)
softwares.Add(software);
reader.Skip();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
if (softwares.Count > 0)
obj.Software = [.. softwares];
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a DataArea
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled DataArea on success, null on error</returns>
public DataArea ParseDataArea(XmlTextReader reader)
{
var obj = new DataArea();
obj.Name = reader.GetAttribute("name");
obj.Size = reader.GetAttribute("size");
obj.Width = reader.GetAttribute("width");
obj.Endianness = reader.GetAttribute("endianness");
List<Rom> roms = [];
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "rom":
var rom = ParseRom(reader);
if (rom is not null)
roms.Add(rom);
reader.Skip();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
if (roms.Count > 0)
obj.Rom = [.. roms];
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a DipSwitch
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled DipSwitch on success, null on error</returns>
public DipSwitch ParseDipSwitch(XmlTextReader reader)
{
var obj = new DipSwitch();
obj.Name = reader.GetAttribute("name");
obj.Tag = reader.GetAttribute("tag");
obj.Mask = reader.GetAttribute("mask");
List<DipValue> dipValues = [];
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "dipvalue":
var dipValue = ParseDipValue(reader);
if (dipValue is not null)
dipValues.Add(dipValue);
reader.Skip();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
if (dipValues.Count > 0)
obj.DipValue = [.. dipValues];
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a DipValue
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled DipValue on success, null on error</returns>
public DipValue ParseDipValue(XmlTextReader reader)
{
var obj = new DipValue();
obj.Name = reader.GetAttribute("name");
obj.Value = reader.GetAttribute("value");
obj.Default = reader.GetAttribute("default");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Disk
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Disk on success, null on error</returns>
public Disk ParseDisk(XmlTextReader reader)
{
var obj = new Disk();
obj.Name = reader.GetAttribute("name");
obj.MD5 = reader.GetAttribute("md5");
obj.SHA1 = reader.GetAttribute("sha1");
obj.Status = reader.GetAttribute("status");
obj.Writeable = reader.GetAttribute("writable");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a DiskArea
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled DiskArea on success, null on error</returns>
public DiskArea ParseDiskArea(XmlTextReader reader)
{
var obj = new DiskArea();
obj.Name = reader.GetAttribute("name");
List<Disk> disks = [];
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "disk":
var disk = ParseDisk(reader);
if (disk is not null)
disks.Add(disk);
reader.Skip();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
if (disks.Count > 0)
obj.Disk = [.. disks];
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Feature
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Feature on success, null on error</returns>
public Feature ParseFeature(XmlTextReader reader)
{
var obj = new Feature();
obj.Name = reader.GetAttribute("name");
obj.Value = reader.GetAttribute("value");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Info
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Info on success, null on error</returns>
public Info ParseInfo(XmlTextReader reader)
{
var obj = new Info();
obj.Name = reader.GetAttribute("name");
obj.Value = reader.GetAttribute("value");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Part
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Part on success, null on error</returns>
public Part ParsePart(XmlTextReader reader)
{
var obj = new Part();
obj.Name = reader.GetAttribute("name");
obj.Interface = reader.GetAttribute("interface");
List<Feature> features = [];
List<DataArea> dataAreas = [];
List<DiskArea> diskAreas = [];
List<DipSwitch> dipSwitches = [];
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "feature":
var feature = ParseFeature(reader);
if (feature is not null)
features.Add(feature);
reader.Skip();
break;
case "dataarea":
var dataArea = ParseDataArea(reader);
if (dataArea is not null)
dataAreas.Add(dataArea);
reader.Skip();
break;
case "diskarea":
var diskArea = ParseDiskArea(reader);
if (diskArea is not null)
diskAreas.Add(diskArea);
reader.Skip();
break;
case "dipswitch":
var dipSwitch = ParseDipSwitch(reader);
if (dipSwitch is not null)
dipSwitches.Add(dipSwitch);
reader.Skip();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
if (features.Count > 0)
obj.Feature = [.. features];
if (dataAreas.Count > 0)
obj.DataArea = [.. dataAreas];
if (diskAreas.Count > 0)
obj.DiskArea = [.. diskAreas];
if (dipSwitches.Count > 0)
obj.DipSwitch = [.. dipSwitches];
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Rom
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Rom on success, null on error</returns>
public Rom ParseRom(XmlTextReader reader)
{
var obj = new Rom();
obj.Name = reader.GetAttribute("name");
obj.Size = reader.GetAttribute("size");
obj.Length = reader.GetAttribute("length");
obj.CRC = reader.GetAttribute("crc");
obj.SHA1 = reader.GetAttribute("sha1");
obj.Offset = reader.GetAttribute("offset");
obj.Value = reader.GetAttribute("value");
obj.Status = reader.GetAttribute("status");
obj.LoadFlag = reader.GetAttribute("loadflag");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a SharedFeat
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled SharedFeat on success, null on error</returns>
public SharedFeat ParseSharedFeat(XmlTextReader reader)
{
var obj = new SharedFeat();
obj.Name = reader.GetAttribute("name");
obj.Value = reader.GetAttribute("value");
return obj;
}
/// <summary>
/// Parse from an XmlTextReader into a Software
/// </summary>
/// <param name="reader">XmlTextReader to read from</param>
/// <returns>Filled Software on success, null on error</returns>
public Software ParseSoftware(XmlTextReader reader)
{
var obj = new Software();
obj.Name = reader.GetAttribute("name");
obj.CloneOf = reader.GetAttribute("cloneof");
obj.Supported = reader.GetAttribute("supported");
List<Info> infos = [];
List<SharedFeat> sharedFeats = [];
List<Part> parts = [];
reader.Read();
while (!reader.EOF)
{
// An ending element means exit
if (reader.NodeType == XmlNodeType.EndElement)
break;
// Only process starting elements
if (!reader.IsStartElement())
continue;
switch (reader.Name)
{
case "description":
if (obj.Description is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Description = reader.ReadElementContentAsString();
break;
case "year":
if (obj.Year is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Year = reader.ReadElementContentAsString();
break;
case "publisher":
if (obj.Publisher is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Publisher = reader.ReadElementContentAsString();
break;
case "notes":
if (obj.Notes is not null && Debug)
Console.WriteLine($"'{reader.Name}' element already found, overwriting");
obj.Notes = reader.ReadElementContentAsString();
break;
case "info":
var info = ParseInfo(reader);
if (info is not null)
infos.Add(info);
reader.Skip();
break;
case "sharedfeat":
var sharedFeat = ParseSharedFeat(reader);
if (sharedFeat is not null)
sharedFeats.Add(sharedFeat);
reader.Skip();
break;
case "part":
var part = ParsePart(reader);
if (part is not null)
parts.Add(part);
reader.Skip();
break;
default:
if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized");
reader.Skip();
break;
}
}
if (infos.Count > 0)
obj.Info = [.. infos];
if (sharedFeats.Count > 0)
obj.SharedFeat = [.. sharedFeats];
if (parts.Count > 0)
obj.Part = [.. parts];
return obj;
}
}
}

View File

@@ -1,47 +0,0 @@
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace SabreTools.Serialization.Readers
{
/// <summary>
/// Base class for other XML deserializers
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class XmlFile<T> : BaseBinaryReader<T>
{
/// <inheritdoc/>
public override T? Deserialize(Stream? data)
{
// If the stream is invalid
if (data is null || !data.CanRead)
return default;
try
{
// Setup the serializer and the reader
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings
{
CheckCharacters = false,
#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
DtdProcessing = DtdProcessing.Ignore,
#endif
ValidationFlags = XmlSchemaValidationFlags.None,
ValidationType = ValidationType.None,
};
var streamReader = new StreamReader(data);
var xmlReader = XmlReader.Create(streamReader, settings);
// Perform the deserialization and return
return (T?)serializer.Deserialize(xmlReader);
}
catch
{
// Ignore the actual error
return default;
}
}
}
}