using System; using System.Collections.Generic; using System.Text.RegularExpressions; using SabreTools.Library.Data; using SabreTools.Library.DatItems; namespace SabreTools.Library.DatFiles { /// /// Represents the filtering operations that need to be performed on a set of items, usually a DAT /// public class Filter { #region Private instance variables #region Positive private List _gameNames; private List _romNames; private List _romTypes; private List _crcs; private List _md5s; private List _sha1s; private List _sha256s; private List _sha384s; private List _sha512s; private ItemStatus _itemStatuses; private MachineType _machineTypes; #endregion #region Negative private List _notGameNames; private List _notRomNames; private List _notRomTypes; private List _notCrcs; private List _notMd5s; private List _notSha1s; private List _notSha256s; private List _notSha384s; private List _notSha512s; private ItemStatus _itemNotStatuses; private MachineType _machineNotTypes; #endregion #region Neutral private long _sizeGreaterThanOrEqual; private long _sizeLessThanOrEqual; private long _sizeEqualTo; private bool _includeOfInGame; private bool? _runnable; #endregion #endregion // Private instance variables #region Pubically facing variables #region Positive public List GameNames { get { return _gameNames; } set { _gameNames = value; } } public List RomNames { get { return _romNames; } set { _romNames = value; } } public List RomTypes { get { return _romTypes; } set { _romTypes = value; } } public List CRCs { get { return _crcs; } set { _crcs = value; } } public List MD5s { get { return _md5s; } set { _md5s = value; } } public List SHA1s { get { return _sha1s; } set { _sha1s = value; } } public List SHA256s { get { return _sha256s; } set { _sha256s = value; } } public List SHA384s { get { return _sha384s; } set { _sha384s = value; } } public List SHA512s { get { return _sha512s; } set { _sha512s = value; } } public ItemStatus ItemStatuses { get { return _itemStatuses; } set { _itemStatuses = value; } } public MachineType MachineTypes { get { return _machineTypes; } set { _machineTypes = value; } } #endregion #region Negative public List NotGameNames { get { return _notGameNames; } set { _notGameNames = value; } } public List NotRomNames { get { return _notRomNames; } set { _notRomNames = value; } } public List NotRomTypes { get { return _notRomTypes; } set { _notRomTypes = value; } } public List NotCRCs { get { return _notCrcs; } set { _notCrcs = value; } } public List NotMD5s { get { return _notMd5s; } set { _notMd5s = value; } } public List NotSHA1s { get { return _notSha1s; } set { _notSha1s = value; } } public List NotSHA256s { get { return _notSha256s; } set { _notSha256s = value; } } public List NotSHA384s { get { return _notSha384s; } set { _notSha384s = value; } } public List NotSHA512s { get { return _notSha512s; } set { _notSha512s = value; } } public ItemStatus NotItemStatuses { get { return _itemNotStatuses; } set { _itemNotStatuses = value; } } public MachineType NotMachineTypes { get { return _machineNotTypes; } set { _machineNotTypes = value; } } #endregion #region Neutral public long SizeGreaterThanOrEqual { get { return _sizeGreaterThanOrEqual; } set { _sizeGreaterThanOrEqual = value; } } public long SizeLessThanOrEqual { get { return _sizeLessThanOrEqual; } set { _sizeLessThanOrEqual = value; } } public long SizeEqualTo { get { return _sizeEqualTo; } set { _sizeEqualTo = value; } } public bool IncludeOfInGame { get { return _includeOfInGame; } set { _includeOfInGame = value; } } public bool? Runnable { get { return _runnable; } set { _runnable = value; } } #endregion #endregion // Pubically facing variables #region Constructors /// /// Create an empty Filter object /// public Filter() { // Positive _gameNames = new List(); _romNames = new List(); _romTypes = new List(); _crcs = new List(); _md5s = new List(); _sha1s = new List(); _sha256s = new List(); _sha384s = new List(); _sha512s = new List(); _itemStatuses = ItemStatus.NULL; _machineTypes = MachineType.NULL; // Negative _notGameNames = new List(); _notRomNames = new List(); _notRomTypes = new List(); _notCrcs = new List(); _notMd5s = new List(); _notSha1s = new List(); _notSha256s = new List(); _notSha384s = new List(); _notSha512s = new List(); _itemNotStatuses = ItemStatus.NULL; _machineNotTypes = MachineType.NULL; // Neutral _sizeGreaterThanOrEqual = -1; _sizeLessThanOrEqual = -1; _sizeEqualTo = -1; _includeOfInGame = false; _runnable = null; } #endregion #region Instance methods /// /// Check to see if a DatItem passes the filter /// /// DatItem to check /// True if the file passed the filter, false otherwise public bool ItemPasses(DatItem item) { // If the item is null, we automatically fail it if (item == null) { return false; } // Filter on machine type if (_machineTypes != MachineType.NULL && (item.MachineType & _machineTypes) == 0) { return false; } if (_machineNotTypes != MachineType.NULL && (item.MachineType & _machineNotTypes) != 0) { return false; } // Filter on machine runability if (_runnable != null && item.Runnable != _runnable) { return false; } // Take care of Rom and Disk specific differences if (item.Type == ItemType.Rom) { Rom rom = (Rom)item; // Filter on status if (_itemStatuses != ItemStatus.NULL && (rom.ItemStatus & _itemStatuses) == 0) { return false; } if (_itemNotStatuses != ItemStatus.NULL && (rom.ItemStatus & _itemNotStatuses) != 0) { return false; } // Filter on rom size if (_sizeEqualTo != -1 && rom.Size != _sizeEqualTo) { return false; } else { if (_sizeGreaterThanOrEqual != -1 && rom.Size < _sizeGreaterThanOrEqual) { return false; } if (_sizeLessThanOrEqual != -1 && rom.Size > _sizeLessThanOrEqual) { return false; } } // Filter on CRC if (_crcs.Count > 0) { // If the CRC isn't in the list, return false if (!FindValueInList(_crcs, rom.CRC)) { return false; } } if (_notCrcs.Count > 0) { // If the CRC is in the list, return false if (FindValueInList(_notCrcs, rom.CRC)) { return false; } } // Filter on MD5 if (_md5s.Count > 0) { // If the MD5 isn't in the list, return false if (!FindValueInList(_md5s, rom.MD5)) { return false; } } if (_notMd5s.Count > 0) { // If the MD5 is in the list, return false if (FindValueInList(_notMd5s, rom.MD5)) { return false; } } // Filter on SHA1 if (_sha1s.Count > 0) { // If the SHA-1 isn't in the list, return false if (!FindValueInList(_sha1s, rom.SHA1)) { return false; } } if (_notSha1s.Count > 0) { // If the SHA-1 is in the list, return false if (FindValueInList(_notSha1s, rom.SHA1)) { return false; } } // Filter on SHA256 if (_sha256s.Count > 0) { // If the SHA-1 isn't in the list, return false if (!FindValueInList(_sha256s, rom.SHA256)) { return false; } } if (_notSha256s.Count > 0) { // If the SHA-1 is in the list, return false if (FindValueInList(_notSha256s, rom.SHA256)) { return false; } } // Filter on SHA384 if (_sha384s.Count > 0) { // If the SHA-1 isn't in the list, return false if (!FindValueInList(_sha384s, rom.SHA384)) { return false; } } if (_notSha384s.Count > 0) { // If the SHA-1 is in the list, return false if (FindValueInList(_notSha384s, rom.SHA384)) { return false; } } // Filter on SHA512 if (_sha512s.Count > 0) { // If the SHA-1 isn't in the list, return false if (!FindValueInList(_sha512s, rom.SHA512)) { return false; } } if (_notSha512s.Count > 0) { // If the SHA-1 is in the list, return false if (FindValueInList(_notSha512s, rom.SHA512)) { return false; } } } else if (item.Type == ItemType.Disk) { Disk rom = (Disk)item; // Filter on status if (_itemStatuses != ItemStatus.NULL && (rom.ItemStatus & _itemStatuses) == 0) { return false; } if (_itemNotStatuses != ItemStatus.NULL && (rom.ItemStatus & _itemNotStatuses) != 0) { return false; } // Filter on MD5 if (_md5s.Count > 0) { // If the MD5 isn't in the list, return false if (!FindValueInList(_md5s, rom.MD5)) { return false; } } if (_notMd5s.Count > 0) { // If the MD5 is in the list, return false if (FindValueInList(_notMd5s, rom.MD5)) { return false; } } // Filter on SHA1 if (_sha1s.Count > 0) { // If the SHA-1 isn't in the list, return false if (!FindValueInList(_sha1s, rom.SHA1)) { return false; } } if (_notSha1s.Count > 0) { // If the SHA-1 is in the list, return false if (FindValueInList(_notSha1s, rom.SHA1)) { return false; } } // Filter on SHA256 if (_sha256s.Count > 0) { // If the SHA-1 isn't in the list, return false if (!FindValueInList(_sha256s, rom.SHA256)) { return false; } } if (_notSha256s.Count > 0) { // If the SHA-1 is in the list, return false if (FindValueInList(_notSha256s, rom.SHA256)) { return false; } } // Filter on SHA384 if (_sha384s.Count > 0) { // If the SHA-1 isn't in the list, return false if (!FindValueInList(_sha384s, rom.SHA384)) { return false; } } if (_notSha384s.Count > 0) { // If the SHA-1 is in the list, return false if (FindValueInList(_notSha384s, rom.SHA384)) { return false; } } // Filter on SHA512 if (_sha512s.Count > 0) { // If the SHA-1 isn't in the list, return false if (!FindValueInList(_sha512s, rom.SHA512)) { return false; } } if (_notSha512s.Count > 0) { // If the SHA-1 is in the list, return false if (FindValueInList(_notSha512s, rom.SHA512)) { return false; } } } // Filter on game name if (_gameNames.Count > 0) { bool found = FindValueInList(_gameNames, item.MachineName); // If we are checking CloneOf and RomOf, add them in as well if (_includeOfInGame) { found |= FindValueInList(_gameNames, item.CloneOf); found |= FindValueInList(_gameNames, item.RomOf); } // If the game name was not found in the list, return false if (!found) { return false; } } if (_notGameNames.Count > 0) { bool found = FindValueInList(_gameNames, item.MachineName); // If we are checking CloneOf and RomOf, add them in as well if (_includeOfInGame) { found |= FindValueInList(_gameNames, item.CloneOf); found |= FindValueInList(_gameNames, item.RomOf); } // If the game name was found in the list, return false if (found) { return false; } } // Filter on rom name if (_romNames.Count > 0) { // If the rom name was not found in the list, return false if (!FindValueInList(_romNames, item.Name)) { return false; } } if (_notRomNames.Count > 0) { // If the rom name was found in the list, return false if (FindValueInList(_notRomNames, item.Name)) { return false; } } // Filter on rom type if (_romTypes.Count == 0 && _notRomTypes.Count == 0 && item.Type != ItemType.Rom && item.Type != ItemType.Disk) { return false; } if (_romTypes.Count > 0) { // If the rom type was not found in the list, return false if (!FindValueInList(_romTypes, item.Type.ToString())) { return false; } } if (_notRomTypes.Count > 0) { // If the rom type was found in the list, return false if (FindValueInList(_notRomTypes, item.Type.ToString())) { return false; } } return true; } /// /// Generic code to check if a specific value is in the list given /// /// List to search for the value in /// Value to search the list for /// True if the value could be found, false otherwise private bool FindValueInList(List haystack, string needle) { bool found = false; foreach (string straw in haystack) { if (!String.IsNullOrEmpty(straw)) { string regexStraw = straw; // If the straw has no special characters at all, treat it as an exact match if (regexStraw == Regex.Escape(regexStraw)) { regexStraw = "^" + regexStraw + "$"; } // Check if a match is found with the regex found |= Regex.IsMatch(needle, regexStraw, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); } } return found; } #endregion #region Static methods /// /// Get the machine type from a string /// /// Machine type as a string /// A machine type based on the input public static MachineType GetMachineTypeFromString(string gametype) { MachineType machineType = MachineType.NULL; switch (gametype.ToLowerInvariant()) { case "none": machineType |= MachineType.None; break; case "bios": machineType |= MachineType.Bios; break; case "dev": case "device": machineType |= MachineType.Device; break; case "mech": case "mechanical": machineType |= MachineType.Mechanical; break; default: Globals.Logger.Warning("{0} is not a valid type", gametype); break; } return machineType; } /// /// Get the item status from a string /// /// Item status as a string /// An item status based on the input public static ItemStatus GetStatusFromString(string status) { ItemStatus itemStatus = ItemStatus.NULL; switch (status.ToLowerInvariant()) { case "none": itemStatus |= ItemStatus.None; break; case "good": itemStatus |= ItemStatus.Good; break; case "baddump": itemStatus |= ItemStatus.BadDump; break; case "nodump": itemStatus |= ItemStatus.Nodump; break; case "verified": itemStatus |= ItemStatus.Verified; break; default: Globals.Logger.Warning("{0} is not a valid status", status); break; } return itemStatus; } #endregion } }