diff --git a/SabreTools.DatFiles/Formats/ClrMamePro.Reader.cs b/SabreTools.DatFiles/Formats/ClrMamePro.Reader.cs
index 83b83189..5b01f166 100644
--- a/SabreTools.DatFiles/Formats/ClrMamePro.Reader.cs
+++ b/SabreTools.DatFiles/Formats/ClrMamePro.Reader.cs
@@ -129,7 +129,7 @@ namespace SabreTools.DatFiles.Formats
ConvertMedia(game.Media, machine, filename, indexId, statsOnly, ref containsItems);
ConvertArchives(game.Archive, machine, filename, indexId, statsOnly, ref containsItems);
ConvertChips(game.Chip, machine, filename, indexId, statsOnly, ref containsItems);
- ConvertVideo(game.Video, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertVideos(game.Video, machine, filename, indexId, statsOnly, ref containsItems);
ConvertSound(game.Sound, machine, filename, indexId, statsOnly, ref containsItems);
ConvertInput(game.Input, machine, filename, indexId, statsOnly, ref containsItems);
ConvertDipSwitches(game.DipSwitch, machine, filename, indexId, statsOnly, ref containsItems);
@@ -431,47 +431,50 @@ namespace SabreTools.DatFiles.Formats
///
/// Convert Video information
///
- /// Deserialized model to convert
+ /// Array of deserialized models to convert
/// Prefilled machine to use
/// Name of the file to be parsed
/// Index ID for the DAT
/// True to only add item statistics while parsing, false otherwise
/// True if there were any items in the array, false otherwise
- private void ConvertVideo(Models.ClrMamePro.Video? video, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ private void ConvertVideos(Models.ClrMamePro.Video[]? videos, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
- // If the video is missing, we can't do anything
- if (video == null)
+ // If the video array is missing, we can't do anything
+ if (videos == null || !videos.Any())
return;
containsItems = true;
- var item = new Display
+ foreach (var video in videos)
{
- DisplayType = video.Screen?.AsDisplayType() ?? DisplayType.NULL,
- Width = Utilities.CleanLong(video.X),
- Height = Utilities.CleanLong(video.Y),
- //AspectX = video.AspectX, // TODO: Add to internal model or find mapping
- //AspectY = video.AspectY, // TODO: Add to internal model or find mapping
- Refresh = Utilities.CleanDouble(video.Freq),
-
- Source = new Source
+ var item = new Display
{
- Index = indexId,
- Name = filename,
- },
- };
+ DisplayType = video.Screen?.AsDisplayType() ?? DisplayType.NULL,
+ Width = Utilities.CleanLong(video.X),
+ Height = Utilities.CleanLong(video.Y),
+ //AspectX = video.AspectX, // TODO: Add to internal model or find mapping
+ //AspectY = video.AspectY, // TODO: Add to internal model or find mapping
+ Refresh = Utilities.CleanDouble(video.Freq),
- switch (video.Orientation)
- {
- case "horizontal":
- item.Rotate = 0;
- break;
- case "vertical":
- item.Rotate = 90;
- break;
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ switch (video.Orientation)
+ {
+ case "horizontal":
+ item.Rotate = 0;
+ break;
+ case "vertical":
+ item.Rotate = 90;
+ break;
+ }
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
}
-
- item.CopyMachineInformation(machine);
- ParseAddHelper(item, statsOnly);
}
///
diff --git a/SabreTools.DatFiles/Formats/ClrMamePro.Writer.cs b/SabreTools.DatFiles/Formats/ClrMamePro.Writer.cs
index 897e4378..1d8ef220 100644
--- a/SabreTools.DatFiles/Formats/ClrMamePro.Writer.cs
+++ b/SabreTools.DatFiles/Formats/ClrMamePro.Writer.cs
@@ -251,6 +251,7 @@ namespace SabreTools.DatFiles.Formats
var samples = new List();
var archives = new List();
var chips = new List();
+ var videos = new List();
var dipswitches = new List();
// Loop through and convert the items to respective lists
@@ -293,7 +294,7 @@ namespace SabreTools.DatFiles.Formats
chips.Add(CreateChip(chip));
break;
case Display display:
- game.Video = CreateVideo(display);
+ videos.Add(CreateVideo(display));
break;
case Sound sound:
game.Sound = CreateSound(sound);
@@ -318,6 +319,9 @@ namespace SabreTools.DatFiles.Formats
game.Media = medias.ToArray();
game.Sample = samples.ToArray();
game.Archive = archives.ToArray();
+ game.Chip = chips.ToArray();
+ game.Video = videos.ToArray();
+ game.DipSwitch = dipswitches.ToArray();
// Add the game to the list
games.Add(game);
diff --git a/SabreTools.IO/IOExtensions.cs b/SabreTools.IO/IOExtensions.cs
index 4ebd837d..6124c2d5 100644
--- a/SabreTools.IO/IOExtensions.cs
+++ b/SabreTools.IO/IOExtensions.cs
@@ -59,6 +59,9 @@ namespace SabreTools.IO
file.Read(bom, 0, 4);
file.Dispose();
+ // Disable warning about UTF7 usage
+ #pragma warning disable SYSLIB0001
+
// Analyze the BOM
if (bom[0] == 0x2b && bom[1] == 0x2f && bom[2] == 0x76) return Encoding.UTF7;
if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf) return Encoding.UTF8;
@@ -66,6 +69,8 @@ namespace SabreTools.IO
if (bom[0] == 0xfe && bom[1] == 0xff) return Encoding.BigEndianUnicode; //UTF-16BE
if (bom[0] == 0 && bom[1] == 0 && bom[2] == 0xfe && bom[3] == 0xff) return Encoding.UTF32;
return Encoding.Default;
+
+ #pragma warning restore SYSLIB0001
}
catch
{
@@ -78,14 +83,14 @@ namespace SabreTools.IO
///
/// Path to get extension from
/// Extension, if possible
- public static string GetNormalizedExtension(this string path)
+ public static string? GetNormalizedExtension(this string? path)
{
// Check null or empty first
if (string.IsNullOrWhiteSpace(path))
return null;
// Get the extension from the path, if possible
- string ext = Path.GetExtension(path)?.ToLowerInvariant();
+ string? ext = Path.GetExtension(path)?.ToLowerInvariant();
// Check if the extension is null or empty
if (string.IsNullOrWhiteSpace(ext))
@@ -96,13 +101,13 @@ namespace SabreTools.IO
return ext;
}
-
+
///
/// Get all empty folders within a root folder
///
/// Root directory to parse
/// IEumerable containing all directories that are empty, an empty enumerable if the root is empty, null otherwise
- public static List ListEmpty(this string root)
+ public static List? ListEmpty(this string? root)
{
// Check null or empty first
if (string.IsNullOrEmpty(root))
diff --git a/SabreTools.IO/ParentablePath.cs b/SabreTools.IO/ParentablePath.cs
index 4bb7d328..505e09aa 100644
--- a/SabreTools.IO/ParentablePath.cs
+++ b/SabreTools.IO/ParentablePath.cs
@@ -11,14 +11,14 @@ namespace SabreTools.IO
///
/// Current full path represented
///
- public string CurrentPath { get; private set; }
+ public string CurrentPath { get; init; }
///
/// Possible parent path represented (may be null or empty)
///
- public string ParentPath { get; private set; }
+ public string? ParentPath { get; init; }
- public ParentablePath(string currentPath, string parentPath = null)
+ public ParentablePath(string currentPath, string? parentPath = null)
{
CurrentPath = currentPath;
ParentPath = parentPath;
@@ -29,7 +29,7 @@ namespace SabreTools.IO
///
/// True if path separators should be converted to '-', false otherwise
/// Subpath for the file
- public string GetNormalizedFileName(bool sanitize)
+ public string? GetNormalizedFileName(bool sanitize)
{
// If the current path is empty, we can't do anything
if (string.IsNullOrWhiteSpace(CurrentPath))
@@ -55,7 +55,7 @@ namespace SabreTools.IO
/// Output directory to use
/// True if the output file should go to the same input folder, false otherwise
/// Complete output path
- public string GetOutputPath(string outDir, bool inplace)
+ public string? GetOutputPath(string outDir, bool inplace)
{
// If the current path is empty, we can't do anything
if (string.IsNullOrWhiteSpace(CurrentPath))
@@ -73,21 +73,22 @@ namespace SabreTools.IO
return Path.GetDirectoryName(CurrentPath);
// If the current and parent paths are the same, just use the output directory
- if (!splitpath || CurrentPath.Length == ParentPath.Length)
+ if (!splitpath || CurrentPath.Length == (ParentPath?.Length ?? 0))
return outDir;
// By default, the working parent directory is the parent path
- string workingParent = ParentPath;
+ string workingParent = ParentPath ?? string.Empty;
// TODO: Should this be the default? Always create a subfolder if a folder is found?
// If we are processing a path that is coming from a directory and we are outputting to the current directory, we want to get the subfolder to write to
if (outDir == Environment.CurrentDirectory)
- workingParent = Path.GetDirectoryName(ParentPath);
+ workingParent = Path.GetDirectoryName(ParentPath ?? string.Empty) ?? string.Empty;
// Determine the correct subfolder based on the working parent directory
int extraLength = workingParent.EndsWith(':')
|| workingParent.EndsWith(Path.DirectorySeparatorChar)
|| workingParent.EndsWith(Path.AltDirectorySeparatorChar) ? 0 : 1;
+
return Path.GetDirectoryName(Path.Combine(outDir, CurrentPath.Remove(0, workingParent.Length + extraLength)));
}
}
diff --git a/SabreTools.IO/Readers/ClrMameProReader.cs b/SabreTools.IO/Readers/ClrMameProReader.cs
index 5b6f864d..3e22067c 100644
--- a/SabreTools.IO/Readers/ClrMameProReader.cs
+++ b/SabreTools.IO/Readers/ClrMameProReader.cs
@@ -23,12 +23,12 @@ namespace SabreTools.IO.Readers
///
/// Internal stream reader for inputting
///
- private readonly StreamReader sr;
+ private readonly StreamReader? sr;
///
/// Contents of the current line, unprocessed
///
- public string CurrentLine { get; private set; } = string.Empty;
+ public string? CurrentLine { get; private set; } = string.Empty;
///
/// Get the current line number
@@ -49,12 +49,12 @@ namespace SabreTools.IO.Readers
///
/// Contents of the currently read line as an internal item
///
- public Dictionary Internal { get; private set; } = new Dictionary();
+ public Dictionary? Internal { get; private set; } = new Dictionary();
///
/// Current internal item name
///
- public string InternalName { get; private set; } = null;
+ public string? InternalName { get; private set; }
///
/// Get if we should be making DosCenter exceptions
@@ -85,7 +85,7 @@ namespace SabreTools.IO.Readers
///
/// Current top-level being read
///
- public string TopLevel { get; private set; } = string.Empty;
+ public string? TopLevel { get; private set; } = string.Empty;
///
/// Constructor for opening a write from a file
@@ -108,10 +108,13 @@ namespace SabreTools.IO.Readers
///
public bool ReadNextLine()
{
- if (!(sr.BaseStream?.CanRead ?? false) || sr.EndOfStream)
+ if (sr?.BaseStream == null)
return false;
- CurrentLine = sr.ReadLine().Trim();
+ if (!sr.BaseStream.CanRead || sr.EndOfStream)
+ return false;
+
+ CurrentLine = sr.ReadLine()?.Trim();
LineNumber++;
ProcessLine();
return true;
@@ -122,6 +125,9 @@ namespace SabreTools.IO.Readers
///
private void ProcessLine()
{
+ if (CurrentLine == null)
+ return;
+
// Standalone (special case for DC dats)
if (CurrentLine.StartsWith("Name:"))
{
@@ -303,7 +309,7 @@ namespace SabreTools.IO.Readers
///
public void Dispose()
{
- sr.Dispose();
+ sr?.Dispose();
}
}
}
diff --git a/SabreTools.IO/Readers/IniReader.cs b/SabreTools.IO/Readers/IniReader.cs
index 4296fb19..0d1e84ac 100644
--- a/SabreTools.IO/Readers/IniReader.cs
+++ b/SabreTools.IO/Readers/IniReader.cs
@@ -11,7 +11,7 @@ namespace SabreTools.IO.Readers
///
/// Internal stream reader for inputting
///
- private readonly StreamReader sr;
+ private readonly StreamReader? sr;
///
/// Get if at end of stream
@@ -32,7 +32,7 @@ namespace SabreTools.IO.Readers
///
/// Contents of the current line, unprocessed
///
- public string CurrentLine { get; private set; } = string.Empty;
+ public string? CurrentLine { get; private set; } = string.Empty;
///
/// Get the current line number
@@ -47,7 +47,7 @@ namespace SabreTools.IO.Readers
///
/// Current section being read
///
- public string Section { get; private set; } = string.Empty;
+ public string? Section { get; private set; } = string.Empty;
///
/// Validate that rows are in key=value format
@@ -75,10 +75,13 @@ namespace SabreTools.IO.Readers
///
public bool ReadNextLine()
{
- if (!(sr.BaseStream?.CanRead ?? false) || sr.EndOfStream)
+ if (sr?.BaseStream == null)
return false;
- CurrentLine = sr.ReadLine().Trim();
+ if (!sr.BaseStream.CanRead || sr.EndOfStream)
+ return false;
+
+ CurrentLine = sr.ReadLine()?.Trim();
LineNumber++;
ProcessLine();
return true;
@@ -89,6 +92,9 @@ namespace SabreTools.IO.Readers
///
private void ProcessLine()
{
+ if (CurrentLine == null)
+ return;
+
// Comment
if (CurrentLine.StartsWith(";"))
{
@@ -142,7 +148,7 @@ namespace SabreTools.IO.Readers
///
public void Dispose()
{
- sr.Dispose();
+ sr?.Dispose();
}
}
}
diff --git a/SabreTools.IO/Readers/SeparatedValueReader.cs b/SabreTools.IO/Readers/SeparatedValueReader.cs
index 6941b372..86a2d0fa 100644
--- a/SabreTools.IO/Readers/SeparatedValueReader.cs
+++ b/SabreTools.IO/Readers/SeparatedValueReader.cs
@@ -12,7 +12,7 @@ namespace SabreTools.IO.Readers
///
/// Internal stream reader for inputting
///
- private readonly StreamReader sr;
+ private readonly StreamReader? sr;
///
/// Internal value to say how many fields should be written
@@ -33,7 +33,7 @@ namespace SabreTools.IO.Readers
///
/// Contents of the current line, unprocessed
///
- public string CurrentLine { get; private set; } = string.Empty;
+ public string? CurrentLine { get; private set; } = string.Empty;
///
/// Get the current line number
@@ -48,12 +48,12 @@ namespace SabreTools.IO.Readers
///
/// Header row values
///
- public List HeaderValues { get; set; } = null;
+ public List? HeaderValues { get; set; } = null;
///
/// Get the current line values
///
- public List Line { get; private set; } = null;
+ public List? Line { get; private set; } = null;
///
/// Assume that values are wrapped in quotes
@@ -105,13 +105,19 @@ namespace SabreTools.IO.Readers
///
public bool ReadNextLine()
{
- if (!(sr.BaseStream?.CanRead ?? false) || sr.EndOfStream)
+ if (sr?.BaseStream == null)
return false;
- string fullLine = sr.ReadLine();
+ if (!sr.BaseStream.CanRead || sr.EndOfStream)
+ return false;
+
+ string? fullLine = sr.ReadLine();
CurrentLine = fullLine;
LineNumber++;
+ if (fullLine == null)
+ return false;
+
// If we have quotes, we need to split specially
if (Quotes)
{
@@ -155,17 +161,21 @@ namespace SabreTools.IO.Readers
///
/// Get the value for the current line for the current key
///
- public string GetValue(string key)
+ public string? GetValue(string key)
{
// No header means no key-based indexing
if (!Header)
throw new ArgumentException("No header expected so no keys can be used");
- // If we don't have the key, return null;
+ // If we don't have the key, return null
+ if (HeaderValues == null)
+ throw new ArgumentException($"Current line doesn't have key {key}");
if (!HeaderValues.Contains(key))
return null;
int index = HeaderValues.IndexOf(key);
+ if (Line == null)
+ throw new ArgumentException($"Current line doesn't have index {index}");
if (Line.Count < index)
throw new ArgumentException($"Current line doesn't have index {index}");
@@ -177,6 +187,8 @@ namespace SabreTools.IO.Readers
///
public string GetValue(int index)
{
+ if (Line == null)
+ throw new ArgumentException($"Current line doesn't have index {index}");
if (Line.Count < index)
throw new ArgumentException($"Current line doesn't have index {index}");
@@ -188,7 +200,7 @@ namespace SabreTools.IO.Readers
///
public void Dispose()
{
- sr.Dispose();
+ sr?.Dispose();
}
}
}
diff --git a/SabreTools.IO/SabreTools.IO.csproj b/SabreTools.IO/SabreTools.IO.csproj
index 741d5731..5a4dc941 100644
--- a/SabreTools.IO/SabreTools.IO.csproj
+++ b/SabreTools.IO/SabreTools.IO.csproj
@@ -2,6 +2,7 @@
net6.0;net7.0
+ enable
diff --git a/SabreTools.IO/Writers/ClrMameProWriter.cs b/SabreTools.IO/Writers/ClrMameProWriter.cs
index d9324f1a..b0473c20 100644
--- a/SabreTools.IO/Writers/ClrMameProWriter.cs
+++ b/SabreTools.IO/Writers/ClrMameProWriter.cs
@@ -44,11 +44,8 @@ namespace SabreTools.IO.Writers
///
/// Tag information for the stack
///
- private struct TagInfo
+ private record struct TagInfo(string? Name, bool Mixed)
{
- public string Name;
- public bool Mixed;
-
public void Init()
{
Name = null;
@@ -173,7 +170,7 @@ namespace SabreTools.IO.Writers
///
/// Write a complete element with content
///
- public void WriteElementString(string name, string value)
+ public void WriteElementString(string name, string? value)
{
WriteStartElement(name);
WriteString(value);
@@ -186,7 +183,7 @@ namespace SabreTools.IO.Writers
/// Name of the element
/// Value to write in the element
/// Indicates if an error should be thrown on a missing required value
- public void WriteRequiredElementString(string name, string value, bool throwOnError = false)
+ public void WriteRequiredElementString(string name, string? value, bool throwOnError = false)
{
// Throw an exception if we are configured to
if (value == null && throwOnError)
@@ -200,7 +197,7 @@ namespace SabreTools.IO.Writers
///
/// Name of the element
/// Value to write in the element
- public void WriteOptionalElementString(string name, string value)
+ public void WriteOptionalElementString(string name, string? value)
{
if (!string.IsNullOrEmpty(value))
WriteElementString(name, value);
@@ -253,7 +250,7 @@ namespace SabreTools.IO.Writers
/// Name of the attribute
/// Value to write in the attribute
/// Non-null to overwrite the writer setting, null otherwise
- public void WriteAttributeString(string name, string value, bool? quoteOverride = null)
+ public void WriteAttributeString(string name, string? value, bool? quoteOverride = null)
{
WriteStartAttribute(name, quoteOverride);
WriteString(value);
@@ -267,7 +264,7 @@ namespace SabreTools.IO.Writers
/// Value to write in the attribute
/// Non-null to overwrite the writer setting, null otherwise
/// Indicates if an error should be thrown on a missing required value
- public void WriteRequiredAttributeString(string name, string value, bool? quoteOverride = null, bool throwOnError = false)
+ public void WriteRequiredAttributeString(string name, string? value, bool? quoteOverride = null, bool throwOnError = false)
{
// Throw an exception if we are configured to
if (value == null && throwOnError)
@@ -282,7 +279,7 @@ namespace SabreTools.IO.Writers
/// Name of the attribute
/// Value to write in the attribute
/// Non-null to overwrite the writer setting, null otherwise
- public void WriteOptionalAttributeString(string name, string value, bool? quoteOverride = null)
+ public void WriteOptionalAttributeString(string name, string? value, bool? quoteOverride = null)
{
if (!string.IsNullOrEmpty(value))
WriteAttributeString(name, value, quoteOverride);
@@ -294,7 +291,7 @@ namespace SabreTools.IO.Writers
/// Name of the attribute
/// Value to write in the attribute
/// Non-null to overwrite the writer setting, null otherwise
- public void WriteStandalone(string name, string value, bool? quoteOverride = null)
+ public void WriteStandalone(string name, string? value, bool? quoteOverride = null)
{
try
{
@@ -306,7 +303,7 @@ namespace SabreTools.IO.Writers
|| (quoteOverride == true))
{
name = name.Replace("\"", "''");
- value = value.Replace("\"", "''");
+ value = value?.Replace("\"", "''");
}
AutoComplete(Token.Standalone);
@@ -338,7 +335,7 @@ namespace SabreTools.IO.Writers
/// Value to write in the attribute
/// Non-null to overwrite the writer setting, null otherwise
/// Indicates if an error should be thrown on a missing required value
- public void WriteRequiredStandalone(string name, string value, bool? quoteOverride = null, bool throwOnError = false)
+ public void WriteRequiredStandalone(string name, string? value, bool? quoteOverride = null, bool throwOnError = false)
{
// Throw an exception if we are configured to
if (value == null && throwOnError)
@@ -353,7 +350,7 @@ namespace SabreTools.IO.Writers
/// Name of the attribute
/// Value to write in the attribute
/// Non-null to overwrite the writer setting, null otherwise
- public void WriteOptionalStandalone(string name, string value, bool? quoteOverride = null)
+ public void WriteOptionalStandalone(string name, string? value, bool? quoteOverride = null)
{
if (!string.IsNullOrEmpty(value))
WriteStandalone(name, value, quoteOverride);
@@ -362,7 +359,7 @@ namespace SabreTools.IO.Writers
///
/// Write a string content value
///
- public void WriteString(string value)
+ public void WriteString(string? value)
{
try
{
diff --git a/SabreTools.IO/Writers/IniWriter.cs b/SabreTools.IO/Writers/IniWriter.cs
index 26ad51e8..c36efe63 100644
--- a/SabreTools.IO/Writers/IniWriter.cs
+++ b/SabreTools.IO/Writers/IniWriter.cs
@@ -9,7 +9,7 @@ namespace SabreTools.IO.Writers
///
/// Internal stream writer for outputting
///
- private readonly StreamWriter sw;
+ private readonly StreamWriter? sw;
///
/// Constructor for writing to a file
@@ -30,8 +30,11 @@ namespace SabreTools.IO.Writers
///
/// Write a section tag
///
- public void WriteSection(string value)
+ public void WriteSection(string? value)
{
+ if (sw?.BaseStream == null)
+ return;
+
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("Section tag cannot be null or empty", nameof(value));
@@ -41,8 +44,11 @@ namespace SabreTools.IO.Writers
///
/// Write a key value pair
///
- public void WriteKeyValuePair(string key, string value)
+ public void WriteKeyValuePair(string key, string? value)
{
+ if (sw?.BaseStream == null)
+ return;
+
if (string.IsNullOrWhiteSpace(key))
throw new ArgumentException("Key cannot be null or empty", nameof(key));
@@ -53,8 +59,11 @@ namespace SabreTools.IO.Writers
///
/// Write a comment
///
- public void WriteComment(string value)
+ public void WriteComment(string? value)
{
+ if (sw?.BaseStream == null)
+ return;
+
value ??= string.Empty;
sw.WriteLine($";{value}");
}
@@ -62,8 +71,11 @@ namespace SabreTools.IO.Writers
///
/// Write a generic string
///
- public void WriteString(string value)
+ public void WriteString(string? value)
{
+ if (sw?.BaseStream == null)
+ return;
+
value ??= string.Empty;
sw.Write(value);
}
@@ -73,6 +85,9 @@ namespace SabreTools.IO.Writers
///
public void WriteLine()
{
+ if (sw?.BaseStream == null)
+ return;
+
sw.WriteLine();
}
@@ -81,7 +96,7 @@ namespace SabreTools.IO.Writers
///
public void Flush()
{
- sw.Flush();
+ sw?.Flush();
}
///
@@ -89,7 +104,7 @@ namespace SabreTools.IO.Writers
///
public void Dispose()
{
- sw.Dispose();
+ sw?.Dispose();
}
}
}
diff --git a/SabreTools.IO/Writers/SeparatedValueWriter.cs b/SabreTools.IO/Writers/SeparatedValueWriter.cs
index 9d3865c7..15e17237 100644
--- a/SabreTools.IO/Writers/SeparatedValueWriter.cs
+++ b/SabreTools.IO/Writers/SeparatedValueWriter.cs
@@ -60,7 +60,7 @@ namespace SabreTools.IO.Writers
///
/// Write a header row
///
- public void WriteHeader(string[] headers)
+ public void WriteHeader(string?[] headers)
{
// If we haven't written anything out, we can write headers
if (!header && !firstRow)
@@ -72,7 +72,7 @@ namespace SabreTools.IO.Writers
///
/// Write a value row
///
- public void WriteValues(object[] values, bool newline = true)
+ public void WriteValues(object?[] values, bool newline = true)
{
// If the writer can't be used, we error
if (sw == null || !sw.BaseStream.CanWrite)
diff --git a/SabreTools.Serialization/AttractMode.Deserializer.cs b/SabreTools.Serialization/AttractMode.Deserializer.cs
index ff314467..aa9f4ed6 100644
--- a/SabreTools.Serialization/AttractMode.Deserializer.cs
+++ b/SabreTools.Serialization/AttractMode.Deserializer.cs
@@ -44,7 +44,7 @@ namespace SabreTools.Serialization
var dat = new MetadataFile();
// Read the header values first
- if (!reader.ReadHeader())
+ if (!reader.ReadHeader() || reader.HeaderValues == null)
return null;
dat.Header = reader.HeaderValues.ToArray();
@@ -54,11 +54,11 @@ namespace SabreTools.Serialization
while (!reader.EndOfStream)
{
// If we have no next line
- if (!reader.ReadNextLine())
+ if (!reader.ReadNextLine() || reader.Line == null)
break;
// Parse the line into a row
- Row? row = null;
+ Row row;
if (reader.Line.Count < HeaderWithRomnameCount)
{
row = new Row
diff --git a/SabreTools.Serialization/ClrMamePro.Deserializer.cs b/SabreTools.Serialization/ClrMamePro.Deserializer.cs
index 01bcb9a5..9ec0a6e0 100644
--- a/SabreTools.Serialization/ClrMamePro.Deserializer.cs
+++ b/SabreTools.Serialization/ClrMamePro.Deserializer.cs
@@ -41,7 +41,7 @@ namespace SabreTools.Serialization
var dat = new MetadataFile();
// Loop through and parse out the values
- string lastTopLevel = reader.TopLevel;
+ string? lastTopLevel = reader.TopLevel;
GameBase? game = null;
var games = new List();
@@ -75,27 +75,32 @@ namespace SabreTools.Serialization
switch (lastTopLevel)
{
case "doscenter":
- dat.ClrMamePro!.ADDITIONAL_ELEMENTS = headerAdditional.ToArray();
+ if (dat.ClrMamePro != null)
+ 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.Video = videos.ToArray();
- game.DipSwitch = dipSwitches.ToArray();
- game.ADDITIONAL_ELEMENTS = gameAdditional.ToArray();
+ if (game != null)
+ {
+ 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.Video = videos.ToArray();
+ game.DipSwitch = dipSwitches.ToArray();
+ game.ADDITIONAL_ELEMENTS = gameAdditional.ToArray();
- games.Add(game);
- game = null;
+ games.Add(game);
+ game = null;
+ }
releases.Clear();
biosSets.Clear();
@@ -138,7 +143,8 @@ namespace SabreTools.Serialization
game = new Set();
break;
default:
- additional.Add(reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ additional.Add(reader.CurrentLine);
break;
}
}
@@ -198,7 +204,8 @@ namespace SabreTools.Serialization
dat.ClrMamePro.ForcePacking = reader.Standalone?.Value;
break;
default:
- headerAdditional.Add(reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ headerAdditional.Add(reader.CurrentLine);
break;
}
}
@@ -255,7 +262,8 @@ namespace SabreTools.Serialization
samples.Add(sample);
break;
default:
- gameAdditional.Add(reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ gameAdditional.Add(reader.CurrentLine);
break;
}
}
@@ -272,53 +280,81 @@ namespace SabreTools.Serialization
switch (reader.InternalName)
{
case "release":
- releases.Add(CreateRelease(reader));
+ var release = CreateRelease(reader);
+ if (release != null)
+ releases.Add(release);
break;
case "biosset":
- biosSets.Add(CreateBiosSet(reader));
+ var biosSet = CreateBiosSet(reader);
+ if (biosSet != null)
+ biosSets.Add(biosSet);
break;
case "rom":
- roms.Add(CreateRom(reader));
+ var rom = CreateRom(reader);
+ if (rom != null)
+ roms.Add(rom);
break;
case "disk":
- disks.Add(CreateDisk(reader));
+ var disk = CreateDisk(reader);
+ if (disk != null)
+ disks.Add(disk);
break;
case "media":
- medias.Add(CreateMedia(reader));
+ var media = CreateMedia(reader);
+ if (media != null)
+ medias.Add(media);
break;
case "sample":
- samples.Add(CreateSample(reader));
+ var sample = CreateSample(reader);
+ if (sample != null)
+ samples.Add(sample);
break;
case "archive":
- archives.Add(CreateArchive(reader));
+ var archive = CreateArchive(reader);
+ if (archive != null)
+ archives.Add(archive);
break;
case "chip":
- chips.Add(CreateChip(reader));
+ var chip = CreateChip(reader);
+ if (chip != null)
+ chips.Add(chip);
break;
case "video":
- videos.Add(CreateVideo(reader));
+ var video = CreateVideo(reader);
+ if (video != null)
+ videos.Add(video);
break;
case "sound":
- game.Sound = CreateSound(reader);
+ var sound = CreateSound(reader);
+ if (sound != null)
+ game.Sound = sound;
break;
case "input":
- game.Input = CreateInput(reader);
+ var input = CreateInput(reader);
+ if (input != null)
+ game.Input = input;
break;
case "dipswitch":
- dipSwitches.Add(CreateDipSwitch(reader));
+ var dipSwitch = CreateDipSwitch(reader);
+ if (dipSwitch != null)
+ dipSwitches.Add(dipSwitch);
break;
case "driver":
- game.Driver = CreateDriver(reader);
+ var driver = CreateDriver(reader);
+ if (driver != null)
+ game.Driver = driver;
break;
default:
- gameAdditional.Add(reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ gameAdditional.Add(reader.CurrentLine);
continue;
}
}
else
{
- additional.Add(reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ additional.Add(reader.CurrentLine);
}
}
@@ -333,8 +369,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// Release object created from the reader context
- private static Release CreateRelease(ClrMameProReader reader)
+ private static Release? CreateRelease(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var release = new Release();
foreach (var kvp in reader.Internal)
@@ -371,8 +410,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// BiosSet object created from the reader context
- private static BiosSet CreateBiosSet(ClrMameProReader reader)
+ private static BiosSet? CreateBiosSet(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var biosset = new BiosSet();
foreach (var kvp in reader.Internal)
@@ -403,8 +445,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// Rom object created from the reader context
- private static Rom CreateRom(ClrMameProReader reader)
+ private static Rom? CreateRom(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var rom = new Rom();
foreach (var kvp in reader.Internal)
@@ -489,8 +534,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// Disk object created from the reader context
- private static Disk CreateDisk(ClrMameProReader reader)
+ private static Disk? CreateDisk(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var disk = new Disk();
foreach (var kvp in reader.Internal)
@@ -530,8 +578,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// Media object created from the reader context
- private static Media CreateMedia(ClrMameProReader reader)
+ private static Media? CreateMedia(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var media = new Media();
foreach (var kvp in reader.Internal)
@@ -568,8 +619,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// Sample object created from the reader context
- private static Sample CreateSample(ClrMameProReader reader)
+ private static Sample? CreateSample(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var sample = new Sample();
foreach (var kvp in reader.Internal)
@@ -594,8 +648,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// Archive object created from the reader context
- private static Archive CreateArchive(ClrMameProReader reader)
+ private static Archive? CreateArchive(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var archive = new Archive();
foreach (var kvp in reader.Internal)
@@ -620,8 +677,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// Chip object created from the reader context
- private static Chip CreateChip(ClrMameProReader reader)
+ private static Chip? CreateChip(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var chip = new Chip();
foreach (var kvp in reader.Internal)
@@ -655,8 +715,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// Video object created from the reader context
- private static Video CreateVideo(ClrMameProReader reader)
+ private static Video? CreateVideo(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var video = new Video();
foreach (var kvp in reader.Internal)
@@ -699,8 +762,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// Sound object created from the reader context
- private static Sound CreateSound(ClrMameProReader reader)
+ private static Sound? CreateSound(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var sound = new Sound();
foreach (var kvp in reader.Internal)
@@ -725,8 +791,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// Input object created from the reader context
- private static Input CreateInput(ClrMameProReader reader)
+ private static Input? CreateInput(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var input = new Input();
foreach (var kvp in reader.Internal)
@@ -766,8 +835,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// DipSwitch object created from the reader context
- private static DipSwitch CreateDipSwitch(ClrMameProReader reader)
+ private static DipSwitch? CreateDipSwitch(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var dipswitch = new DipSwitch();
var entries = new List();
@@ -800,8 +872,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// Driver object created from the reader context
- private static Driver CreateDriver(ClrMameProReader reader)
+ private static Driver? CreateDriver(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var driver = new Driver();
foreach (var kvp in reader.Internal)
@@ -832,7 +907,7 @@ namespace SabreTools.Serialization
driver.ADDITIONAL_ELEMENTS = itemAdditional.ToArray();
return driver;
}
-
+
#region Internal
///
@@ -842,7 +917,7 @@ namespace SabreTools.Serialization
{
if (item == null)
return null;
-
+
var metadataFile = new MetadataFile();
var header = item.Read(Models.Internal.MetadataFile.HeaderKey);
diff --git a/SabreTools.Serialization/DosCenter.Deserializer.cs b/SabreTools.Serialization/DosCenter.Deserializer.cs
index 0ec52199..a271cf0a 100644
--- a/SabreTools.Serialization/DosCenter.Deserializer.cs
+++ b/SabreTools.Serialization/DosCenter.Deserializer.cs
@@ -39,7 +39,7 @@ namespace SabreTools.Serialization
var dat = new MetadataFile();
// Loop through and parse out the values
- string lastTopLevel = reader.TopLevel;
+ string? lastTopLevel = reader.TopLevel;
Game? game = null;
var games = new List();
@@ -48,7 +48,6 @@ namespace SabreTools.Serialization
var additional = new List();
var headerAdditional = new List();
var gameAdditional = new List();
- var fileAdditional = new List();
while (!reader.EndOfStream)
{
// If we have no next line
@@ -102,7 +101,8 @@ namespace SabreTools.Serialization
game = new Game();
break;
default:
- additional.Add(reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ additional.Add(reader.CurrentLine);
break;
}
}
@@ -137,7 +137,8 @@ namespace SabreTools.Serialization
dat.DosCenter.Comment = reader.Standalone?.Value;
break;
default:
- headerAdditional.Add(item: reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ headerAdditional.Add(item: reader.CurrentLine);
break;
}
}
@@ -154,7 +155,8 @@ namespace SabreTools.Serialization
game.Name = reader.Standalone?.Value;
break;
default:
- gameAdditional.Add(item: reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ gameAdditional.Add(item: reader.CurrentLine);
break;
}
}
@@ -165,18 +167,21 @@ namespace SabreTools.Serialization
// If we have an unknown type, log it
if (reader.InternalName != "file")
{
- gameAdditional.Add(reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ gameAdditional.Add(reader.CurrentLine);
continue;
}
// Create the file and add to the list
var file = CreateFile(reader);
- files.Add(file);
+ if (file != null)
+ files.Add(file);
}
else
{
- additional.Add(item: reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ additional.Add(item: reader.CurrentLine);
}
}
@@ -191,8 +196,11 @@ namespace SabreTools.Serialization
///
/// ClrMameProReader representing the metadata file
/// File object created from the reader context
- private static Models.DosCenter.File CreateFile(ClrMameProReader reader)
+ private static Models.DosCenter.File? CreateFile(ClrMameProReader reader)
{
+ if (reader.Internal == null)
+ return null;
+
var itemAdditional = new List();
var file = new Models.DosCenter.File();
foreach (var kvp in reader.Internal)
@@ -212,7 +220,8 @@ namespace SabreTools.Serialization
file.Date = kvp.Value;
break;
default:
- itemAdditional.Add(item: reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ itemAdditional.Add(item: reader.CurrentLine);
break;
}
}
diff --git a/SabreTools.Serialization/DosCenter.Serializer.cs b/SabreTools.Serialization/DosCenter.Serializer.cs
index 1c350448..2c4b34d9 100644
--- a/SabreTools.Serialization/DosCenter.Serializer.cs
+++ b/SabreTools.Serialization/DosCenter.Serializer.cs
@@ -140,7 +140,7 @@ namespace SabreTools.Serialization
writer.WriteRequiredAttributeString("name", file.Name, throwOnError: true);
writer.WriteRequiredAttributeString("size", file.Size, throwOnError: true);
writer.WriteOptionalAttributeString("date", file.Date);
- writer.WriteRequiredAttributeString("crc", file.CRC.ToUpperInvariant(), throwOnError: true);
+ writer.WriteRequiredAttributeString("crc", file.CRC?.ToUpperInvariant(), throwOnError: true);
writer.WriteEndElement(); // file
}
diff --git a/SabreTools.Serialization/EverdriveSMDB.Deserializer.cs b/SabreTools.Serialization/EverdriveSMDB.Deserializer.cs
index ded27de8..d52a695c 100644
--- a/SabreTools.Serialization/EverdriveSMDB.Deserializer.cs
+++ b/SabreTools.Serialization/EverdriveSMDB.Deserializer.cs
@@ -49,7 +49,7 @@ namespace SabreTools.Serialization
while (!reader.EndOfStream)
{
// If we have no next line
- if (!reader.ReadNextLine())
+ if (!reader.ReadNextLine() || reader.Line == null)
break;
// Parse the line into a row
diff --git a/SabreTools.Serialization/EverdriveSMDB.Serializer.cs b/SabreTools.Serialization/EverdriveSMDB.Serializer.cs
index c45f6ec8..3c8e3973 100644
--- a/SabreTools.Serialization/EverdriveSMDB.Serializer.cs
+++ b/SabreTools.Serialization/EverdriveSMDB.Serializer.cs
@@ -66,7 +66,10 @@ namespace SabreTools.Serialization
// Loop through and write out the rows
foreach (var row in rows)
{
- var rowArray = new List
+ if (row == null)
+ continue;
+
+ var rowArray = new List
{
row.SHA256,
row.Name,
diff --git a/SabreTools.Serialization/Hashfile.Serializer.cs b/SabreTools.Serialization/Hashfile.Serializer.cs
index d314d7c1..24c06636 100644
--- a/SabreTools.Serialization/Hashfile.Serializer.cs
+++ b/SabreTools.Serialization/Hashfile.Serializer.cs
@@ -99,6 +99,11 @@ namespace SabreTools.Serialization
// Loop through and write out the items
foreach (var sfv in sfvs)
{
+ if (sfv == null)
+ continue;
+ if (string.IsNullOrWhiteSpace(sfv.File) || string.IsNullOrWhiteSpace(sfv.Hash))
+ continue;
+
writer.WriteValues(new string[] { sfv.File, sfv.Hash });
writer.Flush();
}
@@ -118,6 +123,11 @@ namespace SabreTools.Serialization
// Loop through and write out the items
foreach (var md5 in md5s)
{
+ if (md5 == null)
+ continue;
+ if (string.IsNullOrWhiteSpace(md5.Hash) || string.IsNullOrWhiteSpace(md5.File))
+ continue;
+
writer.WriteValues(new string[] { md5.Hash, md5.File });
writer.Flush();
}
@@ -137,6 +147,11 @@ namespace SabreTools.Serialization
// Loop through and write out the items
foreach (var sha1 in sha1s)
{
+ if (sha1 == null)
+ continue;
+ if (string.IsNullOrWhiteSpace(sha1.Hash) || string.IsNullOrWhiteSpace(sha1.File))
+ continue;
+
writer.WriteValues(new string[] { sha1.Hash, sha1.File });
writer.Flush();
}
@@ -156,6 +171,11 @@ namespace SabreTools.Serialization
// Loop through and write out the items
foreach (var sha256 in sha256s)
{
+ if (sha256 == null)
+ continue;
+ if (string.IsNullOrWhiteSpace(sha256.Hash) || string.IsNullOrWhiteSpace(sha256.File))
+ continue;
+
writer.WriteValues(new string[] { sha256.Hash, sha256.File });
writer.Flush();
}
@@ -175,6 +195,11 @@ namespace SabreTools.Serialization
// Loop through and write out the items
foreach (var sha384 in sha384s)
{
+ if (sha384 == null)
+ continue;
+ if (string.IsNullOrWhiteSpace(sha384.Hash) || string.IsNullOrWhiteSpace(sha384.File))
+ continue;
+
writer.WriteValues(new string[] { sha384.Hash, sha384.File });
writer.Flush();
}
@@ -194,6 +219,11 @@ namespace SabreTools.Serialization
// Loop through and write out the items
foreach (var sha512 in sha512s)
{
+ if (sha512 == null)
+ continue;
+ if (string.IsNullOrWhiteSpace(sha512.Hash) || string.IsNullOrWhiteSpace(sha512.File))
+ continue;
+
writer.WriteValues(new string[] { sha512.Hash, sha512.File });
writer.Flush();
}
@@ -213,6 +243,11 @@ namespace SabreTools.Serialization
// Loop through and write out the items
foreach (var spamsum in spamsums)
{
+ if (spamsum == null)
+ continue;
+ if (string.IsNullOrWhiteSpace(spamsum.Hash) || string.IsNullOrWhiteSpace(spamsum.File))
+ continue;
+
writer.WriteValues(new string[] { spamsum.Hash, spamsum.File });
writer.Flush();
}
diff --git a/SabreTools.Serialization/Listrom.Serializer.cs b/SabreTools.Serialization/Listrom.Serializer.cs
index 5a34b62a..4d45a861 100644
--- a/SabreTools.Serialization/Listrom.Serializer.cs
+++ b/SabreTools.Serialization/Listrom.Serializer.cs
@@ -136,6 +136,9 @@ namespace SabreTools.Serialization
foreach (var row in rows)
{
+ if (string.IsNullOrWhiteSpace(row.Name))
+ continue;
+
var rowBuilder = new StringBuilder();
int padding = 40 - (row.Size?.Length ?? 0);
diff --git a/SabreTools.Serialization/RomCenter.Deserializer.cs b/SabreTools.Serialization/RomCenter.Deserializer.cs
index 6342ca64..bdc9ce62 100644
--- a/SabreTools.Serialization/RomCenter.Deserializer.cs
+++ b/SabreTools.Serialization/RomCenter.Deserializer.cs
@@ -62,7 +62,7 @@ namespace SabreTools.Serialization
case IniRowType.Comment:
continue;
case IniRowType.SectionHeader:
- switch (reader.Section.ToLowerInvariant())
+ switch (reader.Section?.ToLowerInvariant())
{
case "credits":
dat.Credits ??= new Credits();
@@ -77,14 +77,15 @@ namespace SabreTools.Serialization
dat.Games ??= new Games();
break;
default:
- additional.Add(reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ additional.Add(reader.CurrentLine);
break;
}
continue;
}
// If we're in credits
- if (reader.Section.ToLowerInvariant() == "credits")
+ if (reader.Section?.ToLowerInvariant() == "credits")
{
// Create the section if we haven't already
dat.Credits ??= new Credits();
@@ -113,13 +114,14 @@ namespace SabreTools.Serialization
dat.Credits.Comment = reader.KeyValuePair?.Value;
break;
default:
- creditsAdditional.Add(reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ creditsAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in dat
- else if (reader.Section.ToLowerInvariant() == "dat")
+ else if (reader.Section?.ToLowerInvariant() == "dat")
{
// Create the section if we haven't already
dat.Dat ??= new Dat();
@@ -139,13 +141,14 @@ namespace SabreTools.Serialization
dat.Dat.Merge = reader.KeyValuePair?.Value;
break;
default:
- datAdditional.Add(reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ datAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in emulator
- else if (reader.Section.ToLowerInvariant() == "emulator")
+ else if (reader.Section?.ToLowerInvariant() == "emulator")
{
// Create the section if we haven't already
dat.Emulator ??= new Emulator();
@@ -159,21 +162,24 @@ namespace SabreTools.Serialization
dat.Emulator.Version = reader.KeyValuePair?.Value;
break;
default:
- emulatorAdditional.Add(reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ emulatorAdditional.Add(reader.CurrentLine);
break;
}
}
// If we're in games
- else if (reader.Section.ToLowerInvariant() == "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('¬'))
+ if (!(reader.CurrentLine?.Contains('¬') ?? false))
{
- gamesAdditional.Add(reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ gamesAdditional.Add(reader.CurrentLine);
+
continue;
}
@@ -202,22 +208,23 @@ namespace SabreTools.Serialization
else
{
- additional.Add(item: reader.CurrentLine);
+ if (reader.CurrentLine != null)
+ additional.Add(reader.CurrentLine);
}
}
// Add extra pieces and return
- dat.ADDITIONAL_ELEMENTS = additional.ToArray();
+ dat.ADDITIONAL_ELEMENTS = additional.Where(s => s != null).ToArray();
if (dat.Credits != null)
- dat.Credits.ADDITIONAL_ELEMENTS = creditsAdditional.ToArray();
+ dat.Credits.ADDITIONAL_ELEMENTS = creditsAdditional.Where(s => s != null).ToArray();
if (dat.Dat != null)
- dat.Dat.ADDITIONAL_ELEMENTS = datAdditional.ToArray();
+ dat.Dat.ADDITIONAL_ELEMENTS = datAdditional.Where(s => s != null).ToArray();
if (dat.Emulator != null)
- dat.Emulator.ADDITIONAL_ELEMENTS = emulatorAdditional.ToArray();
+ dat.Emulator.ADDITIONAL_ELEMENTS = emulatorAdditional.Where(s => s != null).ToArray();
if (dat.Games != null)
{
dat.Games.Rom = roms.ToArray();
- dat.Games.ADDITIONAL_ELEMENTS = gamesAdditional.ToArray();
+ dat.Games.ADDITIONAL_ELEMENTS = gamesAdditional.Where(s => s != null).Select(s => s).ToArray();
}
return dat;
}
diff --git a/SabreTools.Serialization/SeparatedValue.Deserializer.cs b/SabreTools.Serialization/SeparatedValue.Deserializer.cs
index 94fe1b88..70e8638f 100644
--- a/SabreTools.Serialization/SeparatedValue.Deserializer.cs
+++ b/SabreTools.Serialization/SeparatedValue.Deserializer.cs
@@ -46,7 +46,7 @@ namespace SabreTools.Serialization
var dat = new MetadataFile();
// Read the header values first
- if (!reader.ReadHeader())
+ if (!reader.ReadHeader() || reader.HeaderValues == null)
return null;
dat.Header = reader.HeaderValues.ToArray();
@@ -56,7 +56,7 @@ namespace SabreTools.Serialization
while (!reader.EndOfStream)
{
// If we have no next line
- if (!reader.ReadNextLine())
+ if (!reader.ReadNextLine() || reader.Line == null)
break;
// Parse the line into a row
diff --git a/SabreTools.Test/Serialization/DeserializationTests.cs b/SabreTools.Test/Serialization/DeserializationTests.cs
index d0823f47..491184a5 100644
--- a/SabreTools.Test/Serialization/DeserializationTests.cs
+++ b/SabreTools.Test/Serialization/DeserializationTests.cs
@@ -127,9 +127,9 @@ namespace SabreTools.Test.Parser
Assert.Empty(chip.ADDITIONAL_ELEMENTS);
}
- if (game.Video != null)
+ foreach (var video in game.Video ?? Array.Empty())
{
- Assert.Empty(game.Video.ADDITIONAL_ELEMENTS);
+ Assert.Empty(video.ADDITIONAL_ELEMENTS);
}
if (game.Sound != null)