Filter Abstraction (#25)

* Add category, back filters by dictionary

* Complete internal filter set

* Fix AreaSize filter

* Populate filter object the hard way

* Manipulation flags should not be filters

* None of them need to be public

* Convert to partial helper method

* Better method use

* Field, not string; no dictionary

* Add FilterTo method for later

* More naming options (easier conversion)

* Update README
This commit is contained in:
Matt Nadareski
2020-07-18 21:35:17 -07:00
committed by GitHub
parent a25ffc8a36
commit 334e1c4585
21 changed files with 1551 additions and 254 deletions

View File

@@ -241,6 +241,9 @@ namespace SabreTools.Library.DatFiles
case "manufacturer": case "manufacturer":
machine.Manufacturer = itemVal; machine.Manufacturer = itemVal;
break; break;
case "category":
machine.Category = itemVal;
break;
case "cloneof": case "cloneof":
machine.CloneOf = itemVal; machine.CloneOf = itemVal;
break; break;
@@ -634,6 +637,8 @@ namespace SabreTools.Library.DatFiles
cmpw.WriteStandalone("year", datItem.Year); cmpw.WriteStandalone("year", datItem.Year);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Manufacturer, DatHeader.ExcludeFields))) if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Manufacturer, DatHeader.ExcludeFields)))
cmpw.WriteStandalone("manufacturer", datItem.Manufacturer); cmpw.WriteStandalone("manufacturer", datItem.Manufacturer);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Category, DatHeader.ExcludeFields)))
cmpw.WriteStandalone("category", datItem.Category);
cmpw.Flush(); cmpw.Flush();
} }

View File

@@ -1147,6 +1147,9 @@ namespace SabreTools.Library.DatFiles
if (updateFields.Contains(Field.Publisher)) if (updateFields.Contains(Field.Publisher))
newDatItem.Publisher = firstDupe.Publisher; newDatItem.Publisher = firstDupe.Publisher;
if (updateFields.Contains(Field.Category))
newDatItem.Category = firstDupe.Category;
if (updateFields.Contains(Field.RomOf)) if (updateFields.Contains(Field.RomOf))
newDatItem.RomOf = firstDupe.RomOf; newDatItem.RomOf = firstDupe.RomOf;
@@ -3659,6 +3662,7 @@ namespace SabreTools.Library.DatFiles
name = item.Name, name = item.Name,
manufacturer = item.Manufacturer, manufacturer = item.Manufacturer,
publisher = item.Publisher, publisher = item.Publisher,
category = item.Category,
crc = string.Empty, crc = string.Empty,
md5 = string.Empty, md5 = string.Empty,
ripemd160 = string.Empty, ripemd160 = string.Empty,
@@ -3709,6 +3713,7 @@ namespace SabreTools.Library.DatFiles
.Replace("%name%", name) .Replace("%name%", name)
.Replace("%manufacturer%", manufacturer) .Replace("%manufacturer%", manufacturer)
.Replace("%publisher%", publisher) .Replace("%publisher%", publisher)
.Replace("%category%", category)
.Replace("%crc%", crc) .Replace("%crc%", crc)
.Replace("%md5%", md5) .Replace("%md5%", md5)
.Replace("%ripemd160%", ripemd160) .Replace("%ripemd160%", ripemd160)

File diff suppressed because it is too large Load Diff

View File

@@ -317,6 +317,10 @@ namespace SabreTools.Library.DatFiles
machine.Publisher = jtr.ReadAsString(); machine.Publisher = jtr.ReadAsString();
break; break;
case "category":
machine.Category = jtr.ReadAsString();
break;
case "romof": case "romof":
machine.RomOf = jtr.ReadAsString(); machine.RomOf = jtr.ReadAsString();
break; break;
@@ -1023,6 +1027,11 @@ namespace SabreTools.Library.DatFiles
jtw.WritePropertyName("publisher"); jtw.WritePropertyName("publisher");
jtw.WriteValue(datItem.Publisher); jtw.WriteValue(datItem.Publisher);
} }
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Category, DatHeader.ExcludeFields)))
{
jtw.WritePropertyName("category");
jtw.WriteValue(datItem.Category);
}
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RomOf, DatHeader.ExcludeFields)) && !string.Equals(datItem.MachineName, datItem.RomOf, StringComparison.OrdinalIgnoreCase)) if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RomOf, DatHeader.ExcludeFields)) && !string.Equals(datItem.MachineName, datItem.RomOf, StringComparison.OrdinalIgnoreCase))
{ {
jtw.WritePropertyName("romof"); jtw.WritePropertyName("romof");

View File

@@ -716,6 +716,8 @@ namespace SabreTools.Library.DatFiles
xtw.WriteElementString("year", datItem.Year); xtw.WriteElementString("year", datItem.Year);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Publisher, DatHeader.ExcludeFields))) if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Publisher, DatHeader.ExcludeFields)))
xtw.WriteElementString("publisher", datItem.Publisher); xtw.WriteElementString("publisher", datItem.Publisher);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Category, DatHeader.ExcludeFields)))
xtw.WriteElementString("category", datItem.Category);
if (!DatHeader.ExcludeFields[(int)Field.Infos] && datItem.Infos != null && datItem.Infos.Count > 0) if (!DatHeader.ExcludeFields[(int)Field.Infos] && datItem.Infos != null && datItem.Infos.Count > 0)
{ {

View File

@@ -377,6 +377,10 @@ namespace SabreTools.Library.DatFiles
machine.Publisher = reader.ReadElementContentAsString(); machine.Publisher = reader.ReadElementContentAsString();
break; break;
case "category": // Not technically supported but used by some legacy DATs
machine.Category = reader.ReadElementContentAsString();
break;
case "trurip": // This is special metadata unique to TruRip case "trurip": // This is special metadata unique to TruRip
ReadTruRip(reader.ReadSubtree(), machine); ReadTruRip(reader.ReadSubtree(), machine);
@@ -588,7 +592,7 @@ namespace SabreTools.Library.DatFiles
break; break;
case "genre": case "genre":
reader.ReadElementContentAsString(); machine.Category = reader.ReadElementContentAsString();
break; break;
case "subgenre": case "subgenre":
@@ -894,6 +898,8 @@ namespace SabreTools.Library.DatFiles
xtw.WriteElementString("publisher", datItem.Publisher); xtw.WriteElementString("publisher", datItem.Publisher);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Manufacturer, DatHeader.ExcludeFields))) if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Manufacturer, DatHeader.ExcludeFields)))
xtw.WriteElementString("manufacturer", datItem.Manufacturer); xtw.WriteElementString("manufacturer", datItem.Manufacturer);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Category, DatHeader.ExcludeFields)))
xtw.WriteElementString("category", datItem.Category);
xtw.Flush(); xtw.Flush();
} }

