mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Fix ParentablePath issues; fix parse logging
This commit is contained in:
@@ -59,53 +59,57 @@ namespace SabreTools.Library.DatFiles
|
||||
{
|
||||
// Get the current line, split and parse
|
||||
svr.ReadNextLine();
|
||||
}
|
||||
catch (InvalidDataException ex)
|
||||
{
|
||||
Globals.Logger.Error(ex, $"Malformed line found in '{filename}' at line {svr.LineNumber}");
|
||||
if (throwOnError) throw ex;
|
||||
continue;
|
||||
}
|
||||
|
||||
Rom rom = new Rom
|
||||
{
|
||||
Name = "-",
|
||||
Size = Constants.SizeZero,
|
||||
CRC = Constants.CRCZero,
|
||||
MD5 = Constants.MD5Zero,
|
||||
SHA1 = Constants.SHA1Zero,
|
||||
ItemStatus = ItemStatus.None,
|
||||
|
||||
Machine = new Machine
|
||||
Rom rom = new Rom
|
||||
{
|
||||
Name = svr.Line[0], // #Name
|
||||
Description = svr.Line[1], // Title
|
||||
CloneOf = svr.Line[3], // CloneOf
|
||||
Year = svr.Line[4], // Year
|
||||
Manufacturer = svr.Line[5], // Manufacturer
|
||||
Category = svr.Line[6], // Category
|
||||
Players = svr.Line[7], // Players
|
||||
Rotation = svr.Line[8], // Rotation
|
||||
Control = svr.Line[9], // Control
|
||||
Status = svr.Line[10], // Status
|
||||
DisplayCount = svr.Line[11], // DisplayCount
|
||||
DisplayType = svr.Line[12], // DisplayType
|
||||
Comment = svr.Line[15], // Extra
|
||||
Buttons = svr.Line[16], // Buttons
|
||||
},
|
||||
Name = "-",
|
||||
Size = Constants.SizeZero,
|
||||
CRC = Constants.CRCZero,
|
||||
MD5 = Constants.MD5Zero,
|
||||
SHA1 = Constants.SHA1Zero,
|
||||
ItemStatus = ItemStatus.None,
|
||||
|
||||
AltName = svr.Line[13], // AltRomname
|
||||
AltTitle = svr.Line[14], // AltTitle
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = svr.Line[0], // #Name
|
||||
Description = svr.Line[1], // Title
|
||||
CloneOf = svr.Line[3], // CloneOf
|
||||
Year = svr.Line[4], // Year
|
||||
Manufacturer = svr.Line[5], // Manufacturer
|
||||
Category = svr.Line[6], // Category
|
||||
Players = svr.Line[7], // Players
|
||||
Rotation = svr.Line[8], // Rotation
|
||||
Control = svr.Line[9], // Control
|
||||
Status = svr.Line[10], // Status
|
||||
DisplayCount = svr.Line[11], // DisplayCount
|
||||
DisplayType = svr.Line[12], // DisplayType
|
||||
Comment = svr.Line[15], // Extra
|
||||
Buttons = svr.Line[16], // Buttons
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
AltName = svr.Line[13], // AltRomname
|
||||
AltTitle = svr.Line[14], // AltTitle
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
// Now process and add the rom
|
||||
ParseAddHelper(rom);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string message = $"'{filename}' - There was an error parsing line {svr.LineNumber} '{svr.CurrentLine}'";
|
||||
Globals.Logger.Error(ex, message);
|
||||
if (throwOnError)
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
// Now process and add the rom
|
||||
ParseAddHelper(rom);
|
||||
svr.Dispose();
|
||||
throw new Exception(message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
svr.Dispose();
|
||||
|
||||
@@ -54,33 +54,46 @@ namespace SabreTools.Library.DatFiles
|
||||
|
||||
while (!cmpr.EndOfStream)
|
||||
{
|
||||
cmpr.ReadNextLine();
|
||||
|
||||
// Ignore everything not top-level
|
||||
if (cmpr.RowType != CmpRowType.TopLevel)
|
||||
continue;
|
||||
|
||||
// Switch on the top-level name
|
||||
switch (cmpr.TopLevel.ToLowerInvariant())
|
||||
try
|
||||
{
|
||||
// Header values
|
||||
case "clrmamepro":
|
||||
case "romvault":
|
||||
ReadHeader(cmpr, keep);
|
||||
break;
|
||||
cmpr.ReadNextLine();
|
||||
|
||||
// Sets
|
||||
case "set": // Used by the most ancient DATs
|
||||
case "game": // Used by most CMP DATs
|
||||
case "machine": // Possibly used by MAME CMP DATs
|
||||
ReadSet(cmpr, false, filename, indexId);
|
||||
break;
|
||||
case "resource": // Used by some other DATs to denote a BIOS set
|
||||
ReadSet(cmpr, true, filename, indexId);
|
||||
break;
|
||||
// Ignore everything not top-level
|
||||
if (cmpr.RowType != CmpRowType.TopLevel)
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
// Switch on the top-level name
|
||||
switch (cmpr.TopLevel.ToLowerInvariant())
|
||||
{
|
||||
// Header values
|
||||
case "clrmamepro":
|
||||
case "romvault":
|
||||
ReadHeader(cmpr, keep);
|
||||
break;
|
||||
|
||||
// Sets
|
||||
case "set": // Used by the most ancient DATs
|
||||
case "game": // Used by most CMP DATs
|
||||
case "machine": // Possibly used by MAME CMP DATs
|
||||
ReadSet(cmpr, false, filename, indexId);
|
||||
break;
|
||||
case "resource": // Used by some other DATs to denote a BIOS set
|
||||
ReadSet(cmpr, true, filename, indexId);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string message = $"'{filename}' - There was an error parsing line {cmpr.LineNumber} '{cmpr.CurrentLine}'";
|
||||
Globals.Logger.Error(ex, message);
|
||||
if (throwOnError)
|
||||
{
|
||||
cmpr.Dispose();
|
||||
throw new Exception(message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1802,10 +1802,11 @@ namespace SabreTools.Library.DatFiles
|
||||
/// Create a DatFile and parse a file into it
|
||||
/// </summary>
|
||||
/// <param name="filename">Name of the file to be parsed</param>
|
||||
public static DatFile CreateAndParse(string filename)
|
||||
/// <param name="throwOnError">True if the error that is thrown should be thrown back to the caller, false otherwise</param>
|
||||
public static DatFile CreateAndParse(string filename, bool throwOnError = false)
|
||||
{
|
||||
DatFile datFile = Create();
|
||||
datFile.Parse(new ParentablePath(filename));
|
||||
datFile.Parse(new ParentablePath(filename), throwOnError: throwOnError);
|
||||
return datFile;
|
||||
}
|
||||
|
||||
@@ -1833,22 +1834,22 @@ namespace SabreTools.Library.DatFiles
|
||||
/// <summary>
|
||||
/// Parse a DAT and return all found games and roms within
|
||||
/// </summary>
|
||||
/// <param name="filename">Name of the file to be parsed</param>
|
||||
/// <param name="input">Name of the file to be parsed</param>
|
||||
/// <param name="indexId">Index ID for the DAT</param>
|
||||
/// <param name="keep">True if full pathnames are to be kept, false otherwise (default)</param>
|
||||
/// <param name="keepext">True if original extension should be kept, false otherwise (default)</param>
|
||||
/// <param name="quotes">True if quotes are assumed in supported types (default), false otherwise</param>
|
||||
/// <param name="throwOnError">True if the error that is thrown should be thrown back to the caller, false otherwise</param>
|
||||
public void Parse(
|
||||
ParentablePath filename,
|
||||
ParentablePath input,
|
||||
int indexId = 0,
|
||||
bool keep = false,
|
||||
bool keepext = false,
|
||||
bool quotes = true,
|
||||
bool throwOnError = false)
|
||||
bool throwOnError = true)
|
||||
{
|
||||
// Get the current path from the filename
|
||||
string currentPath = filename.CurrentPath;
|
||||
string currentPath = input.CurrentPath;
|
||||
|
||||
// Check the file extension first as a safeguard
|
||||
if (!PathExtensions.HasValidDatExtension(currentPath))
|
||||
@@ -1868,7 +1869,7 @@ namespace SabreTools.Library.DatFiles
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Globals.Logger.Error(ex, $"Error with file '{filename}'");
|
||||
Globals.Logger.Error(ex, $"Error with file '{currentPath}'");
|
||||
if (throwOnError) throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,27 +43,40 @@ namespace SabreTools.Library.DatFiles
|
||||
|
||||
while (!cmpr.EndOfStream)
|
||||
{
|
||||
cmpr.ReadNextLine();
|
||||
|
||||
// Ignore everything not top-level
|
||||
if (cmpr.RowType != CmpRowType.TopLevel)
|
||||
continue;
|
||||
|
||||
// Switch on the top-level name
|
||||
switch (cmpr.TopLevel.ToLowerInvariant())
|
||||
try
|
||||
{
|
||||
// Header values
|
||||
case "doscenter":
|
||||
ReadHeader(cmpr);
|
||||
break;
|
||||
cmpr.ReadNextLine();
|
||||
|
||||
// Sets
|
||||
case "game":
|
||||
ReadGame(cmpr, filename, indexId);
|
||||
break;
|
||||
// Ignore everything not top-level
|
||||
if (cmpr.RowType != CmpRowType.TopLevel)
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
// Switch on the top-level name
|
||||
switch (cmpr.TopLevel.ToLowerInvariant())
|
||||
{
|
||||
// Header values
|
||||
case "doscenter":
|
||||
ReadHeader(cmpr);
|
||||
break;
|
||||
|
||||
// Sets
|
||||
case "game":
|
||||
ReadGame(cmpr, filename, indexId);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string message = $"'{filename}' - There was an error parsing line {cmpr.LineNumber} '{cmpr.CurrentLine}'";
|
||||
Globals.Logger.Error(ex, message);
|
||||
if (throwOnError)
|
||||
{
|
||||
cmpr.Dispose();
|
||||
throw new Exception(message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,51 +33,65 @@ namespace SabreTools.Library.DatFiles
|
||||
/// <param name="throwOnError">True if the error that is thrown should be thrown back to the caller, false otherwise</param>
|
||||
protected override void ParseFile(string filename, int indexId, bool keep, bool throwOnError = false)
|
||||
{
|
||||
// TODO: Use SeparatedValueReader
|
||||
// Open a file reader
|
||||
Encoding enc = FileExtensions.GetEncoding(filename);
|
||||
StreamReader sr = new StreamReader(FileExtensions.TryOpenRead(filename), enc);
|
||||
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine();
|
||||
|
||||
/*
|
||||
The gameinfo order is as follows
|
||||
0 - SHA-256
|
||||
1 - Machine Name/Filename
|
||||
2 - SHA-1
|
||||
3 - MD5
|
||||
4 - CRC32
|
||||
*/
|
||||
|
||||
string[] gameinfo = line.Split('\t');
|
||||
string[] fullname = gameinfo[1].Split('/');
|
||||
|
||||
Rom rom = new Rom
|
||||
try
|
||||
{
|
||||
Name = gameinfo[1].Substring(fullname[0].Length + 1),
|
||||
Size = null, // No size provided, but we don't want the size being 0
|
||||
CRC = gameinfo[4],
|
||||
MD5 = gameinfo[3],
|
||||
SHA1 = gameinfo[2],
|
||||
SHA256 = gameinfo[0],
|
||||
ItemStatus = ItemStatus.None,
|
||||
string line = sr.ReadLine();
|
||||
|
||||
Machine = new Machine
|
||||
/*
|
||||
The gameinfo order is as follows
|
||||
0 - SHA-256
|
||||
1 - Machine Name/Filename
|
||||
2 - SHA-1
|
||||
3 - MD5
|
||||
4 - CRC32
|
||||
*/
|
||||
|
||||
string[] gameinfo = line.Split('\t');
|
||||
string[] fullname = gameinfo[1].Split('/');
|
||||
|
||||
Rom rom = new Rom
|
||||
{
|
||||
Name = fullname[0],
|
||||
Description = fullname[0],
|
||||
},
|
||||
Name = gameinfo[1].Substring(fullname[0].Length + 1),
|
||||
Size = null, // No size provided, but we don't want the size being 0
|
||||
CRC = gameinfo[4],
|
||||
MD5 = gameinfo[3],
|
||||
SHA1 = gameinfo[2],
|
||||
SHA256 = gameinfo[0],
|
||||
ItemStatus = ItemStatus.None,
|
||||
|
||||
Source = new Source
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = fullname[0],
|
||||
Description = fullname[0],
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
// Now process and add the rom
|
||||
ParseAddHelper(rom);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string message = $"'{filename}' - There was an error parsing at position {sr.BaseStream.Position}";
|
||||
Globals.Logger.Error(ex, message);
|
||||
if (throwOnError)
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
// Now process and add the rom
|
||||
ParseAddHelper(rom);
|
||||
sr.Dispose();
|
||||
throw new Exception(message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sr.Dispose();
|
||||
|
||||
@@ -43,56 +43,69 @@ namespace SabreTools.Library.DatFiles
|
||||
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine();
|
||||
|
||||
// Split the line and get the name and hash
|
||||
string[] split = line.Split(' ');
|
||||
string name = string.Empty;
|
||||
string hash = string.Empty;
|
||||
|
||||
// If we have CRC, then it's an SFV file and the name is first are
|
||||
if (_hash.HasFlag(Hash.CRC))
|
||||
try
|
||||
{
|
||||
name = split[0].Replace("*", String.Empty);
|
||||
hash = split[1];
|
||||
}
|
||||
// Otherwise, the name is second
|
||||
else
|
||||
{
|
||||
name = split[1].Replace("*", String.Empty);
|
||||
hash = split[0];
|
||||
}
|
||||
string line = sr.ReadLine();
|
||||
|
||||
Rom rom = new Rom
|
||||
{
|
||||
Name = name,
|
||||
Size = null,
|
||||
CRC = (_hash.HasFlag(Hash.CRC) ? hash : null),
|
||||
MD5 = (_hash.HasFlag(Hash.MD5) ? hash : null),
|
||||
// Split the line and get the name and hash
|
||||
string[] split = line.Split(' ');
|
||||
string name = string.Empty;
|
||||
string hash = string.Empty;
|
||||
|
||||
// If we have CRC, then it's an SFV file and the name is first are
|
||||
if (_hash.HasFlag(Hash.CRC))
|
||||
{
|
||||
name = split[0].Replace("*", String.Empty);
|
||||
hash = split[1];
|
||||
}
|
||||
// Otherwise, the name is second
|
||||
else
|
||||
{
|
||||
name = split[1].Replace("*", String.Empty);
|
||||
hash = split[0];
|
||||
}
|
||||
|
||||
Rom rom = new Rom
|
||||
{
|
||||
Name = name,
|
||||
Size = null,
|
||||
CRC = (_hash.HasFlag(Hash.CRC) ? hash : null),
|
||||
MD5 = (_hash.HasFlag(Hash.MD5) ? hash : null),
|
||||
#if NET_FRAMEWORK
|
||||
RIPEMD160 = (_hash.HasFlag(Hash.RIPEMD160) ? hash : null),
|
||||
RIPEMD160 = (_hash.HasFlag(Hash.RIPEMD160) ? hash : null),
|
||||
#endif
|
||||
SHA1 = (_hash.HasFlag(Hash.SHA1) ? hash : null),
|
||||
SHA256 = (_hash.HasFlag(Hash.SHA256) ? hash : null),
|
||||
SHA384 = (_hash.HasFlag(Hash.SHA384) ? hash : null),
|
||||
SHA512 = (_hash.HasFlag(Hash.SHA512) ? hash : null),
|
||||
SpamSum = (_hash.HasFlag(Hash.SpamSum) ? hash : null),
|
||||
ItemStatus = ItemStatus.None,
|
||||
SHA1 = (_hash.HasFlag(Hash.SHA1) ? hash : null),
|
||||
SHA256 = (_hash.HasFlag(Hash.SHA256) ? hash : null),
|
||||
SHA384 = (_hash.HasFlag(Hash.SHA384) ? hash : null),
|
||||
SHA512 = (_hash.HasFlag(Hash.SHA512) ? hash : null),
|
||||
SpamSum = (_hash.HasFlag(Hash.SpamSum) ? hash : null),
|
||||
ItemStatus = ItemStatus.None,
|
||||
|
||||
Machine = new Machine
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = Path.GetFileNameWithoutExtension(filename),
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
// Now process and add the rom
|
||||
ParseAddHelper(rom);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string message = $"'{filename}' - There was an error parsing at position {sr.BaseStream.Position}";
|
||||
Globals.Logger.Error(ex, message);
|
||||
if (throwOnError)
|
||||
{
|
||||
Name = Path.GetFileNameWithoutExtension(filename),
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
// Now process and add the rom
|
||||
ParseAddHelper(rom);
|
||||
sr.Dispose();
|
||||
throw new Exception(message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sr.Dispose();
|
||||
|
||||
@@ -1410,13 +1410,13 @@ namespace SabreTools.Library.DatFiles
|
||||
dirStats.ResetStatistics();
|
||||
}
|
||||
|
||||
Globals.Logger.Verbose($"Beginning stat collection for '{file}'", false);
|
||||
Globals.Logger.Verbose($"Beginning stat collection for '{file.CurrentPath}'", false);
|
||||
List<string> games = new List<string>();
|
||||
DatFile datdata = DatFile.CreateAndParse(file.CurrentPath);
|
||||
datdata.Items.BucketBy(Field.Machine_Name, DedupeType.None, norename: true);
|
||||
|
||||
// Output single DAT stats (if asked)
|
||||
Globals.Logger.User($"Adding stats for file '{file}'\n", false);
|
||||
Globals.Logger.User($"Adding stats for file '{file.CurrentPath}'\n", false);
|
||||
if (single)
|
||||
{
|
||||
reports.ForEach(report => report.ReplaceStatistics(datdata.Header.FileName, datdata.Items.Keys.Count, datdata.Items));
|
||||
|
||||
@@ -50,201 +50,214 @@ namespace SabreTools.Library.DatFiles
|
||||
string gamename = string.Empty;
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine().Trim();
|
||||
|
||||
// If we have a blank line, we just skip it
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
try
|
||||
{
|
||||
continue;
|
||||
}
|
||||
string line = sr.ReadLine().Trim();
|
||||
|
||||
// If we have the descriptor line, ignore it
|
||||
else if (line == "Name Size Checksum")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we have the beginning of a game, set the name of the game
|
||||
else if (line.StartsWith("ROMs required for"))
|
||||
{
|
||||
gamename = Regex.Match(line, @"^ROMs required for \S*? string.Empty(.*?)string.Empty\.").Groups[1].Value;
|
||||
}
|
||||
|
||||
// If we have a machine with no required roms (usually internal devices), skip it
|
||||
else if (line.StartsWith("No ROMs required for"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, we assume we have a rom that we need to add
|
||||
else
|
||||
{
|
||||
// First, we preprocess the line so that the rom name is consistently correct
|
||||
string[] split = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// If the line doesn't have the 4 spaces of padding, check for 3
|
||||
if (split.Length == 1)
|
||||
split = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// If the split is still unsuccessful, log it and skip
|
||||
if (split.Length == 1)
|
||||
Globals.Logger.Warning($"Possibly malformed line: '{line}'");
|
||||
|
||||
string romname = split[0];
|
||||
line = line.Substring(romname.Length);
|
||||
|
||||
// Next we separate the ROM into pieces
|
||||
split = line.Split(new char[0], StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// Standard Disks have 2 pieces (name, sha1)
|
||||
if (split.Length == 1)
|
||||
// If we have a blank line, we just skip it
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
Disk disk = new Disk()
|
||||
{
|
||||
Name = romname,
|
||||
SHA1 = Sanitizer.CleanListromHashData(split[0]),
|
||||
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = gamename,
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
ParseAddHelper(disk);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Baddump Disks have 4 pieces (name, BAD, sha1, BAD_DUMP)
|
||||
else if (split.Length == 3 && line.EndsWith("BAD_DUMP"))
|
||||
// If we have the descriptor line, ignore it
|
||||
else if (line == "Name Size Checksum")
|
||||
{
|
||||
Disk disk = new Disk()
|
||||
{
|
||||
Name = romname,
|
||||
SHA1 = Sanitizer.CleanListromHashData(split[1]),
|
||||
ItemStatus = ItemStatus.BadDump,
|
||||
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = gamename,
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
ParseAddHelper(disk);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Standard ROMs have 4 pieces (name, size, crc, sha1)
|
||||
else if (split.Length == 3)
|
||||
// If we have the beginning of a game, set the name of the game
|
||||
else if (line.StartsWith("ROMs required for"))
|
||||
{
|
||||
Rom rom = new Rom()
|
||||
{
|
||||
Name = romname,
|
||||
Size = Sanitizer.CleanLong(split[0]),
|
||||
CRC = Sanitizer.CleanListromHashData(split[1]),
|
||||
SHA1 = Sanitizer.CleanListromHashData(split[2]),
|
||||
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = gamename,
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
ParseAddHelper(rom);
|
||||
gamename = Regex.Match(line, @"^ROMs required for \S*? string.Empty(.*?)string.Empty\.").Groups[1].Value;
|
||||
}
|
||||
|
||||
// Nodump Disks have 5 pieces (name, NO, GOOD, DUMP, KNOWN)
|
||||
else if (split.Length == 4 && line.EndsWith("NO GOOD DUMP KNOWN"))
|
||||
// If we have a machine with no required roms (usually internal devices), skip it
|
||||
else if (line.StartsWith("No ROMs required for"))
|
||||
{
|
||||
Disk disk = new Disk()
|
||||
{
|
||||
Name = romname,
|
||||
ItemStatus = ItemStatus.Nodump,
|
||||
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = gamename,
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
ParseAddHelper(disk);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Baddump ROMs have 6 pieces (name, size, BAD, crc, sha1, BAD_DUMP)
|
||||
else if (split.Length == 5 && line.EndsWith("BAD_DUMP"))
|
||||
{
|
||||
Rom rom = new Rom()
|
||||
{
|
||||
Name = romname,
|
||||
Size = Sanitizer.CleanLong(split[0]),
|
||||
CRC = Sanitizer.CleanListromHashData(split[2]),
|
||||
SHA1 = Sanitizer.CleanListromHashData(split[3]),
|
||||
ItemStatus = ItemStatus.BadDump,
|
||||
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = gamename,
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
ParseAddHelper(rom);
|
||||
}
|
||||
|
||||
// Nodump ROMs have 6 pieces (name, size, NO, GOOD, DUMP, KNOWN)
|
||||
else if (split.Length == 5 && line.EndsWith("NO GOOD DUMP KNOWN"))
|
||||
{
|
||||
Rom rom = new Rom()
|
||||
{
|
||||
Name = romname,
|
||||
Size = Sanitizer.CleanLong(split[0]),
|
||||
ItemStatus = ItemStatus.Nodump,
|
||||
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = gamename,
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
ParseAddHelper(rom);
|
||||
}
|
||||
|
||||
// If we have something else, it's invalid
|
||||
// Otherwise, we assume we have a rom that we need to add
|
||||
else
|
||||
{
|
||||
Globals.Logger.Warning($"Invalid line detected: '{romname} {line}'");
|
||||
// First, we preprocess the line so that the rom name is consistently correct
|
||||
string[] split = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// If the line doesn't have the 4 spaces of padding, check for 3
|
||||
if (split.Length == 1)
|
||||
split = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// If the split is still unsuccessful, log it and skip
|
||||
if (split.Length == 1)
|
||||
Globals.Logger.Warning($"Possibly malformed line: '{line}'");
|
||||
|
||||
string romname = split[0];
|
||||
line = line.Substring(romname.Length);
|
||||
|
||||
// Next we separate the ROM into pieces
|
||||
split = line.Split(new char[0], StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// Standard Disks have 2 pieces (name, sha1)
|
||||
if (split.Length == 1)
|
||||
{
|
||||
Disk disk = new Disk()
|
||||
{
|
||||
Name = romname,
|
||||
SHA1 = Sanitizer.CleanListromHashData(split[0]),
|
||||
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = gamename,
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
ParseAddHelper(disk);
|
||||
}
|
||||
|
||||
// Baddump Disks have 4 pieces (name, BAD, sha1, BAD_DUMP)
|
||||
else if (split.Length == 3 && line.EndsWith("BAD_DUMP"))
|
||||
{
|
||||
Disk disk = new Disk()
|
||||
{
|
||||
Name = romname,
|
||||
SHA1 = Sanitizer.CleanListromHashData(split[1]),
|
||||
ItemStatus = ItemStatus.BadDump,
|
||||
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = gamename,
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
ParseAddHelper(disk);
|
||||
}
|
||||
|
||||
// Standard ROMs have 4 pieces (name, size, crc, sha1)
|
||||
else if (split.Length == 3)
|
||||
{
|
||||
Rom rom = new Rom()
|
||||
{
|
||||
Name = romname,
|
||||
Size = Sanitizer.CleanLong(split[0]),
|
||||
CRC = Sanitizer.CleanListromHashData(split[1]),
|
||||
SHA1 = Sanitizer.CleanListromHashData(split[2]),
|
||||
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = gamename,
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
ParseAddHelper(rom);
|
||||
}
|
||||
|
||||
// Nodump Disks have 5 pieces (name, NO, GOOD, DUMP, KNOWN)
|
||||
else if (split.Length == 4 && line.EndsWith("NO GOOD DUMP KNOWN"))
|
||||
{
|
||||
Disk disk = new Disk()
|
||||
{
|
||||
Name = romname,
|
||||
ItemStatus = ItemStatus.Nodump,
|
||||
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = gamename,
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
ParseAddHelper(disk);
|
||||
}
|
||||
|
||||
// Baddump ROMs have 6 pieces (name, size, BAD, crc, sha1, BAD_DUMP)
|
||||
else if (split.Length == 5 && line.EndsWith("BAD_DUMP"))
|
||||
{
|
||||
Rom rom = new Rom()
|
||||
{
|
||||
Name = romname,
|
||||
Size = Sanitizer.CleanLong(split[0]),
|
||||
CRC = Sanitizer.CleanListromHashData(split[2]),
|
||||
SHA1 = Sanitizer.CleanListromHashData(split[3]),
|
||||
ItemStatus = ItemStatus.BadDump,
|
||||
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = gamename,
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
ParseAddHelper(rom);
|
||||
}
|
||||
|
||||
// Nodump ROMs have 6 pieces (name, size, NO, GOOD, DUMP, KNOWN)
|
||||
else if (split.Length == 5 && line.EndsWith("NO GOOD DUMP KNOWN"))
|
||||
{
|
||||
Rom rom = new Rom()
|
||||
{
|
||||
Name = romname,
|
||||
Size = Sanitizer.CleanLong(split[0]),
|
||||
ItemStatus = ItemStatus.Nodump,
|
||||
|
||||
Machine = new Machine
|
||||
{
|
||||
Name = gamename,
|
||||
},
|
||||
|
||||
Source = new Source
|
||||
{
|
||||
Index = indexId,
|
||||
Name = filename,
|
||||
},
|
||||
};
|
||||
|
||||
ParseAddHelper(rom);
|
||||
}
|
||||
|
||||
// If we have something else, it's invalid
|
||||
else
|
||||
{
|
||||
Globals.Logger.Warning($"Invalid line detected: '{romname} {line}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string message = $"'{filename}' - There was an error parsing at position {sr.BaseStream.Position}";
|
||||
Globals.Logger.Error(ex, message);
|
||||
if (throwOnError)
|
||||
{
|
||||
sr.Dispose();
|
||||
throw new Exception(message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,8 +90,12 @@ namespace SabreTools.Library.DatFiles
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Globals.Logger.Warning($"Exception found while parsing '{filename}': {ex}");
|
||||
if (throwOnError) throw ex;
|
||||
Globals.Logger.Warning(ex, $"Exception found while parsing '{filename}'");
|
||||
if (throwOnError)
|
||||
{
|
||||
xtr.Dispose();
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// For XML errors, just skip the affected node
|
||||
xtr?.Read();
|
||||
|
||||
@@ -107,8 +107,12 @@ namespace SabreTools.Library.DatFiles
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Globals.Logger.Warning($"Exception found while parsing '{filename}': {ex}");
|
||||
if (throwOnError) throw ex;
|
||||
Globals.Logger.Warning(ex, $"Exception found while parsing '{filename}'");
|
||||
if (throwOnError)
|
||||
{
|
||||
xtr.Dispose();
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// For XML errors, just skip the affected node
|
||||
xtr?.Read();
|
||||
|
||||
@@ -78,8 +78,12 @@ namespace SabreTools.Library.DatFiles
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Globals.Logger.Warning($"Exception found while parsing '{filename}': {ex}");
|
||||
if (throwOnError) throw ex;
|
||||
Globals.Logger.Warning(ex, $"Exception found while parsing '{filename}'");
|
||||
if (throwOnError)
|
||||
{
|
||||
xtr.Dispose();
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// For XML errors, just skip the affected node
|
||||
xtr?.Read();
|
||||
|
||||
@@ -80,8 +80,12 @@ namespace SabreTools.Library.DatFiles
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Globals.Logger.Warning($"Exception found while parsing '{filename}': {ex}");
|
||||
if (throwOnError) throw ex;
|
||||
Globals.Logger.Warning(ex, $"Exception found while parsing '{filename}'");
|
||||
if (throwOnError)
|
||||
{
|
||||
xtr.Dispose();
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// For XML errors, just skip the affected node
|
||||
xtr?.Read();
|
||||
|
||||
@@ -84,8 +84,13 @@ namespace SabreTools.Library.DatFiles
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Globals.Logger.Warning($"Exception found while parsing '{filename}': {ex}");
|
||||
if (throwOnError) throw ex;
|
||||
string message = $"'{filename}' - There was an error parsing line {ir.LineNumber} '{ir.CurrentLine}'";
|
||||
Globals.Logger.Error(ex, message);
|
||||
if (throwOnError)
|
||||
{
|
||||
ir.Dispose();
|
||||
throw new Exception(message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
ir.Dispose();
|
||||
@@ -304,7 +309,7 @@ namespace SabreTools.Library.DatFiles
|
||||
}
|
||||
|
||||
// Roms are not valid row formats, usually
|
||||
string line = reader.Line;
|
||||
string line = reader.CurrentLine;
|
||||
|
||||
// If we don't have a valid game, keep reading
|
||||
if (!line.StartsWith("¬"))
|
||||
|
||||
@@ -77,8 +77,12 @@ namespace SabreTools.Library.DatFiles
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Globals.Logger.Warning($"Exception found while parsing '{filename}': {ex}");
|
||||
if (throwOnError) throw ex;
|
||||
Globals.Logger.Warning(ex, $"Exception found while parsing '{filename}'");
|
||||
if (throwOnError)
|
||||
{
|
||||
xtr.Dispose();
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// For XML errors, just skip the affected node
|
||||
xtr?.Read();
|
||||
|
||||
@@ -65,8 +65,14 @@ namespace SabreTools.Library.DatFiles
|
||||
}
|
||||
catch (InvalidDataException ex)
|
||||
{
|
||||
Globals.Logger.Warning($"Malformed line found in '{filename}' at line {svr.LineNumber}");
|
||||
if (throwOnError) throw ex;
|
||||
string message = $"'{filename}' - There was an error parsing line {svr.LineNumber} '{svr.CurrentLine}'";
|
||||
Globals.Logger.Error(ex, message);
|
||||
if (throwOnError)
|
||||
{
|
||||
svr.Dispose();
|
||||
throw new Exception(message, ex);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,8 +81,12 @@ namespace SabreTools.Library.DatFiles
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Globals.Logger.Warning($"Exception found while parsing '{filename}': {ex}");
|
||||
if (throwOnError) throw ex;
|
||||
Globals.Logger.Warning(ex, $"Exception found while parsing '{filename}'");
|
||||
if (throwOnError)
|
||||
{
|
||||
xtr.Dispose();
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// For XML errors, just skip the affected node
|
||||
xtr?.Read();
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace SabreTools.Library.Filtering
|
||||
{
|
||||
// Get the key and value
|
||||
string key = ir.Section;
|
||||
string value = ir.Line.Trim();
|
||||
string value = ir.CurrentLine.Trim();
|
||||
|
||||
// If the section is "ROOT_FOLDER", then we use the value "true" instead.
|
||||
// This is done because some INI files use the name of the file as the
|
||||
|
||||
@@ -16,6 +16,16 @@ namespace SabreTools.Library.IO
|
||||
/// </summary>
|
||||
private StreamReader sr;
|
||||
|
||||
/// <summary>
|
||||
/// Contents of the current line, unprocessed
|
||||
/// </summary>
|
||||
public string CurrentLine { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Get the current line number
|
||||
/// </summary>
|
||||
public long LineNumber { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Get if at end of stream
|
||||
/// </summary>
|
||||
@@ -74,7 +84,6 @@ namespace SabreTools.Library.IO
|
||||
public ClrMameProReader(string filename)
|
||||
{
|
||||
sr = new StreamReader(filename);
|
||||
DosCenter = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -83,7 +92,6 @@ namespace SabreTools.Library.IO
|
||||
public ClrMameProReader(Stream stream, Encoding encoding)
|
||||
{
|
||||
sr = new StreamReader(stream, encoding);
|
||||
DosCenter = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -94,8 +102,11 @@ namespace SabreTools.Library.IO
|
||||
if (!(sr.BaseStream?.CanRead ?? false) || sr.EndOfStream)
|
||||
return false;
|
||||
|
||||
string line = sr.ReadLine().Trim();
|
||||
ProcessLine(line);
|
||||
CurrentLine = sr.ReadLine().Trim();
|
||||
LineNumber++;
|
||||
|
||||
// TODO: Act like IniReader here
|
||||
ProcessLine(CurrentLine);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,14 @@ namespace SabreTools.Library.IO
|
||||
public KeyValuePair<string, string>? KeyValuePair { get; private set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contents of the currently read line
|
||||
/// Contents of the current line, unprocessed
|
||||
/// </summary>
|
||||
public string Line { get; private set; } = string.Empty;
|
||||
public string CurrentLine { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Get the current line number
|
||||
/// </summary>
|
||||
public long LineNumber { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Current row type
|
||||
@@ -73,7 +78,8 @@ namespace SabreTools.Library.IO
|
||||
if (!(sr.BaseStream?.CanRead ?? false) || sr.EndOfStream)
|
||||
return false;
|
||||
|
||||
Line = sr.ReadLine().Trim();
|
||||
CurrentLine = sr.ReadLine().Trim();
|
||||
LineNumber++;
|
||||
ProcessLine();
|
||||
return true;
|
||||
}
|
||||
@@ -84,25 +90,25 @@ namespace SabreTools.Library.IO
|
||||
private void ProcessLine()
|
||||
{
|
||||
// Comment
|
||||
if (Line.StartsWith(";"))
|
||||
if (CurrentLine.StartsWith(";"))
|
||||
{
|
||||
KeyValuePair = null;
|
||||
RowType = IniRowType.Comment;
|
||||
}
|
||||
|
||||
// Section
|
||||
else if (Line.StartsWith("[") && Line.EndsWith("]"))
|
||||
else if (CurrentLine.StartsWith("[") && CurrentLine.EndsWith("]"))
|
||||
{
|
||||
KeyValuePair = null;
|
||||
RowType = IniRowType.SectionHeader;
|
||||
Section = Line.TrimStart('[').TrimEnd(']');
|
||||
Section = CurrentLine.TrimStart('[').TrimEnd(']');
|
||||
}
|
||||
|
||||
// KeyValuePair
|
||||
else if (Line.Contains("="))
|
||||
else if (CurrentLine.Contains("="))
|
||||
{
|
||||
// Split the line by '=' for key-value pairs
|
||||
string[] data = Line.Split('=');
|
||||
string[] data = CurrentLine.Split('=');
|
||||
|
||||
// If the value field contains an '=', we need to put them back in
|
||||
string key = data[0].Trim();
|
||||
@@ -113,10 +119,10 @@ namespace SabreTools.Library.IO
|
||||
}
|
||||
|
||||
// Empty
|
||||
else if (string.IsNullOrEmpty(Line))
|
||||
else if (string.IsNullOrEmpty(CurrentLine))
|
||||
{
|
||||
KeyValuePair = null;
|
||||
Line = string.Empty;
|
||||
CurrentLine = string.Empty;
|
||||
RowType = IniRowType.None;
|
||||
}
|
||||
|
||||
@@ -127,7 +133,7 @@ namespace SabreTools.Library.IO
|
||||
RowType = IniRowType.Invalid;
|
||||
|
||||
if (ValidateRows)
|
||||
throw new InvalidDataException($"Invalid INI row found, cannot continue: {Line}");
|
||||
throw new InvalidDataException($"Invalid INI row found, cannot continue: {CurrentLine}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,16 @@ namespace SabreTools.Library.IO
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contents of the current line, unprocessed
|
||||
/// </summary>
|
||||
public string CurrentLine { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Get the current line number
|
||||
/// </summary>
|
||||
public long LineNumber { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Assume the first row is a header
|
||||
/// </summary>
|
||||
@@ -45,11 +55,6 @@ namespace SabreTools.Library.IO
|
||||
/// </summary>
|
||||
public List<string> Line { get; private set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Get the current line number
|
||||
/// </summary>
|
||||
public long LineNumber { get; private set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Assume that values are wrapped in quotes
|
||||
/// </summary>
|
||||
@@ -104,6 +109,7 @@ namespace SabreTools.Library.IO
|
||||
return false;
|
||||
|
||||
string fullLine = sr.ReadLine();
|
||||
CurrentLine = fullLine;
|
||||
LineNumber++;
|
||||
|
||||
// If we have quotes, we need to split specially
|
||||
|
||||
Reference in New Issue
Block a user