diff --git a/SabreTools.Library/DatFiles/ClrMamePro.cs b/SabreTools.Library/DatFiles/ClrMamePro.cs
index 1fd27ba6..1fe4c21c 100644
--- a/SabreTools.Library/DatFiles/ClrMamePro.cs
+++ b/SabreTools.Library/DatFiles/ClrMamePro.cs
@@ -15,13 +15,24 @@ namespace SabreTools.Library.DatFiles
///
internal class ClrMamePro : DatFile
{
+ #region Fields
+
+ ///
+ /// Get whether to assume quote usage on read and write or not
+ ///
+ public bool Quotes { get; set; } = true;
+
+ #endregion
+
///
/// Constructor designed for casting a base DatFile
///
/// Parent DatFile to copy from
- public ClrMamePro(DatFile datFile)
+ /// Enable quotes on read and write, false otherwise
+ public ClrMamePro(DatFile datFile, bool quotes)
: base(datFile)
{
+ Quotes = quotes;
}
///
@@ -37,7 +48,8 @@ namespace SabreTools.Library.DatFiles
Encoding enc = FileExtensions.GetEncoding(filename);
ClrMameProReader cmpr = new ClrMameProReader(FileExtensions.TryOpenRead(filename), enc)
{
- DosCenter = false
+ DosCenter = false,
+ Quotes = Quotes,
};
while (!cmpr.EndOfStream)
@@ -445,7 +457,7 @@ namespace SabreTools.Library.DatFiles
ClrMameProWriter cmpw = new ClrMameProWriter(fs, new UTF8Encoding(false))
{
- Quotes = true
+ Quotes = Quotes
};
// Write out the header
diff --git a/SabreTools.Library/DatFiles/DatFile.cs b/SabreTools.Library/DatFiles/DatFile.cs
index 8682ca80..187d2271 100644
--- a/SabreTools.Library/DatFiles/DatFile.cs
+++ b/SabreTools.Library/DatFiles/DatFile.cs
@@ -65,8 +65,9 @@ namespace SabreTools.Library.DatFiles
///
/// Format of the DAT to be created
/// DatFile containing the information to use in specific operations
+ /// For relevant types, assume the usage of quotes
/// DatFile of the specific internal type that corresponds to the inputs
- public static DatFile Create(DatFormat? datFormat = null, DatFile baseDat = null)
+ public static DatFile Create(DatFormat? datFormat = null, DatFile baseDat = null, bool quotes = true)
{
switch (datFormat)
{
@@ -74,7 +75,7 @@ namespace SabreTools.Library.DatFiles
return new AttractMode(baseDat);
case DatFormat.ClrMamePro:
- return new ClrMamePro(baseDat);
+ return new ClrMamePro(baseDat, quotes);
case DatFormat.CSV:
return new SeparatedValue(baseDat, ',');
@@ -1819,16 +1820,18 @@ namespace SabreTools.Library.DatFiles
/// Index ID for the DAT
/// True if full pathnames are to be kept, false otherwise (default)
/// True if original extension should be kept, false otherwise (default)
+ /// True if quotes are assumed in supported types (default), false otherwise
/// True if the error that is thrown should be thrown back to the caller, false otherwise
public void Parse(
string filename,
int indexId = 0,
bool keep = false,
bool keepext = false,
+ bool quotes = true,
bool throwOnError = false)
{
ParentablePath path = new ParentablePath(filename.Trim('"'));
- Parse(path, indexId, keep, keepext, throwOnError);
+ Parse(path, indexId, keep, keepext, quotes, throwOnError);
}
///
@@ -1838,12 +1841,14 @@ namespace SabreTools.Library.DatFiles
/// Index ID for the DAT
/// True if full pathnames are to be kept, false otherwise (default)
/// True if original extension should be kept, false otherwise (default)
+ /// True if quotes are assumed in supported types (default), false otherwise
/// True if the error that is thrown should be thrown back to the caller, false otherwise
public void Parse(
ParentablePath filename,
int indexId = 0,
bool keep = false,
bool keepext = false,
+ bool quotes = true,
bool throwOnError = false)
{
// Get the current path from the filename
@@ -1863,7 +1868,7 @@ namespace SabreTools.Library.DatFiles
// Now parse the correct type of DAT
try
{
- Create(currentPath.GetDatFormat(), this)?.ParseFile(currentPath, indexId, keep, throwOnError);
+ Create(currentPath.GetDatFormat(), this, quotes)?.ParseFile(currentPath, indexId, keep, throwOnError);
}
catch (Exception ex)
{
@@ -3484,9 +3489,15 @@ namespace SabreTools.Library.DatFiles
/// Set the output directory (current directory on null)
/// True if files should be overwritten (default), false if they should be renamed instead
/// True if blank roms should be skipped on output, false otherwise (default)
+ /// True if quotes are assumed in supported types (default), false otherwise
/// True if the error that is thrown should be thrown back to the caller, false otherwise
/// True if the DAT was written correctly, false otherwise
- public bool Write(string outDir, bool overwrite = true, bool ignoreblanks = false, bool throwOnError = false)
+ public bool Write(
+ string outDir,
+ bool overwrite = true,
+ bool ignoreblanks = false,
+ bool quotes = true,
+ bool throwOnError = false)
{
// If we have nothing writable, abort
if (!HasWritable())
@@ -3525,7 +3536,7 @@ namespace SabreTools.Library.DatFiles
string outfile = outfiles[datFormat];
try
{
- Create(datFormat, this)?.WriteToFile(outfile, ignoreblanks, throwOnError);
+ Create(datFormat, this, quotes)?.WriteToFile(outfile, ignoreblanks, throwOnError);
}
catch (Exception ex)
{
diff --git a/SabreTools.Library/Data/Constants.cs b/SabreTools.Library/Data/Constants.cs
index 6b07eb2e..63e2943c 100644
--- a/SabreTools.Library/Data/Constants.cs
+++ b/SabreTools.Library/Data/Constants.cs
@@ -526,7 +526,7 @@ namespace SabreTools.Library.Data
public const string XmlPattern = @"<(.*?)>(.*?)(.*?)>";
public const string HeaderPatternCMP = @"(^.*?) \($";
- public const string InternalPatternCMP = @"(^.*?) (\(.+\))$";
+ public const string InternalPatternCMP = @"(^\S*?) (\(.+\))$";
public const string InternalPatternAttributesCMP = @"[^\s""]+|""[^""]*""";
//public const string InternalPatternAttributesCMP = @"([^\s]*""[^""]+""[^\s]*)|[^""]?\w+[^""]?";
public const string ItemPatternCMP = @"^\s*(\S*?) (.*)";
diff --git a/SabreTools.Library/IO/ClrMameProReader.cs b/SabreTools.Library/IO/ClrMameProReader.cs
index 85e4dfad..86e1b6aa 100644
--- a/SabreTools.Library/IO/ClrMameProReader.cs
+++ b/SabreTools.Library/IO/ClrMameProReader.cs
@@ -42,6 +42,17 @@ namespace SabreTools.Library.IO
///
public bool DosCenter { get; set; } = false;
+ ///
+ /// Get if quotes should surround attribute values
+ ///
+ ///
+ /// If this is disabled, then a special bit of code will be
+ /// invoked to deal with unquoted, multi-part names. This can
+ /// backfire in a lot of circumstances, so don't disable this
+ /// unless you know what you're doing
+ ///
+ public bool Quotes { get; set; } = true;
+
///
/// Current row type
///
@@ -166,6 +177,22 @@ namespace SabreTools.Library.IO
value = linegc[++i].Replace("\"", string.Empty);
}
}
+ // Special case for assumed unquoted values (only affects `name`)
+ else if (!Quotes && key == "name")
+ {
+ while (++i < linegc.Length
+ && linegc[i] != "merge"
+ && linegc[i] != "size"
+ && linegc[i] != "crc"
+ && linegc[i] != "md5"
+ && linegc[i] != "sha1")
+ {
+ value += $" {linegc[i]}";
+ }
+
+ value = value.Trim();
+ i--;
+ }
else
{
// Special cases for standalone statuses