View File

@@ -213,6 +213,10 @@ namespace SabreTools.Library.DatFiles
machine.Publisher = value; machine.Publisher = value;
break; break;
case "Machine.Category":
machine.Category = value;
break;
case "Machine.RomOf": case "Machine.RomOf":
machine.RomOf = value; machine.RomOf = value;
break; break;

View File

@@ -174,6 +174,10 @@ namespace SabreTools.Library.DatFiles
machine.Publisher = reader.ReadElementContentAsString(); machine.Publisher = reader.ReadElementContentAsString();
break; break;
case "category":
machine.Category = reader.ReadElementContentAsString();
break;
case "info": case "info":
machine.Infos.Add(new KeyValuePair<string, string>(reader.GetAttribute("name"), reader.GetAttribute("value"))); machine.Infos.Add(new KeyValuePair<string, string>(reader.GetAttribute("name"), reader.GetAttribute("value")));
reader.Read(); reader.Read();
@@ -717,6 +721,8 @@ namespace SabreTools.Library.DatFiles
xtw.WriteElementString("year", datItem.Year); xtw.WriteElementString("year", datItem.Year);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Publisher, DatHeader.ExcludeFields))) if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Publisher, DatHeader.ExcludeFields)))
xtw.WriteElementString("publisher", datItem.Publisher); xtw.WriteElementString("publisher", datItem.Publisher);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Category, DatHeader.ExcludeFields)))
xtw.WriteElementString("category", datItem.Category);
if (!DatHeader.ExcludeFields[(int)Field.Infos] && datItem.Infos != null && datItem.Infos.Count > 0) if (!DatHeader.ExcludeFields[(int)Field.Infos] && datItem.Infos != null && datItem.Infos.Count > 0)
{ {

View File

@@ -32,6 +32,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported, Supported = this.Supported,
Publisher = this.Publisher, Publisher = this.Publisher,
Category = this.Category,
Infos = this.Infos, Infos = this.Infos,
PartName = this.PartName, PartName = this.PartName,
PartInterface = this.PartInterface, PartInterface = this.PartInterface,

View File

@@ -49,6 +49,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported, Supported = this.Supported,
Publisher = this.Publisher, Publisher = this.Publisher,
Category = this.Category,
Infos = this.Infos, Infos = this.Infos,
PartName = this.PartName, PartName = this.PartName,
PartInterface = this.PartInterface, PartInterface = this.PartInterface,

View File

@@ -32,6 +32,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported, Supported = this.Supported,
Publisher = this.Publisher, Publisher = this.Publisher,
Category = this.Category,
Infos = this.Infos, Infos = this.Infos,
PartName = this.PartName, PartName = this.PartName,
PartInterface = this.PartInterface, PartInterface = this.PartInterface,

View File

@@ -206,6 +206,32 @@ namespace SabreTools.Library.DatItems
} }
} }
/// <summary>
/// Machine category, if available
/// </summary>
[JsonIgnore]
public string Category
{
get
{
if (_machine == null)
{
_machine = new Machine();
}
return _machine.Category;
}
set
{
if (_machine == null)
{
_machine = new Machine();
}
_machine.Category = value;
}
}
/// <summary> /// <summary>
/// Machine romof parent /// Machine romof parent
/// </summary> /// </summary>
@@ -633,6 +659,9 @@ namespace SabreTools.Library.DatItems
case Field.Publisher: case Field.Publisher:
fieldValue = this.Publisher; fieldValue = this.Publisher;
break; break;
case Field.Category:
fieldValue = this.Category;
break;
case Field.RomOf: case Field.RomOf:
fieldValue = this.RomOf; fieldValue = this.RomOf;
break; break;

