using System; using System.Collections.Generic; using SabreTools.Library.Data; using SabreTools.Library.DatItems; #if MONO using System.IO; #else using Alphaleonis.Win32.Filesystem; #endif namespace SabreTools.Library.DatFiles { /// /// Represents the filtering operations that need to be performed on a set of items, usually a DAT /// public partial class Filter { #region Pubically facing variables /// /// Include or exclude machine names /// public FilterItem MachineName { get; set; } = new FilterItem(); /// /// Include or exclude machine descriptions /// public FilterItem MachineDescription { get; set; } = new FilterItem(); /// /// Include or exclude item names /// public FilterItem ItemName { get; set; } = new FilterItem(); /// /// Include or exclude item types /// public FilterItem ItemTypes { get; set; } = new FilterItem(); /// /// Include or exclude CRC32 hashes /// public FilterItem CRC { get; set; } = new FilterItem(); /// /// Include or exclude MD5 hashes /// public FilterItem MD5 { get; set; } = new FilterItem(); /// /// Include or exclude SHA-1 hashes /// public FilterItem SHA1 { get; set; } = new FilterItem(); /// /// Include or exclude SHA-256 hashes /// public FilterItem SHA256 { get; set; } = new FilterItem(); /// /// Include or exclude SHA-384 hashes /// public FilterItem SHA384 { get; set; } = new FilterItem(); /// /// Include or exclude SHA-512 hashes /// public FilterItem SHA512 { get; set; } = new FilterItem(); /// /// Include or exclude item statuses /// public FilterItem ItemStatuses { get; set; } = new FilterItem() { Positive = ItemStatus.NULL, Negative = ItemStatus.NULL }; /// /// Include or exclude machine types /// public FilterItem MachineTypes { get; set; } = new FilterItem() { Positive = MachineType.NULL, Negative = MachineType.NULL }; /// /// Include or exclude item sizes /// /// Positive means "Greater than or equal", Negative means "Less than or equal", Neutral means "Equal" public FilterItem Size { get; set; } = new FilterItem() { Positive = -1, Negative = -1, Neutral = -1 }; /// /// Include romof and cloneof when filtering machine names /// public FilterItem IncludeOfInGame { get; set; } = new FilterItem() { Neutral = false }; /// /// Include or exclude items with the "Runnable" tag /// public FilterItem Runnable { get; set; } = new FilterItem() { Neutral = null }; /// /// Change all machine names to "!" /// public FilterItem Single { get; set; } = new FilterItem() { Neutral = false }; /// /// Trim total machine and item name to not exceed NTFS limits /// public FilterItem Trim { get; set; } = new FilterItem() { Neutral = false }; /// /// Include root directory when determing trim sizes /// public FilterItem Root { get; set; } = new FilterItem() { Neutral = null }; #endregion // Pubically facing variables #region Instance methods /// /// Filter a DatFile using the inputs /// /// /// True if the DatFile was filtered, false on error public bool FilterDatFile(DatFile datFile) { try { // Loop over every key in the dictionary List keys = datFile.Keys; foreach (string key in keys) { // For every item in the current key List items = datFile[key]; List newitems = new List(); foreach (DatItem item in items) { // If the rom passes the filter, include it if (ItemPasses(item)) { // If we are in single game mode, rename all games if (this.Single.Neutral) item.MachineName = "!"; // If we are in NTFS trim mode, trim the game name if (this.Trim.Neutral) { // Windows max name length is 260 int usableLength = 260 - item.MachineName.Length - this.Root.Neutral.Length; if (item.Name.Length > usableLength) { string ext = Path.GetExtension(item.Name); item.Name = item.Name.Substring(0, usableLength - ext.Length); item.Name += ext; } } // Lock the list and add the item back lock (newitems) { newitems.Add(item); } } } datFile.Remove(key); datFile.AddRange(key, newitems); } } catch (Exception ex) { Globals.Logger.Error(ex.ToString()); return false; } return true; } /// /// 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 (!this.MachineTypes.MatchesPositive(MachineType.NULL, item.MachineType)) return false; if (this.MachineTypes.MatchesNegative(MachineType.NULL, item.MachineType)) return false; // Filter on machine runability if (!this.Runnable.MatchesNeutral(null, item.Runnable)) return false; // Take care of Rom and Disk specific differences if (item.ItemType == ItemType.Rom) { Rom rom = (Rom)item; // Filter on status if (!this.ItemStatuses.MatchesPositive(ItemStatus.NULL, rom.ItemStatus)) return false; if (this.ItemStatuses.MatchesNegative(ItemStatus.NULL, rom.ItemStatus)) return false; // Filter on rom size if (!this.Size.MatchesNeutral(-1, rom.Size)) return false; else if (!this.Size.MatchesPositive(-1, rom.Size)) return false; else if (!this.Size.MatchesNegative(-1, rom.Size)) return false; // Filter on CRC if (!this.CRC.MatchesPositiveSet(rom.CRC)) return false; if (this.CRC.MatchesNegativeSet(rom.CRC)) return false; // Filter on MD5 if (!this.MD5.MatchesPositiveSet(rom.MD5)) return false; if (this.MD5.MatchesNegativeSet(rom.MD5)) return false; // Filter on SHA-1 if (!this.SHA1.MatchesPositiveSet(rom.SHA1)) return false; if (this.SHA1.MatchesNegativeSet(rom.SHA1)) return false; // Filter on SHA-256 if (!this.SHA256.MatchesPositiveSet(rom.SHA256)) return false; if (this.SHA256.MatchesNegativeSet(rom.SHA256)) return false; // Filter on SHA-384 if (!this.SHA384.MatchesPositiveSet(rom.SHA384)) return false; if (this.SHA384.MatchesNegativeSet(rom.SHA384)) return false; // Filter on SHA-512 if (!this.SHA512.MatchesPositiveSet(rom.SHA512)) return false; if (this.SHA512.MatchesNegativeSet(rom.SHA512)) return false; } else if (item.ItemType == ItemType.Disk) { Disk rom = (Disk)item; // Filter on status if (!this.ItemStatuses.MatchesPositive(ItemStatus.NULL, rom.ItemStatus)) return false; if (this.ItemStatuses.MatchesNegative(ItemStatus.NULL, rom.ItemStatus)) return false; // Filter on MD5 if (!this.MD5.MatchesPositiveSet(rom.MD5)) return false; if (this.MD5.MatchesNegativeSet(rom.MD5)) return false; // Filter on SHA-1 if (!this.SHA1.MatchesPositiveSet(rom.SHA1)) return false; if (this.SHA1.MatchesNegativeSet(rom.SHA1)) return false; // Filter on SHA-256 if (!this.SHA256.MatchesPositiveSet(rom.SHA256)) return false; if (this.SHA256.MatchesNegativeSet(rom.SHA256)) return false; // Filter on SHA-384 if (!this.SHA384.MatchesPositiveSet(rom.SHA384)) return false; if (this.SHA384.MatchesNegativeSet(rom.SHA384)) return false; // Filter on SHA-512 if (!this.SHA512.MatchesPositiveSet(rom.SHA512)) return false; if (this.SHA512.MatchesNegativeSet(rom.SHA512)) return false; } // Filter on machine name bool machineNameFound = this.MachineName.MatchesPositiveSet(item.MachineName); if (this.IncludeOfInGame.Neutral) { machineNameFound |= this.MachineName.MatchesPositiveSet(item.CloneOf); machineNameFound |= this.MachineName.MatchesPositiveSet(item.RomOf); } if (!machineNameFound) return false; machineNameFound = this.MachineName.MatchesNegativeSet(item.MachineName); if (this.IncludeOfInGame.Neutral) { machineNameFound |= this.MachineName.MatchesNegativeSet(item.CloneOf); machineNameFound |= this.MachineName.MatchesNegativeSet(item.RomOf); } if (machineNameFound) return false; // Filter on machine description if (!this.MachineDescription.MatchesPositiveSet(item.MachineDescription)) return false; if (this.MachineDescription.MatchesNegativeSet(item.MachineDescription)) return false; // Filter on item name if (!this.ItemName.MatchesPositiveSet(item.Name)) return false; if (this.ItemName.MatchesNegativeSet(item.Name)) return false; // Filter on item type if (this.ItemTypes.PositiveSet.Count == 0 && this.ItemTypes.NegativeSet.Count == 0 && item.ItemType != ItemType.Rom && item.ItemType != ItemType.Disk && item.ItemType != ItemType.Blank) return false; if (!this.ItemTypes.MatchesPositiveSet(item.ItemType.ToString())) return false; if (this.ItemTypes.MatchesNegativeSet(item.ItemType.ToString())) return false; return true; } #endregion } }