using System; using System.Collections.Generic; using SabreTools.Library.DatItems; using SabreTools.Library.Logging; using SabreTools.Library.Tools; namespace SabreTools.Library.Filtering { /// /// Represents the filtering operations that need to be performed on a set of items, usually a DAT /// /// TODO: Can clever use of Filtering allow for easier external splitting methods? public class Filter { #region Fields #region Machine Filters #region Common public FilterItem Machine_Name { get; private set; } = new FilterItem(); public FilterItem Machine_Comment { get; private set; } = new FilterItem(); public FilterItem Machine_Description { get; private set; } = new FilterItem(); public FilterItem Machine_Year { get; private set; } = new FilterItem(); public FilterItem Machine_Manufacturer { get; private set; } = new FilterItem(); public FilterItem Machine_Publisher { get; private set; } = new FilterItem(); public FilterItem Machine_Category { get; private set; } = new FilterItem(); public FilterItem Machine_RomOf { get; private set; } = new FilterItem(); public FilterItem Machine_CloneOf { get; private set; } = new FilterItem(); public FilterItem Machine_SampleOf { get; private set; } = new FilterItem(); public FilterItem Machine_Type { get; private set; } = new FilterItem() { Positive = 0x0, Negative = 0x0 }; #endregion #region AttractMode public FilterItem Machine_Players { get; private set; } = new FilterItem(); public FilterItem Machine_Rotation { get; private set; } = new FilterItem(); public FilterItem Machine_Control { get; private set; } = new FilterItem(); public FilterItem Machine_Status { get; private set; } = new FilterItem(); public FilterItem Machine_DisplayCount { get; private set; } = new FilterItem(); public FilterItem Machine_DisplayType { get; private set; } = new FilterItem(); public FilterItem Machine_Buttons { get; private set; } = new FilterItem(); #endregion #region ListXML public FilterItem Machine_SourceFile { get; private set; } = new FilterItem(); public FilterItem Machine_Runnable { get; private set; } = new FilterItem() { Positive = Runnable.NULL, Negative = Runnable.NULL }; #endregion #region Logiqx public FilterItem Machine_Board { get; private set; } = new FilterItem(); public FilterItem Machine_RebuildTo { get; private set; } = new FilterItem(); #endregion #region Logiqx EmuArc public FilterItem Machine_TitleID { get; private set; } = new FilterItem(); public FilterItem Machine_Developer { get; private set; } = new FilterItem(); public FilterItem Machine_Genre { get; private set; } = new FilterItem(); public FilterItem Machine_Subgenre { get; private set; } = new FilterItem(); public FilterItem Machine_Ratings { get; private set; } = new FilterItem(); public FilterItem Machine_Score { get; private set; } = new FilterItem(); public FilterItem Machine_Enabled { get; private set; } = new FilterItem(); public FilterItem Machine_CRC { get; private set; } = new FilterItem() { Neutral = null }; public FilterItem Machine_RelatedTo { get; private set; } = new FilterItem(); #endregion #region OpenMSX public FilterItem Machine_GenMSXID { get; private set; } = new FilterItem(); public FilterItem Machine_System { get; private set; } = new FilterItem(); public FilterItem Machine_Country { get; private set; } = new FilterItem(); #endregion #region SoftwareList public FilterItem Machine_Supported { get; private set; } = new FilterItem() { Positive = Supported.NULL, Negative = Supported.NULL }; #endregion #endregion // Machine Filters #region DatItem Filters #region Common public FilterItem DatItem_Type { get; private set; } = new FilterItem(); #endregion #region Item-Specific #region Actionable // Rom public FilterItem DatItem_Name { get; private set; } = new FilterItem(); public FilterItem DatItem_Bios { get; private set; } = new FilterItem(); public FilterItem DatItem_Size { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_CRC { get; private set; } = new FilterItem(); public FilterItem DatItem_MD5 { get; private set; } = new FilterItem(); #if NET_FRAMEWORK public FilterItem DatItem_RIPEMD160 { get; private set; } = new FilterItem(); #endif public FilterItem DatItem_SHA1 { get; private set; } = new FilterItem(); public FilterItem DatItem_SHA256 { get; private set; } = new FilterItem(); public FilterItem DatItem_SHA384 { get; private set; } = new FilterItem(); public FilterItem DatItem_SHA512 { get; private set; } = new FilterItem(); public FilterItem DatItem_SpamSum { get; private set; } = new FilterItem(); public FilterItem DatItem_Merge { get; private set; } = new FilterItem(); public FilterItem DatItem_Region { get; private set; } = new FilterItem(); public FilterItem DatItem_Offset { get; private set; } = new FilterItem(); public FilterItem DatItem_Date { get; private set; } = new FilterItem(); public FilterItem DatItem_Status { get; private set; } = new FilterItem() { Positive = ItemStatus.NULL, Negative = ItemStatus.NULL }; public FilterItem DatItem_Optional { get; private set; } = new FilterItem() { Neutral = null }; public FilterItem DatItem_Inverted { get; private set; } = new FilterItem(); // Rom (AttractMode) public FilterItem DatItem_AltName { get; private set; } = new FilterItem(); public FilterItem DatItem_AltTitle { get; private set; } = new FilterItem(); // Rom (OpenMSX) public FilterItem DatItem_Original { get; private set; } = new FilterItem(); public FilterItem DatItem_OpenMSXSubType { get; private set; } = new FilterItem() { Positive = OpenMSXSubType.NULL, Negative = OpenMSXSubType.NULL }; public FilterItem DatItem_OpenMSXType { get; private set; } = new FilterItem(); public FilterItem DatItem_Remark { get; private set; } = new FilterItem(); public FilterItem DatItem_Boot { get; private set; } = new FilterItem(); // Rom (SoftwareList) public FilterItem DatItem_LoadFlag { get; private set; } = new FilterItem() { Positive = LoadFlag.NULL, Negative = LoadFlag.NULL }; public FilterItem DatItem_Value { get; private set; } = new FilterItem(); // Disk public FilterItem DatItem_Index { get; private set; } = new FilterItem(); public FilterItem DatItem_Writable { get; private set; } = new FilterItem() { Neutral = null }; #endregion #region Auxiliary // Adjuster public FilterItem DatItem_Default { get; private set; } = new FilterItem() { Neutral = null }; // Analog public FilterItem DatItem_Analog_Mask { get; private set; } = new FilterItem(); // BiosSet public FilterItem DatItem_Description { get; private set; } = new FilterItem(); // Chip public FilterItem DatItem_Tag { get; private set; } = new FilterItem(); public FilterItem DatItem_ChipType { get; private set; } = new FilterItem() { Positive = ChipType.NULL, Negative = ChipType.NULL }; public FilterItem DatItem_Clock { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; // Condition public FilterItem DatItem_Mask { get; private set; } = new FilterItem(); public FilterItem DatItem_Relation { get; private set; } = new FilterItem() { Positive = Relation.NULL, Negative = Relation.NULL }; public FilterItem DatItem_Condition_Tag { get; private set; } = new FilterItem(); public FilterItem DatItem_Condition_Mask { get; private set; } = new FilterItem(); public FilterItem DatItem_Condition_Relation { get; private set; } = new FilterItem() { Positive = Relation.NULL, Negative = Relation.NULL }; public FilterItem DatItem_Condition_Value { get; private set; } = new FilterItem(); // Control public FilterItem DatItem_Control_Type { get; private set; } = new FilterItem() { Positive = ControlType.NULL, Negative = ControlType.NULL }; public FilterItem DatItem_Control_Player { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_Control_Buttons { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_Control_ReqButtons { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_Control_Minimum { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_Control_Maximum { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_Control_Sensitivity { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_Control_KeyDelta { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_Control_Reverse { get; private set; } = new FilterItem() { Neutral = null }; public FilterItem DatItem_Control_Ways { get; private set; } = new FilterItem(); public FilterItem DatItem_Control_Ways2 { get; private set; } = new FilterItem(); public FilterItem DatItem_Control_Ways3 { get; private set; } = new FilterItem(); // DataArea public FilterItem DatItem_AreaName { get; private set; } = new FilterItem(); public FilterItem DatItem_AreaSize { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_AreaWidth { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_AreaEndianness { get; private set; } = new FilterItem() { Positive = Endianness.NULL, Negative = Endianness.NULL }; // Device public FilterItem DatItem_DeviceType { get; private set; } = new FilterItem() { Positive = DeviceType.NULL, Negative = DeviceType.NULL }; public FilterItem DatItem_FixedImage { get; private set; } = new FilterItem(); public FilterItem DatItem_Mandatory { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_Interface { get; private set; } = new FilterItem(); // Display public FilterItem DatItem_DisplayType { get; private set; } = new FilterItem() { Positive = DisplayType.NULL, Negative = DisplayType.NULL }; public FilterItem DatItem_Rotate { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_FlipX { get; private set; } = new FilterItem() { Neutral = null }; public FilterItem DatItem_Width { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_Height { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_Refresh { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_PixClock { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_HTotal { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_HBEnd { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_HBStart { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_VTotal { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_VBEnd { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_VBStart { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; // Driver public FilterItem DatItem_SupportStatus { get; private set; } = new FilterItem() { Positive = SupportStatus.NULL, Negative = SupportStatus.NULL }; public FilterItem DatItem_EmulationStatus { get; private set; } = new FilterItem() { Positive = SupportStatus.NULL, Negative = SupportStatus.NULL }; public FilterItem DatItem_CocktailStatus { get; private set; } = new FilterItem() { Positive = SupportStatus.NULL, Negative = SupportStatus.NULL }; public FilterItem DatItem_SaveStateStatus { get; private set; } = new FilterItem() { Positive = Supported.NULL, Negative = Supported.NULL }; // Extension public FilterItem DatItem_Extension_Name { get; private set; } = new FilterItem(); // Feature public FilterItem DatItem_FeatureType { get; private set; } = new FilterItem() { Positive = FeatureType.NULL, Negative = FeatureType.NULL }; public FilterItem DatItem_FeatureStatus { get; private set; } = new FilterItem() { Positive = FeatureStatus.NULL, Negative = FeatureStatus.NULL }; public FilterItem DatItem_FeatureOverall { get; private set; } = new FilterItem() { Positive = FeatureStatus.NULL, Negative = FeatureStatus.NULL }; // Input public FilterItem DatItem_Service { get; private set; } = new FilterItem() { Neutral = null }; public FilterItem DatItem_Tilt { get; private set; } = new FilterItem() { Neutral = null }; public FilterItem DatItem_Players { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_Coins { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; // Instance public FilterItem DatItem_Instance_Name { get; private set; } = new FilterItem(); public FilterItem DatItem_Instance_BriefName { get; private set; } = new FilterItem(); // Location public FilterItem DatItem_Location_Name { get; private set; } = new FilterItem(); public FilterItem DatItem_Location_Number { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem DatItem_Location_Inverted { get; private set; } = new FilterItem() { Neutral = null }; // Part public FilterItem DatItem_Part_Name { get; private set; } = new FilterItem(); public FilterItem DatItem_Part_Interface { get; private set; } = new FilterItem(); // PartFeature public FilterItem DatItem_Part_Feature_Name { get; private set; } = new FilterItem(); public FilterItem DatItem_Part_Feature_Value { get; private set; } = new FilterItem(); // RamOption public FilterItem DatItem_Content { get; private set; } = new FilterItem(); // Release public FilterItem DatItem_Language { get; private set; } = new FilterItem(); // Setting public FilterItem DatItem_Setting_Name { get; private set; } = new FilterItem(); public FilterItem DatItem_Setting_Value { get; private set; } = new FilterItem(); public FilterItem DatItem_Setting_Default { get; private set; } = new FilterItem() { Neutral = null }; // SlotOption public FilterItem DatItem_SlotOption_Name { get; private set; } = new FilterItem(); public FilterItem DatItem_SlotOption_DeviceName { get; private set; } = new FilterItem(); public FilterItem DatItem_SlotOption_Default { get; private set; } = new FilterItem() { Neutral = null }; // SoftwareList public FilterItem DatItem_SoftwareListStatus { get; private set; } = new FilterItem() { Positive = SoftwareListStatus.NULL, Negative = SoftwareListStatus.NULL }; public FilterItem DatItem_Filter { get; private set; } = new FilterItem(); // Sound public FilterItem DatItem_Channels { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; #endregion #endregion // Item-Specific #endregion // DatItem Filters #region Additional Flags /// /// Include romof and cloneof when filtering machine names /// public bool IncludeOfInGame { get; set; } #endregion #endregion // Fields #region Logging /// /// Logging object /// private readonly Logger logger; #endregion #region Instance methods #region Constructors /// /// Constructor /// public Filter() { logger = new Logger(this); } #endregion #region Filter Population /// /// Populate the filters object using a set of key:value filters /// /// List of key:value where ~key/!key is negated public void PopulateFromList(List filters) { foreach (string filterPair in filters) { // If we don't even have a possible filter pair if (!filterPair.Contains(":")) { logger.Warning($"'{filterPair}` is not a valid filter string. Valid filter strings are of the form 'key:value'. Please refer to README.1ST or the help feature for more details."); continue; } string filterPairTrimmed = filterPair.Trim('"', ' ', '\t'); bool negate = filterPairTrimmed.StartsWith("!") || filterPairTrimmed.StartsWith("~") || filterPairTrimmed.StartsWith("not-"); filterPairTrimmed = filterPairTrimmed.TrimStart('!', '~'); filterPairTrimmed = filterPairTrimmed.StartsWith("not-") ? filterPairTrimmed.Substring(4) : filterPairTrimmed; string filterFieldString = filterPairTrimmed.Split(':')[0].ToLowerInvariant().Trim('"', ' ', '\t'); string filterValue = filterPairTrimmed.Substring(filterFieldString.Length + 1).Trim('"', ' ', '\t'); Field filterField = filterFieldString.AsField(); SetFilter(filterField, filterValue, negate); } } /// /// Set multiple filters from key /// /// Key for the filter to be set /// List of values for the filter /// True if negative filter, false otherwise public void SetFilter(Field key, List values, bool negate) { foreach (string value in values) { SetFilter(key, value, negate); } } /// /// Set a single filter from key /// /// Key for the filter to be set /// Value of the filter /// True if negative filter, false otherwise public void SetFilter(Field key, string value, bool negate) { switch (key) { #region Machine Filters #region Common case Field.Machine_Name: SetStringFilter(Machine_Name, value, negate); break; case Field.Machine_Comment: SetStringFilter(Machine_Comment, value, negate); break; case Field.Machine_Description: SetStringFilter(Machine_Description, value, negate); break; case Field.Machine_Year: SetStringFilter(Machine_Year, value, negate); break; case Field.Machine_Manufacturer: SetStringFilter(Machine_Manufacturer, value, negate); break; case Field.Machine_Publisher: SetStringFilter(Machine_Publisher, value, negate); break; case Field.Machine_Category: SetStringFilter(Machine_Category, value, negate); break; case Field.Machine_RomOf: SetStringFilter(Machine_RomOf, value, negate); break; case Field.Machine_CloneOf: SetStringFilter(Machine_CloneOf, value, negate); break; case Field.Machine_SampleOf: SetStringFilter(Machine_SampleOf, value, negate); break; case Field.Machine_Type: if (negate) Machine_Type.Negative |= value.AsMachineType(); else Machine_Type.Positive |= value.AsMachineType(); break; #endregion #region AttractMode case Field.Machine_Players: SetStringFilter(Machine_Players, value, negate); break; case Field.Machine_Rotation: SetStringFilter(Machine_Rotation, value, negate); break; case Field.Machine_Control: SetStringFilter(Machine_Control, value, negate); break; case Field.Machine_Status: SetStringFilter(Machine_Status, value, negate); break; case Field.Machine_DisplayCount: SetStringFilter(Machine_DisplayCount, value, negate); break; case Field.Machine_DisplayType: SetStringFilter(Machine_DisplayType, value, negate); break; case Field.Machine_Buttons: SetStringFilter(Machine_Buttons, value, negate); break; #endregion #region ListXML case Field.Machine_SourceFile: SetStringFilter(Machine_SourceFile, value, negate); break; case Field.Machine_Runnable: if (negate) Machine_Runnable.Negative |= value.AsRunnable(); else Machine_Runnable.Positive |= value.AsRunnable(); break; #endregion #region Logiqx case Field.Machine_Board: SetStringFilter(Machine_Board, value, negate); break; case Field.Machine_RebuildTo: SetStringFilter(Machine_RebuildTo, value, negate); break; #endregion #region Logiqx EmuArc case Field.Machine_TitleID: SetStringFilter(Machine_TitleID, value, negate); break; case Field.Machine_Developer: SetStringFilter(Machine_Developer, value, negate); break; case Field.Machine_Genre: SetStringFilter(Machine_Genre, value, negate); break; case Field.Machine_Subgenre: SetStringFilter(Machine_Subgenre, value, negate); break; case Field.Machine_Ratings: SetStringFilter(Machine_Ratings, value, negate); break; case Field.Machine_Score: SetStringFilter(Machine_Score, value, negate); break; case Field.Machine_Enabled: SetStringFilter(Machine_Enabled, value, negate); break; case Field.Machine_CRC: SetBooleanFilter(Machine_CRC, value, negate); break; case Field.Machine_RelatedTo: SetStringFilter(Machine_RelatedTo, value, negate); break; #endregion #region OpenMSX case Field.Machine_GenMSXID: SetStringFilter(Machine_GenMSXID, value, negate); break; case Field.Machine_System: SetStringFilter(Machine_System, value, negate); break; case Field.Machine_Country: SetStringFilter(Machine_Country, value, negate); break; #endregion #region SoftwareList case Field.Machine_Supported: if (negate) Machine_Supported.Negative |= value.AsSupported(); else Machine_Supported.Positive |= value.AsSupported(); break; #endregion #endregion // Machine Filters #region DatItem Filters #region Common case Field.DatItem_Type: if (value.AsItemType() == null) return; SetStringFilter(DatItem_Type, value, negate); break; #endregion #region Item-Specific #region Actionable // Rom case Field.DatItem_Name: SetStringFilter(DatItem_Name, value, negate); break; case Field.DatItem_Bios: SetStringFilter(DatItem_Bios, value, negate); break; case Field.DatItem_Size: SetLongFilter(DatItem_Size, value, negate); break; case Field.DatItem_CRC: SetStringFilter(DatItem_CRC, value, negate); break; case Field.DatItem_MD5: SetStringFilter(DatItem_MD5, value, negate); break; #if NET_FRAMEWORK case Field.DatItem_RIPEMD160: SetStringFilter(DatItem_RIPEMD160, value, negate); break; #endif case Field.DatItem_SHA1: SetStringFilter(DatItem_SHA1, value, negate); break; case Field.DatItem_SHA256: SetStringFilter(DatItem_SHA256, value, negate); break; case Field.DatItem_SHA384: SetStringFilter(DatItem_SHA384, value, negate); break; case Field.DatItem_SHA512: SetStringFilter(DatItem_SHA512, value, negate); break; case Field.DatItem_SpamSum: SetStringFilter(DatItem_SpamSum, value, negate); break; case Field.DatItem_Merge: SetStringFilter(DatItem_Merge, value, negate); break; case Field.DatItem_Region: SetStringFilter(DatItem_Region, value, negate); break; case Field.DatItem_Offset: SetStringFilter(DatItem_Offset, value, negate); break; case Field.DatItem_Date: SetStringFilter(DatItem_Date, value, negate); break; case Field.DatItem_Status: if (negate) DatItem_Status.Negative |= value.AsItemStatus(); else DatItem_Status.Positive |= value.AsItemStatus(); break; case Field.DatItem_Optional: SetBooleanFilter(DatItem_Optional, value, negate); break; case Field.DatItem_Inverted: SetBooleanFilter(DatItem_Inverted, value, negate); break; // Rom (AttractMode) case Field.DatItem_AltName: SetStringFilter(DatItem_AltName, value, negate); break; case Field.DatItem_AltTitle: SetStringFilter(DatItem_AltTitle, value, negate); break; // Rom (OpenMSX) case Field.DatItem_Original: SetStringFilter(DatItem_Original, value, negate); break; case Field.DatItem_OpenMSXSubType: if (negate) DatItem_OpenMSXSubType.Negative |= value.AsOpenMSXSubType(); else DatItem_OpenMSXSubType.Positive |= value.AsOpenMSXSubType(); break; case Field.DatItem_OpenMSXType: SetStringFilter(DatItem_OpenMSXType, value, negate); break; case Field.DatItem_Remark: SetStringFilter(DatItem_Remark, value, negate); break; case Field.DatItem_Boot: SetStringFilter(DatItem_Boot, value, negate); break; // Rom (SoftwareList) case Field.DatItem_LoadFlag: if (negate) DatItem_LoadFlag.Negative |= value.AsLoadFlag(); else DatItem_LoadFlag.Positive |= value.AsLoadFlag(); break; case Field.DatItem_Value: SetStringFilter(DatItem_Value, value, negate); break; // Disk case Field.DatItem_Index: SetStringFilter(DatItem_Index, value, negate); break; case Field.DatItem_Writable: SetBooleanFilter(DatItem_Writable, value, negate); break; #endregion #region Auxiliary // Adjuster case Field.DatItem_Default: SetBooleanFilter(DatItem_Default, value, negate); break; // Analog case Field.DatItem_Analog_Mask: SetStringFilter(DatItem_Analog_Mask, value, negate); break; // BiosSet case Field.DatItem_Description: SetStringFilter(DatItem_Description, value, negate); break; // Chip case Field.DatItem_Tag: SetStringFilter(DatItem_Tag, value, negate); break; case Field.DatItem_ChipType: if (negate) DatItem_ChipType.Negative |= value.AsChipType(); else DatItem_ChipType.Positive |= value.AsChipType(); break; case Field.DatItem_Clock: SetLongFilter(DatItem_Clock, value, negate); break; // Condition case Field.DatItem_Mask: SetStringFilter(DatItem_Mask, value, negate); break; case Field.DatItem_Relation: if (negate) DatItem_Relation.Negative |= value.AsRelation(); else DatItem_Relation.Positive |= value.AsRelation(); break; case Field.DatItem_Condition_Tag: SetStringFilter(DatItem_Condition_Tag, value, negate); break; case Field.DatItem_Condition_Mask: SetStringFilter(DatItem_Condition_Mask, value, negate); break; case Field.DatItem_Condition_Relation: if (negate) DatItem_Condition_Relation.Negative |= value.AsRelation(); else DatItem_Condition_Relation.Positive |= value.AsRelation(); break; case Field.DatItem_Condition_Value: SetStringFilter(DatItem_Condition_Value, value, negate); break; // Control case Field.DatItem_Control_Type: if (negate) DatItem_Control_Type.Negative |= value.AsControlType(); else DatItem_Control_Type.Positive |= value.AsControlType(); break; case Field.DatItem_Control_Player: SetLongFilter(DatItem_Control_Player, value, negate); break; case Field.DatItem_Control_Buttons: SetLongFilter(DatItem_Control_Buttons, value, negate); break; case Field.DatItem_Control_RequiredButtons: SetLongFilter(DatItem_Control_ReqButtons, value, negate); break; case Field.DatItem_Control_Minimum: SetLongFilter(DatItem_Control_Minimum, value, negate); break; case Field.DatItem_Control_Maximum: SetLongFilter(DatItem_Control_Maximum, value, negate); break; case Field.DatItem_Control_Sensitivity: SetLongFilter(DatItem_Control_Sensitivity, value, negate); break; case Field.DatItem_Control_KeyDelta: SetLongFilter(DatItem_Control_KeyDelta, value, negate); break; case Field.DatItem_Control_Reverse: SetBooleanFilter(DatItem_Control_Reverse, value, negate); break; case Field.DatItem_Control_Ways: SetStringFilter(DatItem_Control_Ways, value, negate); break; case Field.DatItem_Control_Ways2: SetStringFilter(DatItem_Control_Ways2, value, negate); break; case Field.DatItem_Control_Ways3: SetStringFilter(DatItem_Control_Ways3, value, negate); break; // DataArea case Field.DatItem_AreaName: SetStringFilter(DatItem_AreaName, value, negate); break; case Field.DatItem_AreaSize: SetLongFilter(DatItem_AreaSize, value, negate); break; case Field.DatItem_AreaWidth: SetLongFilter(DatItem_AreaWidth, value, negate); break; case Field.DatItem_AreaEndianness: if (negate) DatItem_AreaEndianness.Negative |= value.AsEndianness(); else DatItem_AreaEndianness.Positive |= value.AsEndianness(); break; // Device case Field.DatItem_DeviceType: if (negate) DatItem_DeviceType.Negative |= value.AsDeviceType(); else DatItem_DeviceType.Positive |= value.AsDeviceType(); break; case Field.DatItem_FixedImage: SetStringFilter(DatItem_FixedImage, value, negate); break; case Field.DatItem_Mandatory: SetLongFilter(DatItem_Mandatory, value, negate); break; case Field.DatItem_Interface: SetStringFilter(DatItem_Interface, value, negate); break; // Display case Field.DatItem_DisplayType: if (negate) DatItem_DisplayType.Negative |= value.AsDisplayType(); else DatItem_DisplayType.Positive |= value.AsDisplayType(); break; case Field.DatItem_Rotate: SetLongFilter(DatItem_Rotate, value, negate); break; case Field.DatItem_FlipX: SetBooleanFilter(DatItem_FlipX, value, negate); break; case Field.DatItem_Width: SetLongFilter(DatItem_Width, value, negate); break; case Field.DatItem_Height: SetLongFilter(DatItem_Height, value, negate); break; case Field.DatItem_Refresh: SetDoubleFilter(DatItem_Refresh, value, negate); break; case Field.DatItem_PixClock: SetLongFilter(DatItem_PixClock, value, negate); break; case Field.DatItem_HTotal: SetLongFilter(DatItem_HTotal, value, negate); break; case Field.DatItem_HBEnd: SetLongFilter(DatItem_HBEnd, value, negate); break; case Field.DatItem_HBStart: SetLongFilter(DatItem_HBStart, value, negate); break; case Field.DatItem_VTotal: SetLongFilter(DatItem_VTotal, value, negate); break; case Field.DatItem_VBEnd: SetLongFilter(DatItem_VBEnd, value, negate); break; case Field.DatItem_VBStart: SetLongFilter(DatItem_VBStart, value, negate); break; // Driver case Field.DatItem_SupportStatus: if (negate) DatItem_SupportStatus.Negative |= value.AsSupportStatus(); else DatItem_SupportStatus.Positive |= value.AsSupportStatus(); break; case Field.DatItem_EmulationStatus: if (negate) DatItem_EmulationStatus.Negative |= value.AsSupportStatus(); else DatItem_EmulationStatus.Positive |= value.AsSupportStatus(); break; case Field.DatItem_CocktailStatus: if (negate) DatItem_CocktailStatus.Negative |= value.AsSupportStatus(); else DatItem_CocktailStatus.Positive |= value.AsSupportStatus(); break; case Field.DatItem_SaveStateStatus: if (negate) DatItem_SaveStateStatus.Negative |= value.AsSupported(); else DatItem_SaveStateStatus.Positive |= value.AsSupported(); break; // Extension case Field.DatItem_Extension_Name: SetStringFilter(DatItem_Extension_Name, value, negate); break; // Feature case Field.DatItem_FeatureType: if (negate) DatItem_FeatureType.Negative |= value.AsFeatureType(); else DatItem_FeatureType.Positive |= value.AsFeatureType(); break; case Field.DatItem_FeatureStatus: if (negate) DatItem_FeatureStatus.Negative |= value.AsFeatureStatus(); else DatItem_FeatureStatus.Positive |= value.AsFeatureStatus(); break; case Field.DatItem_FeatureOverall: if (negate) DatItem_FeatureOverall.Negative |= value.AsFeatureStatus(); else DatItem_FeatureOverall.Positive |= value.AsFeatureStatus(); break; // Input case Field.DatItem_Service: SetBooleanFilter(DatItem_Service, value, negate); break; case Field.DatItem_Tilt: SetBooleanFilter(DatItem_Tilt, value, negate); break; case Field.DatItem_Players: SetLongFilter(DatItem_Players, value, negate); break; case Field.DatItem_Coins: SetLongFilter(DatItem_Coins, value, negate); break; // Instance case Field.DatItem_Instance_Name: SetStringFilter(DatItem_Instance_Name, value, negate); break; case Field.DatItem_Instance_BriefName: SetStringFilter(DatItem_Instance_BriefName, value, negate); break; // Location case Field.DatItem_Location_Name: SetStringFilter(DatItem_Location_Name, value, negate); break; case Field.DatItem_Location_Number: SetLongFilter(DatItem_Location_Number, value, negate); break; case Field.DatItem_Location_Inverted: SetBooleanFilter(DatItem_Location_Inverted, value, negate); break; // Part case Field.DatItem_Part_Name: SetStringFilter(DatItem_Part_Name, value, negate); break; case Field.DatItem_Part_Interface: SetStringFilter(DatItem_Part_Interface, value, negate); break; // PartFeature case Field.DatItem_Part_Feature_Name: SetStringFilter(DatItem_Part_Feature_Name, value, negate); break; case Field.DatItem_Part_Feature_Value: SetStringFilter(DatItem_Part_Feature_Value, value, negate); break; // RamOption case Field.DatItem_Content: SetStringFilter(DatItem_Content, value, negate); break; // Release case Field.DatItem_Language: SetStringFilter(DatItem_Language, value, negate); break; // Setting case Field.DatItem_Setting_Name: SetStringFilter(DatItem_Setting_Name, value, negate); break; case Field.DatItem_Setting_Value: SetStringFilter(DatItem_Setting_Value, value, negate); break; case Field.DatItem_Setting_Default: SetBooleanFilter(DatItem_Setting_Default, value, negate); break; // SlotOption case Field.DatItem_SlotOption_Name: SetStringFilter(DatItem_SlotOption_Name, value, negate); break; case Field.DatItem_SlotOption_DeviceName: SetStringFilter(DatItem_SlotOption_DeviceName, value, negate); break; case Field.DatItem_SlotOption_Default: SetBooleanFilter(DatItem_SlotOption_Default, value, negate); break; // SoftwareList case Field.DatItem_SoftwareListStatus: if (negate) DatItem_SoftwareListStatus.Negative |= value.AsSoftwareListStatus(); else DatItem_SoftwareListStatus.Positive |= value.AsSoftwareListStatus(); break; case Field.DatItem_Filter: SetStringFilter(DatItem_Filter, value, negate); break; // Sound case Field.DatItem_Channels: SetLongFilter(DatItem_Channels, value, negate); break; #endregion #endregion // Item-Specific #endregion // DatItem Filters } } /// /// Set a bool? filter /// /// FilterItem to populate /// String value to add /// True to set negative filter, false otherwise private void SetBooleanFilter(FilterItem filterItem, string value, bool negate) { if (negate || value.Equals("false", StringComparison.OrdinalIgnoreCase)) filterItem.Neutral = false; else filterItem.Neutral = true; } /// /// Set a long? filter /// /// FilterItem to populate /// String value to add /// True to set negative filter, false otherwise private void SetDoubleFilter(FilterItem filterItem, string value, bool negate) { bool? operation = null; if (value.StartsWith(">")) operation = true; else if (value.StartsWith("<")) operation = false; else if (value.StartsWith("=")) operation = null; string valueString = value.TrimStart('>', '<', '='); if (!Double.TryParse(valueString, out double valueDouble)) return; // Equal if (operation == null && !negate) { filterItem.Neutral = valueDouble; } // Not Equal else if (operation == null && negate) { filterItem.Negative = valueDouble - 1; filterItem.Positive = valueDouble + 1; } // Greater Than or Equal else if (operation == true && !negate) { filterItem.Positive = valueDouble; } // Strictly Less Than else if (operation == true && negate) { filterItem.Negative = valueDouble - 1; } // Less Than or Equal else if (operation == false && !negate) { filterItem.Negative = valueDouble; } // Strictly Greater Than else if (operation == false && negate) { filterItem.Positive = valueDouble + 1; } } /// /// Set a long? filter /// /// FilterItem to populate /// String value to add /// True to set negative filter, false otherwise private void SetLongFilter(FilterItem filterItem, string value, bool negate) { bool? operation = null; if (value.StartsWith(">")) operation = true; else if (value.StartsWith("<")) operation = false; else if (value.StartsWith("=")) operation = null; string valueString = value.TrimStart('>', '<', '='); if (!Int64.TryParse(valueString, out long valueLong)) return; // Equal if (operation == null && !negate) { filterItem.Neutral = valueLong; } // Not Equal else if (operation == null && negate) { filterItem.Negative = valueLong - 1; filterItem.Positive = valueLong + 1; } // Greater Than or Equal else if (operation == true && !negate) { filterItem.Positive = valueLong; } // Strictly Less Than else if (operation == true && negate) { filterItem.Negative = valueLong - 1; } // Less Than or Equal else if (operation == false && !negate) { filterItem.Negative = valueLong; } // Strictly Greater Than else if (operation == false && negate) { filterItem.Positive = valueLong + 1; } } /// /// Set a string filter /// /// FilterItem to populate /// String value to add /// True to set negative filter, false otherwise private void SetStringFilter(FilterItem filterItem, string value, bool negate) { if (negate) filterItem.NegativeSet.Add(value); else filterItem.PositiveSet.Add(value); } #endregion #region Filter Running /// /// Determines if a value passes a bool? filter /// /// Filter item to check /// Value to check /// True if the value passes, false otherwise public bool PassBoolFilter(FilterItem filterItem, bool? value) { if (filterItem.MatchesNeutral(null, value) == false) return false; return true; } /// /// Determines if a value passes a double? filter /// /// Filter item to check /// Value to check /// True if the value passes, false otherwise public bool PassDoubleFilter(FilterItem filterItem, double? value) { if (filterItem.MatchesNeutral(null, value) == false) return false; else if (filterItem.MatchesPositive(null, value) == false) return false; else if (filterItem.MatchesNegative(null, value) == false) return false; return true; } /// /// Determines if a value passes a long? filter /// /// Filter item to check /// Value to check /// True if the value passes, false otherwise public bool PassLongFilter(FilterItem filterItem, long? value) { if (filterItem.MatchesNeutral(null, value) == false) return false; else if (filterItem.MatchesPositive(null, value) == false) return false; else if (filterItem.MatchesNegative(null, value) == false) return false; return true; } /// /// Determines if a value passes a string filter /// /// Filter item to check /// Value to check /// True if the value passes, false otherwise public bool PassStringFilter(FilterItem filterItem, string value) { if (filterItem.MatchesPositiveSet(value) == false) return false; if (filterItem.MatchesNegativeSet(value) == true) return false; return true; } #endregion #endregion // Instance Methods } }