View File

@@ -173,6 +173,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported, Supported = this.Supported,
Publisher = this.Publisher, Publisher = this.Publisher,
Category = this.Category,
Infos = this.Infos, Infos = this.Infos,
PartName = this.PartName, PartName = this.PartName,
PartInterface = this.PartInterface, PartInterface = this.PartInterface,
@@ -241,6 +242,7 @@ namespace SabreTools.Library.DatItems
Year = this.Year, Year = this.Year,
Manufacturer = this.Manufacturer, Manufacturer = this.Manufacturer,
Publisher = this.Publisher, Publisher = this.Publisher,
Category = this.Category,
RomOf = this.RomOf, RomOf = this.RomOf,
CloneOf = this.CloneOf, CloneOf = this.CloneOf,
SampleOf = this.SampleOf, SampleOf = this.SampleOf,

View File

@@ -49,6 +49,12 @@ namespace SabreTools.Library.DatItems
[JsonProperty("publisher")] [JsonProperty("publisher")]
public string Publisher { get; set; } public string Publisher { get; set; }
/// <summary>
/// Category, if available
/// </summary>
[JsonProperty("category")]
public string Category { get; set; }
/// <summary> /// <summary>
/// fomof parent /// fomof parent
/// </summary> /// </summary>
@@ -138,6 +144,7 @@ namespace SabreTools.Library.DatItems
Year = null; Year = null;
Manufacturer = null; Manufacturer = null;
Publisher = null; Publisher = null;
Category = null;
RomOf = null; RomOf = null;
CloneOf = null; CloneOf = null;
SampleOf = null; SampleOf = null;
@@ -165,6 +172,7 @@ namespace SabreTools.Library.DatItems
Year = null; Year = null;
Manufacturer = null; Manufacturer = null;
Publisher = null; Publisher = null;
Category = null;
RomOf = null; RomOf = null;
CloneOf = null; CloneOf = null;
SampleOf = null; SampleOf = null;
@@ -197,6 +205,7 @@ namespace SabreTools.Library.DatItems
Year = this.Year, Year = this.Year,
Manufacturer = this.Manufacturer, Manufacturer = this.Manufacturer,
Publisher = this.Publisher, Publisher = this.Publisher,
Category = this.Category,
RomOf = this.RomOf, RomOf = this.RomOf,
CloneOf = this.CloneOf, CloneOf = this.CloneOf,
SampleOf = this.SampleOf, SampleOf = this.SampleOf,

View File

@@ -65,6 +65,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported, Supported = this.Supported,
Publisher = this.Publisher, Publisher = this.Publisher,
Category = this.Category,
Infos = this.Infos, Infos = this.Infos,
PartName = this.PartName, PartName = this.PartName,
PartInterface = this.PartInterface, PartInterface = this.PartInterface,

View File

@@ -220,6 +220,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported, Supported = this.Supported,
Publisher = this.Publisher, Publisher = this.Publisher,
Category = this.Category,
Infos = this.Infos, Infos = this.Infos,
PartName = this.PartName, PartName = this.PartName,
PartInterface = this.PartInterface, PartInterface = this.PartInterface,

View File

@@ -32,6 +32,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported, Supported = this.Supported,
Publisher = this.Publisher, Publisher = this.Publisher,
Category = this.Category,
Infos = this.Infos, Infos = this.Infos,
PartName = this.PartName, PartName = this.PartName,
PartInterface = this.PartInterface, PartInterface = this.PartInterface,

View File

@@ -261,7 +261,6 @@
Game, Game,
} }
/// <summary> /// <summary>
/// Determines the DAT deduplication type /// Determines the DAT deduplication type
/// </summary> /// </summary>
@@ -351,6 +350,7 @@
NULL = 0, NULL = 0,
// Generic DatItem // Generic DatItem
ItemType,
Name, Name,
PartName, PartName,
PartInterface, PartInterface,
@@ -365,6 +365,7 @@
Year, Year,
Manufacturer, Manufacturer,
Publisher, Publisher,
Category,
RomOf, RomOf,
CloneOf, CloneOf,
SampleOf, SampleOf,

View File

