using System; using System.Collections.Generic; using System.Text.RegularExpressions; namespace SabreTools.Library.DatFiles { /// /// Represents a single filter within the overall filter /// /// Generic type representing the filtered object public class FilterItem { /// /// Single positive value for this filter /// public T Positive { get; set; } /// /// List of positive values for this filter /// public List PositiveSet { get; set; } = new List(); /// /// Single negative value for this filter /// public T Negative { get; set; } /// /// List of negative values for this filter /// public List NegativeSet { get; set; } = new List(); /// /// Single neutral value for this filter /// public T Neutral { get; set; } /// /// List of neutral values for this filter /// public List NeutralSet { get; set; } = new List(); /// /// Check if a value matches the positive filter /// /// Default value to check filter value /// Value to check /// True if the value was found in the positive filter, null on default value, false otherwise public bool? MatchesPositive(T def, T value) { return Matches(this.Positive, def, value); } /// /// Check if a value matches the negative filter /// /// Default value to check filter value /// Value to check /// True if the value was found in the negative filter, null on default value, false otherwise public bool? MatchesNegative(T def, T value) { return Matches(this.Negative, def, value); } /// /// Check if a value matches the neutral filter /// /// Default value to check filter value /// Value to check /// True if the value was found in the neutral filter, null on default value, false otherwise public bool? MatchesNeutral(T def, T value) { return Matches(this.Neutral, def, value); } /// /// Check if the given value matches any of the positive filters /// /// Value to check /// True if the value was found in a positive filter, null on an empty set, false otherwise public bool? MatchesPositiveSet(T value) { return MatchesSet(this.PositiveSet, value); } /// /// Check if the given value matches any of the negative filters /// /// Value to check /// True if the value was found in a negative filter, null on an empty set, false otherwise public bool? MatchesNegativeSet(T value) { return MatchesSet(this.NegativeSet, value); } /// /// Check if the given value matches any of the neutral filters /// /// Value to check /// True if the value was found in a neutral filter, null on an empty set, false otherwise public bool? MatchesNeutralSet(T value) { return MatchesSet(this.NeutralSet, value); } /// /// Check if a value matches the supplied filter /// /// Value to check against /// Default value to check filter value /// Value to check /// True if the value was found in the supplied filter, null on default value, false otherwise private bool? Matches(T single, T def, T value) { // If the filter is default, we ignore if (single.Equals(def)) return null; // If we have a flag if (typeof(T).IsEnum && (single as Enum).HasFlag(value as Enum)) return true; return single.Equals(value); } /// /// Check if a value matches the supplied filter /// /// Set to check against /// Value to check /// True if the value was found in the supplied filter, null on an empty set, false otherwise private bool? MatchesSet(List set, T value) { if (set.Count == 0) return null; if (this.FindValueInList(set, value)) return true; return false; } /// /// 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, T needle) { bool found = false; foreach (T straw in haystack) { if (straw is string) { string needleString = needle as string; string strawString = straw as string; if (!string.IsNullOrWhiteSpace(strawString) && needleString != null) { string regexStraw = strawString; // If the straw has no special characters at all (excluding whitespace), treat it as an exact match if (regexStraw == Regex.Escape(regexStraw).Replace("\\ ", " ")) regexStraw = $"^{regexStraw}$"; // Check if a match is found with the regex found |= Regex.IsMatch(needleString, regexStraw, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); } } else { found |= (needle.Equals(straw)); } } return found; } } }