using System.Collections.Generic; using SabreTools.Core; using SabreTools.Core.Tools; using SabreTools.Logging; namespace SabreTools.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? /// TODO: Investigate how to reduce the amount of hardcoded filter statements public class DatItemFilter : Filter { #region Fields #region Common public FilterItem Type { get; private set; } = new FilterItem(); #endregion #region Item-Specific #region Actionable // Rom public FilterItem Name { get; private set; } = new FilterItem(); public FilterItem Bios { get; private set; } = new FilterItem(); public FilterItem Size { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem CRC { get; private set; } = new FilterItem(); public FilterItem MD5 { get; private set; } = new FilterItem(); #if NET_FRAMEWORK public FilterItem RIPEMD160 { get; private set; } = new FilterItem(); #endif public FilterItem SHA1 { get; private set; } = new FilterItem(); public FilterItem SHA256 { get; private set; } = new FilterItem(); public FilterItem SHA384 { get; private set; } = new FilterItem(); public FilterItem SHA512 { get; private set; } = new FilterItem(); public FilterItem SpamSum { get; private set; } = new FilterItem(); public FilterItem Merge { get; private set; } = new FilterItem(); public FilterItem Region { get; private set; } = new FilterItem(); public FilterItem Offset { get; private set; } = new FilterItem(); public FilterItem Date { get; private set; } = new FilterItem(); public FilterItem Status { get; private set; } = new FilterItem() { Positive = ItemStatus.NULL, Negative = ItemStatus.NULL }; public FilterItem Optional { get; private set; } = new FilterItem() { Neutral = null }; public FilterItem Inverted { get; private set; } = new FilterItem(); // Rom (AttractMode) public FilterItem AltName { get; private set; } = new FilterItem(); public FilterItem AltTitle { get; private set; } = new FilterItem(); // Rom (OpenMSX) public FilterItem Original { get; private set; } = new FilterItem(); public FilterItem OpenMSXSubType { get; private set; } = new FilterItem() { Positive = Core.OpenMSXSubType.NULL, Negative = Core.OpenMSXSubType.NULL }; public FilterItem OpenMSXType { get; private set; } = new FilterItem(); public FilterItem Remark { get; private set; } = new FilterItem(); public FilterItem Boot { get; private set; } = new FilterItem(); // Rom (SoftwareList) public FilterItem LoadFlag { get; private set; } = new FilterItem() { Positive = Core.LoadFlag.NULL, Negative = Core.LoadFlag.NULL }; public FilterItem Value { get; private set; } = new FilterItem(); // Disk public FilterItem Index { get; private set; } = new FilterItem(); public FilterItem Writable { get; private set; } = new FilterItem() { Neutral = null }; #endregion #region Auxiliary // Adjuster public FilterItem Default { get; private set; } = new FilterItem() { Neutral = null }; // Analog public FilterItem Analog_Mask { get; private set; } = new FilterItem(); // BiosSet public FilterItem Description { get; private set; } = new FilterItem(); // Chip public FilterItem Tag { get; private set; } = new FilterItem(); public FilterItem ChipType { get; private set; } = new FilterItem() { Positive = Core.ChipType.NULL, Negative = Core.ChipType.NULL }; public FilterItem Clock { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; // Condition public FilterItem Mask { get; private set; } = new FilterItem(); public FilterItem Relation { get; private set; } = new FilterItem() { Positive = Core.Relation.NULL, Negative = Core.Relation.NULL }; public FilterItem Condition_Tag { get; private set; } = new FilterItem(); public FilterItem Condition_Mask { get; private set; } = new FilterItem(); public FilterItem Condition_Relation { get; private set; } = new FilterItem() { Positive = Core.Relation.NULL, Negative = Core.Relation.NULL }; public FilterItem Condition_Value { get; private set; } = new FilterItem(); // Control public FilterItem Control_Type { get; private set; } = new FilterItem() { Positive = ControlType.NULL, Negative = ControlType.NULL }; public FilterItem Control_Player { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem Control_Buttons { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem Control_ReqButtons { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem Control_Minimum { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem Control_Maximum { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem Control_Sensitivity { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem Control_KeyDelta { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem Control_Reverse { get; private set; } = new FilterItem() { Neutral = null }; public FilterItem Control_Ways { get; private set; } = new FilterItem(); public FilterItem Control_Ways2 { get; private set; } = new FilterItem(); public FilterItem Control_Ways3 { get; private set; } = new FilterItem(); // DataArea public FilterItem AreaName { get; private set; } = new FilterItem(); public FilterItem AreaSize { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem AreaWidth { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem AreaEndianness { get; private set; } = new FilterItem() { Positive = Endianness.NULL, Negative = Endianness.NULL }; // Device public FilterItem DeviceType { get; private set; } = new FilterItem() { Positive = Core.DeviceType.NULL, Negative = Core.DeviceType.NULL }; public FilterItem FixedImage { get; private set; } = new FilterItem(); public FilterItem Mandatory { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem Interface { get; private set; } = new FilterItem(); // Display public FilterItem DisplayType { get; private set; } = new FilterItem() { Positive = Core.DisplayType.NULL, Negative = Core.DisplayType.NULL }; public FilterItem Rotate { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem FlipX { get; private set; } = new FilterItem() { Neutral = null }; public FilterItem Width { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem Height { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem Refresh { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem PixClock { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem HTotal { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem HBEnd { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem HBStart { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem VTotal { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem VBEnd { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem VBStart { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; // Driver public FilterItem SupportStatus { get; private set; } = new FilterItem() { Positive = Core.SupportStatus.NULL, Negative = Core.SupportStatus.NULL }; public FilterItem EmulationStatus { get; private set; } = new FilterItem() { Positive = Core.SupportStatus.NULL, Negative = Core.SupportStatus.NULL }; public FilterItem CocktailStatus { get; private set; } = new FilterItem() { Positive = Core.SupportStatus.NULL, Negative = Core.SupportStatus.NULL }; public FilterItem SaveStateStatus { get; private set; } = new FilterItem() { Positive = Supported.NULL, Negative = Supported.NULL }; // Extension public FilterItem Extension_Name { get; private set; } = new FilterItem(); // Feature public FilterItem FeatureType { get; private set; } = new FilterItem() { Positive = Core.FeatureType.NULL, Negative = Core.FeatureType.NULL }; public FilterItem FeatureStatus { get; private set; } = new FilterItem() { Positive = Core.FeatureStatus.NULL, Negative = Core.FeatureStatus.NULL }; public FilterItem FeatureOverall { get; private set; } = new FilterItem() { Positive = Core.FeatureStatus.NULL, Negative = Core.FeatureStatus.NULL }; // Input public FilterItem Service { get; private set; } = new FilterItem() { Neutral = null }; public FilterItem Tilt { get; private set; } = new FilterItem() { Neutral = null }; public FilterItem Players { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem Coins { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; // Instance public FilterItem Instance_Name { get; private set; } = new FilterItem(); public FilterItem Instance_BriefName { get; private set; } = new FilterItem(); // Location public FilterItem Location_Name { get; private set; } = new FilterItem(); public FilterItem Location_Number { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; public FilterItem Location_Inverted { get; private set; } = new FilterItem() { Neutral = null }; // Part public FilterItem Part_Name { get; private set; } = new FilterItem(); public FilterItem Part_Interface { get; private set; } = new FilterItem(); // PartFeature public FilterItem Part_Feature_Name { get; private set; } = new FilterItem(); public FilterItem Part_Feature_Value { get; private set; } = new FilterItem(); // RamOption public FilterItem Content { get; private set; } = new FilterItem(); // Release public FilterItem Language { get; private set; } = new FilterItem(); // Setting public FilterItem Setting_Name { get; private set; } = new FilterItem(); public FilterItem Setting_Value { get; private set; } = new FilterItem(); public FilterItem Setting_Default { get; private set; } = new FilterItem() { Neutral = null }; // SlotOption public FilterItem SlotOption_Name { get; private set; } = new FilterItem(); public FilterItem SlotOption_DeviceName { get; private set; } = new FilterItem(); public FilterItem SlotOption_Default { get; private set; } = new FilterItem() { Neutral = null }; // SoftwareList public FilterItem SoftwareListStatus { get; private set; } = new FilterItem() { Positive = Core.SoftwareListStatus.NULL, Negative = Core.SoftwareListStatus.NULL }; public FilterItem Filter { get; private set; } = new FilterItem(); // Sound public FilterItem Channels { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null }; #endregion #endregion // Item-Specific #endregion // Fields #region Constructors /// /// Constructor /// public DatItemFilter() { 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 override void PopulateFromList(List filters) { foreach (string filterPair in filters) { (string field, string value, bool negate) = ProcessFilterPair(filterPair); // If we don't even have a possible filter pair if (field == null && value == null) continue; DatItemField filterField = field.AsDatItemField(); SetFilter(filterField, value, 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(DatItemField 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(DatItemField key, string value, bool negate) { switch (key) { #region Common case DatItemField.Type: if (value.AsItemType() == null) return; SetStringFilter(Type, value, negate); break; #endregion #region Item-Specific #region Actionable // Rom case DatItemField.Name: SetStringFilter(Name, value, negate); break; case DatItemField.Bios: SetStringFilter(Bios, value, negate); break; case DatItemField.Size: SetLongFilter(Size, value, negate); break; case DatItemField.CRC: SetStringFilter(CRC, value, negate); break; case DatItemField.MD5: SetStringFilter(MD5, value, negate); break; #if NET_FRAMEWORK case DatItemField.RIPEMD160: SetStringFilter(RIPEMD160, value, negate); break; #endif case DatItemField.SHA1: SetStringFilter(SHA1, value, negate); break; case DatItemField.SHA256: SetStringFilter(SHA256, value, negate); break; case DatItemField.SHA384: SetStringFilter(SHA384, value, negate); break; case DatItemField.SHA512: SetStringFilter(SHA512, value, negate); break; case DatItemField.SpamSum: SetStringFilter(SpamSum, value, negate); break; case DatItemField.Merge: SetStringFilter(Merge, value, negate); break; case DatItemField.Region: SetStringFilter(Region, value, negate); break; case DatItemField.Offset: SetStringFilter(Offset, value, negate); break; case DatItemField.Date: SetStringFilter(Date, value, negate); break; case DatItemField.Status: if (negate) Status.Negative |= value.AsItemStatus(); else Status.Positive |= value.AsItemStatus(); break; case DatItemField.Optional: SetBooleanFilter(Optional, value, negate); break; case DatItemField.Inverted: SetBooleanFilter(Inverted, value, negate); break; // Rom (AttractMode) case DatItemField.AltName: SetStringFilter(AltName, value, negate); break; case DatItemField.AltTitle: SetStringFilter(AltTitle, value, negate); break; // Rom (OpenMSX) case DatItemField.Original: SetStringFilter(Original, value, negate); break; case DatItemField.OpenMSXSubType: if (negate) OpenMSXSubType.Negative |= value.AsOpenMSXSubType(); else OpenMSXSubType.Positive |= value.AsOpenMSXSubType(); break; case DatItemField.OpenMSXType: SetStringFilter(OpenMSXType, value, negate); break; case DatItemField.Remark: SetStringFilter(Remark, value, negate); break; case DatItemField.Boot: SetStringFilter(Boot, value, negate); break; // Rom (SoftwareList) case DatItemField.LoadFlag: if (negate) LoadFlag.Negative |= value.AsLoadFlag(); else LoadFlag.Positive |= value.AsLoadFlag(); break; case DatItemField.Value: SetStringFilter(Value, value, negate); break; // Disk case DatItemField.Index: SetStringFilter(Index, value, negate); break; case DatItemField.Writable: SetBooleanFilter(Writable, value, negate); break; #endregion #region Auxiliary // Adjuster case DatItemField.Default: SetBooleanFilter(Default, value, negate); break; // Analog case DatItemField.Analog_Mask: SetStringFilter(Analog_Mask, value, negate); break; // BiosSet case DatItemField.Description: SetStringFilter(Description, value, negate); break; // Chip case DatItemField.Tag: SetStringFilter(Tag, value, negate); break; case DatItemField.ChipType: if (negate) ChipType.Negative |= value.AsChipType(); else ChipType.Positive |= value.AsChipType(); break; case DatItemField.Clock: SetLongFilter(Clock, value, negate); break; // Condition case DatItemField.Mask: SetStringFilter(Mask, value, negate); break; case DatItemField.Relation: if (negate) Relation.Negative |= value.AsRelation(); else Relation.Positive |= value.AsRelation(); break; case DatItemField.Condition_Tag: SetStringFilter(Condition_Tag, value, negate); break; case DatItemField.Condition_Mask: SetStringFilter(Condition_Mask, value, negate); break; case DatItemField.Condition_Relation: if (negate) Condition_Relation.Negative |= value.AsRelation(); else Condition_Relation.Positive |= value.AsRelation(); break; case DatItemField.Condition_Value: SetStringFilter(Condition_Value, value, negate); break; // Control case DatItemField.Control_Type: if (negate) Control_Type.Negative |= value.AsControlType(); else Control_Type.Positive |= value.AsControlType(); break; case DatItemField.Control_Player: SetLongFilter(Control_Player, value, negate); break; case DatItemField.Control_Buttons: SetLongFilter(Control_Buttons, value, negate); break; case DatItemField.Control_RequiredButtons: SetLongFilter(Control_ReqButtons, value, negate); break; case DatItemField.Control_Minimum: SetLongFilter(Control_Minimum, value, negate); break; case DatItemField.Control_Maximum: SetLongFilter(Control_Maximum, value, negate); break; case DatItemField.Control_Sensitivity: SetLongFilter(Control_Sensitivity, value, negate); break; case DatItemField.Control_KeyDelta: SetLongFilter(Control_KeyDelta, value, negate); break; case DatItemField.Control_Reverse: SetBooleanFilter(Control_Reverse, value, negate); break; case DatItemField.Control_Ways: SetStringFilter(Control_Ways, value, negate); break; case DatItemField.Control_Ways2: SetStringFilter(Control_Ways2, value, negate); break; case DatItemField.Control_Ways3: SetStringFilter(Control_Ways3, value, negate); break; // DataArea case DatItemField.AreaName: SetStringFilter(AreaName, value, negate); break; case DatItemField.AreaSize: SetLongFilter(AreaSize, value, negate); break; case DatItemField.AreaWidth: SetLongFilter(AreaWidth, value, negate); break; case DatItemField.AreaEndianness: if (negate) AreaEndianness.Negative |= value.AsEndianness(); else AreaEndianness.Positive |= value.AsEndianness(); break; // Device case DatItemField.DeviceType: if (negate) DeviceType.Negative |= value.AsDeviceType(); else DeviceType.Positive |= value.AsDeviceType(); break; case DatItemField.FixedImage: SetStringFilter(FixedImage, value, negate); break; case DatItemField.Mandatory: SetLongFilter(Mandatory, value, negate); break; case DatItemField.Interface: SetStringFilter(Interface, value, negate); break; // Display case DatItemField.DisplayType: if (negate) DisplayType.Negative |= value.AsDisplayType(); else DisplayType.Positive |= value.AsDisplayType(); break; case DatItemField.Rotate: SetLongFilter(Rotate, value, negate); break; case DatItemField.FlipX: SetBooleanFilter(FlipX, value, negate); break; case DatItemField.Width: SetLongFilter(Width, value, negate); break; case DatItemField.Height: SetLongFilter(Height, value, negate); break; case DatItemField.Refresh: SetDoubleFilter(Refresh, value, negate); break; case DatItemField.PixClock: SetLongFilter(PixClock, value, negate); break; case DatItemField.HTotal: SetLongFilter(HTotal, value, negate); break; case DatItemField.HBEnd: SetLongFilter(HBEnd, value, negate); break; case DatItemField.HBStart: SetLongFilter(HBStart, value, negate); break; case DatItemField.VTotal: SetLongFilter(VTotal, value, negate); break; case DatItemField.VBEnd: SetLongFilter(VBEnd, value, negate); break; case DatItemField.VBStart: SetLongFilter(VBStart, value, negate); break; // Driver case DatItemField.SupportStatus: if (negate) SupportStatus.Negative |= value.AsSupportStatus(); else SupportStatus.Positive |= value.AsSupportStatus(); break; case DatItemField.EmulationStatus: if (negate) EmulationStatus.Negative |= value.AsSupportStatus(); else EmulationStatus.Positive |= value.AsSupportStatus(); break; case DatItemField.CocktailStatus: if (negate) CocktailStatus.Negative |= value.AsSupportStatus(); else CocktailStatus.Positive |= value.AsSupportStatus(); break; case DatItemField.SaveStateStatus: if (negate) SaveStateStatus.Negative |= value.AsSupported(); else SaveStateStatus.Positive |= value.AsSupported(); break; // Extension case DatItemField.Extension_Name: SetStringFilter(Extension_Name, value, negate); break; // Feature case DatItemField.FeatureType: if (negate) FeatureType.Negative |= value.AsFeatureType(); else FeatureType.Positive |= value.AsFeatureType(); break; case DatItemField.FeatureStatus: if (negate) FeatureStatus.Negative |= value.AsFeatureStatus(); else FeatureStatus.Positive |= value.AsFeatureStatus(); break; case DatItemField.FeatureOverall: if (negate) FeatureOverall.Negative |= value.AsFeatureStatus(); else FeatureOverall.Positive |= value.AsFeatureStatus(); break; // Input case DatItemField.Service: SetBooleanFilter(Service, value, negate); break; case DatItemField.Tilt: SetBooleanFilter(Tilt, value, negate); break; case DatItemField.Players: SetLongFilter(Players, value, negate); break; case DatItemField.Coins: SetLongFilter(Coins, value, negate); break; // Instance case DatItemField.Instance_Name: SetStringFilter(Instance_Name, value, negate); break; case DatItemField.Instance_BriefName: SetStringFilter(Instance_BriefName, value, negate); break; // Location case DatItemField.Location_Name: SetStringFilter(Location_Name, value, negate); break; case DatItemField.Location_Number: SetLongFilter(Location_Number, value, negate); break; case DatItemField.Location_Inverted: SetBooleanFilter(Location_Inverted, value, negate); break; // Part case DatItemField.Part_Name: SetStringFilter(Part_Name, value, negate); break; case DatItemField.Part_Interface: SetStringFilter(Part_Interface, value, negate); break; // PartFeature case DatItemField.Part_Feature_Name: SetStringFilter(Part_Feature_Name, value, negate); break; case DatItemField.Part_Feature_Value: SetStringFilter(Part_Feature_Value, value, negate); break; // RamOption case DatItemField.Content: SetStringFilter(Content, value, negate); break; // Release case DatItemField.Language: SetStringFilter(Language, value, negate); break; // Setting case DatItemField.Setting_Name: SetStringFilter(Setting_Name, value, negate); break; case DatItemField.Setting_Value: SetStringFilter(Setting_Value, value, negate); break; case DatItemField.Setting_Default: SetBooleanFilter(Setting_Default, value, negate); break; // SlotOption case DatItemField.SlotOption_Name: SetStringFilter(SlotOption_Name, value, negate); break; case DatItemField.SlotOption_DeviceName: SetStringFilter(SlotOption_DeviceName, value, negate); break; case DatItemField.SlotOption_Default: SetBooleanFilter(SlotOption_Default, value, negate); break; // SoftwareList case DatItemField.SoftwareListStatus: if (negate) SoftwareListStatus.Negative |= value.AsSoftwareListStatus(); else SoftwareListStatus.Positive |= value.AsSoftwareListStatus(); break; case DatItemField.Filter: SetStringFilter(Filter, value, negate); break; // Sound case DatItemField.Channels: SetLongFilter(Channels, value, negate); break; #endregion #endregion // Item-Specific } } #endregion } }