@@ -334,6 +334,26 @@ Options:
compare against the input DATs. This flag forces all CHDs to be compare against the input DATs. This flag forces all CHDs to be
treated like regular files. treated like regular files.
-fi=, --filter= Filter a game/rom field with the given value(s)
Filter any valid item or machine field from inputs. Filters are input
in the form 'key:value' or '!key:value', where the '!' signifies 'not'
matching. Numeric values may also prefix the 'value' with '>', '<', or
'=' accordingly. Key examples include: romof, category, and game.
Additionally, the user can specify an exact match or full C#-style
regex for pattern matching. Multiple instances of this flag are
allowed.
-cat=, --category-filter= Filter by category
Include only items with this category in the output. Additionally,
the user can specify an exact match or full C#-style regex for
pattern matching. Multiple instances of this flag are allowed.
-ncat=, --not-category= Filter by not category
Include only items without this category in the output.
Additionally, the user can specify an exact match or full C#-style
regex for pattern matching. Multiple instances of this flag are
allowed.
-gn=, --game-name= Filter by game name -gn=, --game-name= Filter by game name
Include only items with this game name in the output. Additionally, Include only items with this game name in the output. Additionally,
the user can specify an exact match or full C#-style regex for the user can specify an exact match or full C#-style regex for
@@ -950,6 +970,7 @@ Options:
- %name% - Replaced with the Rom name - %name% - Replaced with the Rom name
- %manufacturer% - Replaced with game Manufacturer - %manufacturer% - Replaced with game Manufacturer
- %publisher% - Replaced with game Publisher - %publisher% - Replaced with game Publisher
- %category% - Replaced with game Category
- %crc% - Replaced with the CRC - %crc% - Replaced with the CRC
- %md5% - Replaced with the MD5 - %md5% - Replaced with the MD5
- %ripemd160% - Replaced with the RIPEMD160 (.NET Framework 4.8 only) - %ripemd160% - Replaced with the RIPEMD160 (.NET Framework 4.8 only)
@@ -1276,6 +1297,26 @@ Options:
second time, this will skip writing it. This can often speed up second time, this will skip writing it. This can often speed up
the output process. [Both diff-cascade and diff-reverse-cascade] the output process. [Both diff-cascade and diff-reverse-cascade]
-fi=, --filter= Filter a game/rom field with the given value(s)
Filter any valid item or machine field from inputs. Filters are input
in the form 'key:value' or '!key:value', where the '!' signifies 'not'
matching. Numeric values may also prefix the 'value' with '>', '<', or
'=' accordingly. Key examples include: romof, category, and game.
Additionally, the user can specify an exact match or full C#-style
regex for pattern matching. Multiple instances of this flag are
allowed.
-cat=, --category-filter= Filter by category
Include only items with this category in the output. Additionally,
the user can specify an exact match or full C#-style regex for
pattern matching. Multiple instances of this flag are allowed.
-ncat=, --not-category= Filter by not category
Include only items without this category in the output.
Additionally, the user can specify an exact match or full C#-style
regex for pattern matching. Multiple instances of this flag are
allowed.
-gn=, --game-name= Filter by game name -gn=, --game-name= Filter by game name
Include only items with this game name in the output. Additionally, Include only items with this game name in the output. Additionally,
the user can specify an exact match or full C#-style regex for the user can specify an exact match or full C#-style regex for
@@ -1533,6 +1574,26 @@ Options:
parent sets based on the cloneof and romof tags as well as device parent sets based on the cloneof and romof tags as well as device
references. This is incompatible with the other --dat-X flags. references. This is incompatible with the other --dat-X flags.
-fi=, --filter= Filter a game/rom field with the given value(s)
Filter any valid item or machine field from inputs. Filters are input
in the form 'key:value' or '!key:value', where the '!' signifies 'not'
matching. Numeric values may also prefix the 'value' with '>', '<', or
'=' accordingly. Key examples include: romof, category, and game.
Additionally, the user can specify an exact match or full C#-style
regex for pattern matching. Multiple instances of this flag are
allowed.
-cat=, --category-filter= Filter by category
Include only items with this category in the output. Additionally,
the user can specify an exact match or full C#-style regex for
pattern matching. Multiple instances of this flag are allowed.
-ncat=, --not-category= Filter by not category
Include only items without this category in the output.
Additionally, the user can specify an exact match or full C#-style
regex for pattern matching. Multiple instances of this flag are
allowed.
-gn=, --game-name= Filter by game name -gn=, --game-name= Filter by game name
Include only items with this game name in the output. Additionally, Include only items with this game name in the output. Additionally,
the user can specify an exact match or full C#-style regex for the user can specify an exact match or full C#-style regex for

View File

