using System; using System.Collections.Generic; using SabreTools.Logging; namespace SabreTools.Filtering { /// /// Represents the filtering operations that need to be performed on a set of items, usually a DAT /// public abstract class Filter { #region Logging /// /// Logging object /// protected Logger logger; #endregion #region Constructors /// /// Constructor /// public Filter() { logger = new Logger(this); } #endregion #region Filter Population /// /// Split the parts of a filter statement /// /// key:value where ~key/!key is negated protected (string field, string value, bool negate) ProcessFilterPair(string filter) { // If we don't even have a possible filter pair if (!filter.Contains(":")) { logger.Warning($"'{filter}` 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."); return (null, null, false); } string filterTrimmed = filter.Trim('"', ' ', '\t'); bool negate = filterTrimmed.StartsWith("!") || filterTrimmed.StartsWith("~") || filterTrimmed.StartsWith("not-"); filterTrimmed = filterTrimmed.TrimStart('!', '~'); filterTrimmed = filterTrimmed.StartsWith("not-") ? filterTrimmed[4..] : filterTrimmed; string filterFieldString = filterTrimmed.Split(':')[0].ToLowerInvariant().Trim('"', ' ', '\t'); string filterValue = filterTrimmed[(filterFieldString.Length + 1)..].Trim('"', ' ', '\t'); return (filterFieldString, filterValue, negate); } /// /// Set a bool? filter /// /// FilterItem to populate /// String value to add /// True to set negative filter, false otherwise protected 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 protected 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 protected 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 protected 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 static 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 static 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 static 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 static bool PassStringFilter(FilterItem filterItem, string value) { if (filterItem.MatchesPositiveSet(value) == false) return false; if (filterItem.MatchesNegativeSet(value) == true) return false; return true; } #endregion } }