@@ -122,45 +122,78 @@ namespace SabreTools.Library.Tools
switch (input?.ToLowerInvariant()) switch (input?.ToLowerInvariant())
{ {
case "areaname": case "areaname":
case "area-name":
return Field.AreaName; return Field.AreaName;
case "areasize": case "areasize":
case "area-size":
return Field.AreaSize; return Field.AreaSize;
case "bios": case "bios":
return Field.Bios; return Field.Bios;
case "biosdescription": case "biosdescription":
case "bios description": case "bios-description":
case "biossetdescription":
case "biosset description":
case "biossetdescription": case "biossetdescription":
case "biosset-description":
case "bios-set-description":
return Field.BiosDescription; return Field.BiosDescription;
case "board": case "board":
return Field.Board; return Field.Board;
case "category":
case "machinecategory":
case "machine-category":
return Field.Category;
case "cloneof": case "cloneof":
return Field.CloneOf; return Field.CloneOf;
case "comment": case "comment":
return Field.Comment; return Field.Comment;
case "crc": case "crc":
case "crc32":
return Field.CRC; return Field.CRC;
case "default": case "default":
return Field.Default; return Field.Default;
case "date": case "date":
return Field.Date; return Field.Date;
case "desc":
case "description": case "description":
case "gamedesc":
case "gamedescription":
case "game-description":
case "machinedesc":
case "machinedescription":
case "machine-description":
return Field.Description; return Field.Description;
case "devices": case "devices":
return Field.Devices; return Field.Devices;
case "equal":
case "greater":
case "less":
case "size":
return Field.Size;
case "features": case "features":
return Field.Features; return Field.Features;
case "gamename": case "gamename":
case "machinename": case "machinename":
return Field.MachineName; return Field.MachineName;
case "gametype": case "gametype":
case "game-type":
case "machinetype": case "machinetype":
case "machine-type":
return Field.MachineType; return Field.MachineType;
case "index": case "index":
return Field.Index; return Field.Index;
case "infos": case "infos":
return Field.Infos; return Field.Infos;
case "itemname":
case "item-name":
case "name":
return Field.Name;
case "itemtatus":
case "item-status":
case "status":
return Field.Status;
case "itemtype":
case "item-type":
case "type":
return Field.ItemType;
case "language": case "language":
return Field.Language; return Field.Language;
case "manufacturer": case "manufacturer":
@@ -168,16 +201,18 @@ namespace SabreTools.Library.Tools
case "md5": case "md5":
return Field.MD5; return Field.MD5;
case "merge": case "merge":
case "mergetag":
case "merge-tag":
return Field.Merge; return Field.Merge;
case "name":
return Field.Name;
case "offset": case "offset":
return Field.Offset; return Field.Offset;
case "optional": case "optional":
return Field.Optional; return Field.Optional;
case "partinterface": case "partinterface":
case "part-interface":
return Field.PartInterface; return Field.PartInterface;
case "partname": case "partname":
case "part-name":
return Field.PartName; return Field.PartName;
case "publisher": case "publisher":
return Field.Publisher; return Field.Publisher;
@@ -196,21 +231,23 @@ namespace SabreTools.Library.Tools
case "sampleof": case "sampleof":
return Field.SampleOf; return Field.SampleOf;
case "sha1": case "sha1":
case "sha-1":
return Field.SHA1; return Field.SHA1;
case "sha256": case "sha256":
case "sha-256":
return Field.SHA256; return Field.SHA256;
case "sha384": case "sha384":
case "sha-384":
return Field.SHA384; return Field.SHA384;
case "sha512": case "sha512":
case "sha-512":
return Field.SHA512; return Field.SHA512;
case "size":
return Field.Size;
case "slotoptions": case "slotoptions":
case "slot-options":
return Field.SlotOptions; return Field.SlotOptions;
case "sourcefile": case "sourcefile":
case "source-file":
return Field.SourceFile; return Field.SourceFile;
case "status":
return Field.Status;
case "supported": case "supported":
return Field.Supported; return Field.Supported;
case "writable": case "writable":

View File

@@ -1269,6 +1269,20 @@ namespace SabreTools
} }
} }
public const string CategoryListValue = "category-filter";
private static Feature CategoryListInput
{
get
{
return new Feature(
CategoryListValue,
new List<string>() { "-cat", "--category-filter" },
"Filter by Category",
FeatureType.List,
longDescription: "Include only items with this Category in the output. Additionally, the user can specify an exact match or full C#-style regex for pattern matching. Multiple instances of this flag are allowed.");
}
}
public const string CrcListValue = "crc"; public const string CrcListValue = "crc";
private static Feature CrcListInput private static Feature CrcListInput
{ {
@@ -1339,6 +1353,20 @@ namespace SabreTools
} }
} }
public const string FilterListValue = "filter";
private static Feature FilterListInput
{
get
{
return new Feature(
FilterListValue,
new List<string>() { "-fi", "--filter" },
"Filter a game/rom field with the given value(s)",
FeatureType.List,
longDescription: "Filter any valid item or machine field from inputs. Filters are input in the form 'key:value' or '!key:value', where the '!' signifies 'not' matching. Numeric values may also prefix the 'value' with '>', '<', or '=' accordingly. Key examples include: romof, category, and game. Additionally, the user can specify an exact match or full C#-style regex for pattern matching. Multiple instances of this flag are allowed.");
}
}
public const string GameDescriptionListValue = "game-description"; public const string GameDescriptionListValue = "game-description";
private static Feature GameDescriptionListInput private static Feature GameDescriptionListInput
{ {
@@ -1424,6 +1452,20 @@ Possible values are: None, Bios, Device, Mechanical");
} }
} }
public const string NotCategoryListValue = "not-category";
private static Feature NotCategoryListInput
{
get
{
return new Feature(
NotCategoryListValue,
new List<string>() { "-ncat", "--not-category" },
"Filter by not Category",
FeatureType.List,
longDescription: "Include only items without this Category in the output. Additionally, the user can specify an exact match or full C#-style regex for pattern matching. Multiple instances of this flag are allowed.");
}
}
public const string NotCrcListValue = "not-crc"; public const string NotCrcListValue = "not-crc";
private static Feature NotCrcListInput private static Feature NotCrcListInput
{ {
@@ -2055,6 +2097,7 @@ Some special strings that can be used:
- %name% - Replaced with the Rom name - %name% - Replaced with the Rom name
- %manufacturer% - Replaced with game Manufacturer - %manufacturer% - Replaced with game Manufacturer
- %publisher% - Replaced with game Publisher - %publisher% - Replaced with game Publisher
- %category% - Replaced with game Category
- %crc% - Replaced with the CRC - %crc% - Replaced with the CRC
- %md5% - Replaced with the MD5" - %md5% - Replaced with the MD5"
#if NET_FRAMEWORK #if NET_FRAMEWORK
@@ -2087,6 +2130,7 @@ Some special strings that can be used:
- %name% - Replaced with the Rom name - %name% - Replaced with the Rom name
- %manufacturer% - Replaced with game Manufacturer - %manufacturer% - Replaced with game Manufacturer
- %publisher% - Replaced with game Publisher - %publisher% - Replaced with game Publisher
- %category% - Replaced with game Category
- %crc% - Replaced with the CRC - %crc% - Replaced with the CRC
- %md5% - Replaced with the MD5 - %md5% - Replaced with the MD5
- %sha1% - Replaced with the SHA-1 - %sha1% - Replaced with the SHA-1
@@ -2297,106 +2341,243 @@ Some special strings that can be used:
{ {
Filter filter = new Filter(); Filter filter = new Filter();
// Clean names // Use the Filter flag first
filter.Clean.Neutral = GetBoolean(features, CleanValue); List<string> filterPairs = GetList(features, FilterListValue);
filter.PopulateFromList(filterPairs);
#region Obsoleted Inputs
// Category
if (features.ContainsKey(NotCategoryListValue))
{
Globals.Logger.User($"This flag '{NotCategoryListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.Category, GetList(features, NotCategoryListValue), true);
}
if (features.ContainsKey(CategoryListValue))
{
Globals.Logger.User($"This flag '{CategoryListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.Category, GetList(features, CategoryListValue), false);
}
// CRC // CRC
filter.CRC.NegativeSet.AddRange(GetList(features, NotCrcListValue)); if (features.ContainsKey(NotCrcListValue))
filter.CRC.PositiveSet.AddRange(GetList(features, CrcListValue)); {
Globals.Logger.User($"This flag '{NotCrcListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
// Machine description as machine name filter.SetFilter(Field.CRC, GetList(features, NotCrcListValue), true);
filter.DescriptionAsName.Neutral = GetBoolean(features, DescriptionAsNameValue); }
if (features.ContainsKey(CrcListValue))
// Include 'of" in game filters {
filter.IncludeOfInGame.Neutral = GetBoolean(features, MatchOfTagsValue); Globals.Logger.User($"This flag '{CrcListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.CRC, GetList(features, NotCrcListValue), false);
// Internal splitting }
filter.InternalSplit.Neutral = GetSplitType(features);
// Item name // Item name
filter.ItemName.NegativeSet.AddRange(GetList(features, NotItemNameListValue)); if (features.ContainsKey(NotItemNameListValue))
filter.ItemName.PositiveSet.AddRange(GetList(features, ItemNameListValue)); {
Globals.Logger.User($"This flag '{NotItemNameListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.Name, GetList(features, NotItemNameListValue), true);
}
if (features.ContainsKey(ItemNameListValue))
{
Globals.Logger.User($"This flag '{ItemNameListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.Name, GetList(features, ItemNameListValue), false);
}
// Item status // Item status
foreach (string stat in GetList(features, NotStatusListValue)) if (features.ContainsKey(NotStatusListValue))
{ {
filter.ItemStatuses.Negative |= stat.AsItemStatus(); Globals.Logger.User($"This flag '{NotStatusListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.Status, GetList(features, NotStatusListValue), true);
} }
foreach (string stat in GetList(features, StatusListValue)) if (features.ContainsKey(StatusListValue))
{ {
filter.ItemStatuses.Positive |= stat.AsItemStatus(); Globals.Logger.User($"This flag '{StatusListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.Status, GetList(features, StatusListValue), false);
} }
// Item type // Item type
filter.ItemTypes.NegativeSet.AddRange(GetList(features, NotItemTypeListValue)); if (features.ContainsKey(NotItemTypeListValue))
filter.ItemTypes.PositiveSet.AddRange(GetList(features, ItemTypeListValue)); {
Globals.Logger.User($"This flag '{NotItemTypeListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.ItemType, GetList(features, NotItemTypeListValue), true);
}
if (features.ContainsKey(ItemTypeListValue))
{
Globals.Logger.User($"This flag '{ItemTypeListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.ItemType, GetList(features, ItemTypeListValue), false);
}
// Machine description // Machine description
filter.MachineDescription.NegativeSet.AddRange(GetList(features, NotGameDescriptionListValue)); if (features.ContainsKey(NotGameDescriptionListValue))
filter.MachineDescription.PositiveSet.AddRange(GetList(features, GameDescriptionListValue)); {
Globals.Logger.User($"This flag '{NotGameDescriptionListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.Description, GetList(features, NotGameDescriptionListValue), true);
}
if (features.ContainsKey(GameDescriptionListValue))
{
Globals.Logger.User($"This flag '{GameDescriptionListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.Description, GetList(features, GameDescriptionListValue), false);
}
// Machine name // Machine name
filter.MachineName.NegativeSet.AddRange(GetList(features, NotGameNameListValue)); if (features.ContainsKey(NotGameNameListValue))
filter.MachineName.PositiveSet.AddRange(GetList(features, GameNameListValue)); {
Globals.Logger.User($"This flag '{NotGameNameListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.MachineName, GetList(features, NotGameNameListValue), true);
}
if (features.ContainsKey(GameNameListValue))
{
Globals.Logger.User($"This flag '{GameNameListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.MachineName, GetList(features, GameNameListValue), false);
}
// Machine type // Machine type
foreach (string mach in GetList(features, NotGameTypeListValue)) if (features.ContainsKey(NotGameTypeListValue))
{ {
filter.MachineTypes.Negative |= mach.AsMachineType(); Globals.Logger.User($"This flag '{NotGameTypeListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.MachineType, GetList(features, NotGameTypeListValue), true);
} }
foreach (string mach in GetList(features, GameTypeListValue)) if (features.ContainsKey(GameTypeListValue))
{ {
filter.MachineTypes.Positive |= mach.AsMachineType(); Globals.Logger.User($"This flag '{GameTypeListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.MachineType, GetList(features, GameTypeListValue), false);
} }
// MD5 // MD5
filter.MD5.NegativeSet.AddRange(GetList(features, NotMd5ListValue)); if (features.ContainsKey(NotMd5ListValue))
filter.MD5.PositiveSet.AddRange(GetList(features, Md5ListValue)); {
Globals.Logger.User($"This flag '{NotMd5ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
// Remove unicode characters filter.SetFilter(Field.MD5, GetList(features, NotMd5ListValue), true);
filter.RemoveUnicode.Neutral = GetBoolean(features, RemoveUnicodeValue); }
if (features.ContainsKey(Md5ListValue))
{
Globals.Logger.User($"This flag '{Md5ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.MD5, GetList(features, Md5ListValue), false);
}
#if NET_FRAMEWORK #if NET_FRAMEWORK
// RIPEMD160 // RIPEMD160
filter.RIPEMD160.NegativeSet.AddRange(GetList(features, NotRipeMd160ListValue)); if (features.ContainsKey(NotRipeMd160ListValue))
filter.RIPEMD160.PositiveSet.AddRange(GetList(features, RipeMd160ListValue)); {
Globals.Logger.User($"This flag '{NotRipeMd160ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.RIPEMD160, GetList(features, NotRipeMd160ListValue), true);
}
if (features.ContainsKey(RipeMd160ListValue))
{
Globals.Logger.User($"This flag '{RipeMd160ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.RIPEMD160, GetList(features, RipeMd160ListValue), false);
}
#endif #endif
// Root directory
filter.Root.Neutral = GetString(features, RootDirStringValue);
// Runnable // Runnable
if (GetBoolean(features, NotRunnableValue)) if (features.ContainsKey(NotRunnableValue))
filter.Runnable.Neutral = false; {
if (GetBoolean(features, RunnableValue)) Globals.Logger.User($"This flag '{NotRunnableValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.Runnable.Neutral = true; filter.SetFilter(Field.Runnable, string.Empty, true);
}
if (features.ContainsKey(RunnableValue))
{
Globals.Logger.User($"This flag '{RunnableValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.Runnable, string.Empty, false);
}
// SHA-1 // SHA1
filter.SHA1.NegativeSet.AddRange(GetList(features, NotSha1ListValue)); if (features.ContainsKey(NotSha1ListValue))
filter.SHA1.PositiveSet.AddRange(GetList(features, Sha1ListValue)); {
Globals.Logger.User($"This flag '{NotSha1ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.SHA1, GetList(features, NotSha1ListValue), true);
}
if (features.ContainsKey(Sha1ListValue))
{
Globals.Logger.User($"This flag '{Sha1ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.SHA1, GetList(features, Sha1ListValue), false);
}
// SHA-256 // SHA256
filter.SHA256.NegativeSet.AddRange(GetList(features, NotSha256ListValue)); if (features.ContainsKey(NotSha256ListValue))
filter.SHA256.PositiveSet.AddRange(GetList(features, Sha256ListValue)); {
Globals.Logger.User($"This flag '{NotSha256ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.SHA256, GetList(features, NotSha256ListValue), true);
}
if (features.ContainsKey(Sha256ListValue))
{
Globals.Logger.User($"This flag '{Sha256ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.SHA256, GetList(features, Sha256ListValue), false);
}
// SHA-384 // SHA384
filter.SHA384.NegativeSet.AddRange(GetList(features, NotSha384ListValue)); if (features.ContainsKey(NotSha384ListValue))
filter.SHA384.PositiveSet.AddRange(GetList(features, Sha384ListValue)); {
Globals.Logger.User($"This flag '{NotSha384ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.SHA384, GetList(features, NotSha384ListValue), true);
}
if (features.ContainsKey(Sha384ListValue))
{
Globals.Logger.User($"This flag '{Sha384ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.SHA384, GetList(features, Sha384ListValue), false);
}
// SHA-512 // SHA512
filter.SHA512.NegativeSet.AddRange(GetList(features, NotSha512ListValue)); if (features.ContainsKey(NotSha512ListValue))
filter.SHA512.PositiveSet.AddRange(GetList(features, Sha512ListValue)); {
Globals.Logger.User($"This flag '{NotSha512ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
// Single game in output filter.SetFilter(Field.SHA512, GetList(features, NotSha512ListValue), true);
filter.Single.Neutral = GetBoolean(features, SingleSetValue); }
if (features.ContainsKey(Sha512ListValue))
{
Globals.Logger.User($"This flag '{Sha512ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
filter.SetFilter(Field.SHA512, GetList(features, Sha512ListValue), false);
}
// Size // Size
filter.Size.Negative = Sanitizer.ToSize(GetString(features, LessStringValue)); if (features.ContainsKey(LessStringValue))
filter.Size.Neutral = Sanitizer.ToSize(GetString(features, EqualStringValue)); {
filter.Size.Positive = Sanitizer.ToSize(GetString(features, GreaterStringValue)); Globals.Logger.User($"This flag '{LessStringValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
var value = Sanitizer.ToSize(GetString(features, LessStringValue));
filter.SetFilter(Field.Size, $"<{value}", false);
}
if (features.ContainsKey(EqualStringValue))
{
Globals.Logger.User($"This flag '{EqualStringValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
var value = Sanitizer.ToSize(GetString(features, EqualStringValue));
filter.SetFilter(Field.Size, $"={value}", false);
}
if (features.ContainsKey(GreaterStringValue))
{
Globals.Logger.User($"This flag '{GreaterStringValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
var value = Sanitizer.ToSize(GetString(features, GreaterStringValue));
filter.SetFilter(Field.Size, $">{value}", false);
}
#endregion
#region Filter manipulation flags
// Clean names
filter.Clean = GetBoolean(features, CleanValue);
// Machine description as machine name
filter.DescriptionAsName = GetBoolean(features, DescriptionAsNameValue);
// Include 'of" in game filters
filter.IncludeOfInGame = GetBoolean(features, MatchOfTagsValue);
// Internal splitting
filter.InternalSplit = GetSplitType(features);
// Remove unicode characters
filter.RemoveUnicode = GetBoolean(features, RemoveUnicodeValue);
// Root directory
filter.Root = GetString(features, RootDirStringValue);
// Single game in output
filter.Single = GetBoolean(features, SingleSetValue);
// Trim to NTFS length // Trim to NTFS length
filter.Trim.Neutral = GetBoolean(features, TrimValue); filter.Trim = GetBoolean(features, TrimValue);
#endregion
return filter; return filter;
} }
@@ -2714,6 +2895,9 @@ Some special strings that can be used:
AddFeature(CopyFilesFlag); AddFeature(CopyFilesFlag);
AddFeature(HeaderStringInput); AddFeature(HeaderStringInput);
AddFeature(ChdsAsFilesFlag); AddFeature(ChdsAsFilesFlag);
AddFeature(FilterListInput);
AddFeature(CategoryListInput);
AddFeature(NotCategoryListInput);
AddFeature(GameNameListInput); AddFeature(GameNameListInput);
AddFeature(NotGameNameListInput); AddFeature(NotGameNameListInput);
AddFeature(GameDescriptionListInput); AddFeature(GameDescriptionListInput);
@@ -3238,6 +3422,9 @@ The stats that are outputted are as follows:
this[DiffCascadeFlag].AddFeature(SkipFirstOutputFlag); this[DiffCascadeFlag].AddFeature(SkipFirstOutputFlag);
AddFeature(DiffReverseCascadeFlag); AddFeature(DiffReverseCascadeFlag);
this[DiffReverseCascadeFlag].AddFeature(SkipFirstOutputFlag); this[DiffReverseCascadeFlag].AddFeature(SkipFirstOutputFlag);
AddFeature(FilterListInput);
AddFeature(CategoryListInput);
AddFeature(NotCategoryListInput);
AddFeature(GameNameListInput); AddFeature(GameNameListInput);
AddFeature(NotGameNameListInput); AddFeature(NotGameNameListInput);
AddFeature(GameDescriptionListInput); AddFeature(GameDescriptionListInput);
@@ -3369,6 +3556,9 @@ The stats that are outputted are as follows:
AddFeature(DatDeviceNonMergedFlag); AddFeature(DatDeviceNonMergedFlag);
AddFeature(DatNonMergedFlag); AddFeature(DatNonMergedFlag);
AddFeature(DatFullNonMergedFlag); AddFeature(DatFullNonMergedFlag);
AddFeature(FilterListInput);
AddFeature(CategoryListInput);
AddFeature(NotCategoryListInput);
AddFeature(GameNameListInput); AddFeature(GameNameListInput);
AddFeature(NotGameNameListInput); AddFeature(NotGameNameListInput);
AddFeature(GameDescriptionListInput); AddFeature(GameDescriptionListInput);